TEST_F(ConstraintsTests, ForeignKeyInsertTest) { // First, initial 2 tables like following // TABLE A -- src table TABLE B -- sink table // int(primary, ref B) int int(primary) int // 0 0 0 0 // 1 0 1 0 // 2 0 2 0 // ..... // 9 0 // create new db auto &manager = catalog::Manager::GetInstance(); oid_t current_db_oid = bridge::Bridge::GetCurrentDatabaseOid(); auto newdb = new storage::Database(current_db_oid); manager.AddDatabase(newdb); auto table_A = TransactionTestsUtil::CreateTable(3, "tableA", 0, 1000, 1000, true); // we wouldn't use table_B later here so we don't save the return value TransactionTestsUtil::CreateTable(10, "tableB", 0, 1001, 1001, true); // add the foreign key constraints for table_A std::unique_ptr<catalog::ForeignKey> foreign_key(new catalog::ForeignKey( 1001, {"id"}, {0}, {"id"}, {0}, 'r', 'c', "THIS_IS_FOREIGN_CONSTRAINT")); table_A->AddForeignKey(foreign_key.get()); auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); // Test1: insert 2 tuple, one of which doesn't follow foreign key constraint // txn0 insert (10,10) --> fail // txn1 insert (9,10) --> success // txn0 commit // txn1 commit { TransactionScheduler scheduler(2, table_A, &txn_manager); scheduler.Txn(0).Insert(10, 10); scheduler.Txn(1).Insert(9, 10); scheduler.Txn(0).Commit(); scheduler.Txn(1).Commit(); scheduler.Run(); EXPECT_TRUE(RESULT_ABORTED == scheduler.schedules[0].txn_result); EXPECT_TRUE(RESULT_SUCCESS == scheduler.schedules[1].txn_result); } // this will also indirectly delete all tables in this database delete newdb; }
void raw_foreign_key_info::CreateForeignkey(void) const { // Get source table, sink table, and database oid oid_t source_table_oid = source_table_id; assert(source_table_oid); oid_t sink_table_oid = sink_table_id; assert(sink_table_oid); oid_t database_oid = Bridge::GetCurrentDatabaseOid(); // get source, sink tables auto &manager = catalog::Manager::GetInstance(); auto source_table = manager.GetTableWithOid(database_oid, source_table_oid); assert(source_table); auto sink_table = manager.GetTableWithOid(database_oid, sink_table_oid); assert(sink_table); // extract column_names std::vector<std::string> sink_column_names; std::vector<std::string> source_column_names; auto source_table_schema = source_table->GetSchema(); auto sink_table_schema = sink_table->GetSchema(); // Populate primary key column names for (auto sink_offset : sink_column_offsets) { catalog::Column column = sink_table_schema->GetColumn(sink_offset - 1); sink_column_names.push_back(column.GetName()); } // Populate source key column names for (auto source_offset : source_column_offsets) { catalog::Column column = source_table_schema->GetColumn(source_offset - 1); source_column_names.push_back(column.GetName()); } catalog::ForeignKey *foreign_key = new catalog::ForeignKey( sink_table_oid, sink_column_names, source_column_names, update_action, delete_action, fk_name); source_table->AddForeignKey(foreign_key); }