/*! * \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; }