Example #1
0
/*!
 * \brief This method creates a MockDataSourceTransactor
 * \return Returns a mocked DataSourceTransactor that has the required behavior for unittests
 */
te::da::MockDataSourceTransactor* createMockDataSourceTransactor()
{
  te::da::MockDataSourceTransactor* mockDataSourceTransactor(new te::da::MockDataSourceTransactor());

  EXPECT_CALL(*mockDataSourceTransactor, createDataSet(::testing::_, ::testing::_)).WillRepeatedly(::testing::Return());
  EXPECT_CALL(*mockDataSourceTransactor, PrimaryKeyPtrReturn()).WillRepeatedly(::testing::Return(new te::da::PrimaryKey()));
  EXPECT_CALL(*mockDataSourceTransactor, execute(::testing::An<const std::string&>())).WillRepeatedly(::testing::Return());
  EXPECT_CALL(*mockDataSourceTransactor, commit()).WillRepeatedly(::testing::Return());
  EXPECT_CALL(*mockDataSourceTransactor, getLastGeneratedId()).WillRepeatedly(::testing::Return(1));
  EXPECT_CALL(*mockDataSourceTransactor, PropertyPtrReturn()).WillRepeatedly(::testing::Return(nullptr));
  EXPECT_CALL(*mockDataSourceTransactor, addPrimaryKey(::testing::An<const std::string&>(), ::testing::_)).WillRepeatedly(::testing::Return());
  EXPECT_CALL(*mockDataSourceTransactor, addForeignKey(::testing::An<const std::string&>(), ::testing::_)).WillRepeatedly(::testing::Return());
  EXPECT_CALL(*mockDataSourceTransactor, escape(::testing::An<const std::string&>())).WillRepeatedly(::testing::Return(""));
  EXPECT_CALL(*mockDataSourceTransactor, isInTransaction()).WillRepeatedly(::testing::Return(false));
  EXPECT_CALL(*mockDataSourceTransactor, begin()).WillRepeatedly(::testing::Return());


  /* Every time the mockDataSourceTransactor object calls a method that returns a DataSet
   * the actualy method called will be the createMockDataSet() that returns a
   * new mocked DataSet.
   * A new mocked object is needed in every call because TerraLib takes ownership from the pointer.
   */
  EXPECT_CALL(*mockDataSourceTransactor, DataSetPtrReturn()).WillRepeatedly(::testing::Invoke(&createMockDataSet));

  return mockDataSourceTransactor;
}
/**
 * Writes updated record to table
 *
 * rel = table handle
 * record = updated record to be written
 *
 */
RC updateRecord(RM_TableData *rel, Record *record) {

	Value* val;
	bool pk = false;

	//Sanity Checks
	if (rel == NULL) {
		THROW(RC_INVALID_HANDLE, "Table handle is invalid");
	}

	if (record == NULL) {
		THROW(RC_INVALID_HANDLE, "Record handle is invalid");
	}

	// Check if this table has primary key defined
	if (rel->schema->keySize == 1) {
		pk = true;
		// ensure pk constraint is not violated
		getAttr(record, rel->schema, rel->schema->keyAttrs[0], &val);
		if (checkIfPKExists(rel->name,
				((RM_TableMgmtData *) rel->mgmtData)->tblNameSize,
				val->v.intV)) {
			// this value already exists
			freeVal(val);
			THROW(RC_DUPLICATE_KEY, "Can not insert duplicate key");
		}
	}

	//Write updated record
	RC rc = writeRecord(rel, record);

	// add the primary key in the index file
	if (pk) {
		addPrimaryKey(rel->name,
				((RM_TableMgmtData *) rel->mgmtData)->tblNameSize, val->v.intV,
				record->id);
		freeVal(val);
	}

	return rc;
}
/**
 * Inserts new record into the table
 *
 * rel = table handle
 * record = record to be inserted
 *
 */
RC insertRecord(RM_TableData *rel, Record *record) {

	Value* val = NULL;
	bool pk = false;

	//Sanity Checks
	if (rel == NULL) {
		THROW(RC_INVALID_HANDLE, "Table handle is invalid");
	}

	if (record == NULL) {
		THROW(RC_INVALID_HANDLE, "Record handle is invalid");
	}

	// Check if this table has primary key defined
	if (rel->schema->keySize == 1) {
		pk = true;
		// ensure pk constraint is not violated
		getAttr(record, rel->schema, rel->schema->keyAttrs[0], &val);
		if (checkIfPKExists(rel->name,
				((RM_TableMgmtData *) rel->mgmtData)->tblNameSize,
				val->v.intV)) {
			// this value already exists
			freeVal(val);
			THROW(RC_DUPLICATE_KEY, "Can not insert duplicate key");
		}
	}

	//Check if all slots in last page are full, if yes, add new page
	if (((RM_TableMgmtData *) rel->mgmtData)->firstFreeSlot.slot
			== ((RM_TableMgmtData *) rel->mgmtData)->slotCapacityPage) {
		//Add new page
		BM_PageHandle *page = (BM_PageHandle *) malloc(sizeof(BM_PageHandle));

		if (page == NULL) {
			THROW(RC_NOT_ENOUGH_MEMORY,
					"Not enough memory available for resource allocation");
		}

		//Request +1th page
		pinPage(((RM_TableMgmtData *) rel->mgmtData)->bPool, page,
				((RM_TableMgmtData *) rel->mgmtData)->pageCount);
		//Mark it dirty
		markDirty(((RM_TableMgmtData *) rel->mgmtData)->bPool, page);
		unpinPage(((RM_TableMgmtData *) rel->mgmtData)->bPool, page);
		free(page);

		((RM_TableMgmtData *) rel->mgmtData)->firstFreeSlot.page =
				((RM_TableMgmtData *) rel->mgmtData)->pageCount++;
		//Point first free slot to first slot in new page
		((RM_TableMgmtData *) rel->mgmtData)->firstFreeSlot.slot = 0;
	}

	//Point new record to first free slot and page available
	record->id.page = ((RM_TableMgmtData *) rel->mgmtData)->firstFreeSlot.page;
	record->id.slot =
			((RM_TableMgmtData *) rel->mgmtData)->firstFreeSlot.slot++;

	//Write new record to its assigned page and slot
	RC rc = writeRecord(rel, record);

	// add the primary key in the index file
	if (pk) {
		//Update primary key index
		addPrimaryKey(rel->name,
				((RM_TableMgmtData *) rel->mgmtData)->tblNameSize, val->v.intV,
				record->id);
		freeVal(val);
	}

	//All OK
	if (rc == RC_OK)
		((RM_TableMgmtData *) rel->mgmtData)->tupleCount++;

	return rc;
}