TEST_F(CatalogTests, TableObject) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); auto table_object = catalog::Catalog::GetInstance()->GetTableObject( "EMP_DB", "department_table", txn); auto index_objects = table_object->GetIndexObjects(); auto column_objects = table_object->GetColumnObjects(); EXPECT_EQ(1, index_objects.size()); EXPECT_EQ(2, column_objects.size()); EXPECT_EQ(table_object->GetTableOid(), column_objects[0]->GetTableOid()); EXPECT_EQ("id", column_objects[0]->GetColumnName()); EXPECT_EQ(0, column_objects[0]->GetColumnId()); EXPECT_EQ(0, column_objects[0]->GetColumnOffset()); EXPECT_EQ(type::TypeId::INTEGER, column_objects[0]->GetColumnType()); EXPECT_TRUE(column_objects[0]->IsInlined()); EXPECT_TRUE(column_objects[0]->IsPrimary()); EXPECT_FALSE(column_objects[0]->IsNotNull()); EXPECT_EQ(table_object->GetTableOid(), column_objects[1]->GetTableOid()); EXPECT_EQ("name", column_objects[1]->GetColumnName()); EXPECT_EQ(1, column_objects[1]->GetColumnId()); EXPECT_EQ(4, column_objects[1]->GetColumnOffset()); EXPECT_EQ(type::TypeId::VARCHAR, column_objects[1]->GetColumnType()); EXPECT_TRUE(column_objects[1]->IsInlined()); EXPECT_FALSE(column_objects[1]->IsPrimary()); EXPECT_FALSE(column_objects[1]->IsNotNull()); txn_manager.CommitTransaction(txn); }
std::shared_ptr<IndexCatalogEntry> IndexCatalog::GetIndexCatalogEntry( concurrency::TransactionContext *txn, const std::string &database_name, const std::string &schema_name, const std::string &index_name) { if (txn == nullptr) { throw CatalogException("Transaction is invalid!"); } // try get from cache auto index_object = txn->catalog_cache.GetCachedIndexObject(database_name, schema_name, index_name); if (index_object) { return index_object; } // cache miss, get from pg_index std::vector<oid_t> column_ids(all_column_ids); oid_t index_offset = IndexId::SKEY_INDEX_NAME; // Index of index_name & schema_name std::vector<type::Value> values; values.push_back( type::ValueFactory::GetVarcharValue(index_name, nullptr).Copy()); values.push_back( type::ValueFactory::GetVarcharValue(schema_name, nullptr).Copy()); auto result_tiles = GetResultWithIndexScan(txn, column_ids, index_offset, values); if (result_tiles->size() == 1 && (*result_tiles)[0]->GetTupleCount() == 1) { auto index_object = std::make_shared<IndexCatalogEntry>((*result_tiles)[0].get()); // fetch all indexes into table object (cannot use the above index object) auto pg_table = Catalog::GetInstance() ->GetSystemCatalogs(database_oid_) ->GetTableCatalog(); auto table_object = pg_table->GetTableCatalogEntry(txn, index_object->GetTableOid()); PELOTON_ASSERT(table_object && table_object->GetTableOid() == index_object->GetTableOid()); return table_object->GetIndexCatalogEntry(index_name); } else { LOG_DEBUG("Found %lu index with name %s", result_tiles->size(), index_name.c_str()); } // return empty object if not found return nullptr; }
TEST_F(CatalogTests, TableObject) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); auto table_object = catalog::Catalog::GetInstance()->GetTableObject( "emp_db", DEFAULT_SCHEMA_NAME, "department_table", txn); auto index_objects = table_object->GetIndexObjects(); auto column_objects = table_object->GetColumnObjects(); EXPECT_EQ(1, index_objects.size()); EXPECT_EQ(2, column_objects.size()); EXPECT_EQ(table_object->GetTableOid(), column_objects[0]->GetTableOid()); EXPECT_EQ("id", column_objects[0]->GetColumnName()); EXPECT_EQ(0, column_objects[0]->GetColumnId()); EXPECT_EQ(0, column_objects[0]->GetColumnOffset()); EXPECT_EQ(type::TypeId::INTEGER, column_objects[0]->GetColumnType()); EXPECT_TRUE(column_objects[0]->IsInlined()); EXPECT_TRUE(column_objects[0]->IsPrimary()); EXPECT_FALSE(column_objects[0]->IsNotNull()); EXPECT_EQ(table_object->GetTableOid(), column_objects[1]->GetTableOid()); EXPECT_EQ("name", column_objects[1]->GetColumnName()); EXPECT_EQ(1, column_objects[1]->GetColumnId()); EXPECT_EQ(4, column_objects[1]->GetColumnOffset()); EXPECT_EQ(type::TypeId::VARCHAR, column_objects[1]->GetColumnType()); EXPECT_TRUE(column_objects[1]->IsInlined()); EXPECT_FALSE(column_objects[1]->IsPrimary()); EXPECT_FALSE(column_objects[1]->IsNotNull()); // update pg_table SET version_oid = 1 where table_name = department_table oid_t department_table_oid = table_object->GetTableOid(); auto pg_table = catalog::Catalog::GetInstance() ->GetSystemCatalogs(table_object->GetDatabaseOid()) ->GetTableCatalog(); bool update_result = pg_table->UpdateVersionId(1, department_table_oid, txn); // get version id after update, invalidate old cache table_object = catalog::Catalog::GetInstance()->GetTableObject( "emp_db", DEFAULT_SCHEMA_NAME, "department_table", txn); uint32_t version_oid = table_object->GetVersionId(); EXPECT_NE(department_table_oid, INVALID_OID); EXPECT_EQ(update_result, true); EXPECT_EQ(version_oid, 1); txn_manager.CommitTransaction(txn); }
// { ----- begin ID methods ----- NS_IMETHODIMP morkTable::GetOid(nsIMdbEnv* mev, mdbOid* outOid) // read object identity { morkEnv* ev = morkEnv::FromMdbEnv(mev); GetTableOid(ev, outOid); return NS_OK; }
/* @brief evict table catalog object from cache * @param table_name * @return true if table_name is found and evicted; false if not found */ bool DatabaseCatalogObject::EvictTableObject(const std::string &table_name, const std::string &schema_name) { std::string key = schema_name + "." + table_name; // find table name from table name cache auto it = table_name_cache.find(key); if (it == table_name_cache.end()) { return false; // table name not found in cache } auto table_object = it->second; PELOTON_ASSERT(table_object); table_name_cache.erase(it); table_objects_cache.erase(table_object->GetTableOid()); return true; }
bool IndexCatalog::DeleteIndex(concurrency::TransactionContext *txn, oid_t database_oid, oid_t index_oid) { oid_t index_offset = IndexId::PRIMARY_KEY; // Index of index_oid std::vector<type::Value> values; values.push_back(type::ValueFactory::GetIntegerValue(index_oid).Copy()); auto index_object = txn->catalog_cache.GetCachedIndexObject(database_oid, index_oid); if (index_object) { auto table_object = txn->catalog_cache.GetCachedTableObject(database_oid, index_object->GetTableOid()); table_object->EvictAllIndexCatalogEntries(); } return DeleteWithIndexScan(txn, index_offset, values); }
/*@brief get all index records from the same table * this function may be useful when calling DropTable * @param table_oid * @param txn TransactionContext * @return a vector of index catalog objects */ const std::unordered_map<oid_t, std::shared_ptr<IndexCatalogEntry>> IndexCatalog::GetIndexCatalogEntries( concurrency::TransactionContext *txn, oid_t table_oid) { if (txn == nullptr) { throw CatalogException("Transaction is invalid!"); } // try get from cache auto pg_table = Catalog::GetInstance() ->GetSystemCatalogs(database_oid_) ->GetTableCatalog(); auto table_object = pg_table->GetTableCatalogEntry(txn, table_oid); PELOTON_ASSERT(table_object && table_object->GetTableOid() == table_oid); auto index_objects = table_object->GetIndexCatalogEntries(true); if (index_objects.empty() == false) return index_objects; // cache miss, get from pg_index std::vector<oid_t> column_ids(all_column_ids); oid_t index_offset = IndexId::SKEY_TABLE_OID; // Index of table_oid std::vector<type::Value> values; values.push_back(type::ValueFactory::GetIntegerValue(table_oid).Copy()); auto result_tiles = GetResultWithIndexScan(txn, column_ids, index_offset, values); for (auto &tile : (*result_tiles)) { for (auto tuple_id : *tile) { auto index_object = std::make_shared<IndexCatalogEntry>(tile.get(), tuple_id); table_object->InsertIndexCatalogEntry(index_object); } } return table_object->GetIndexCatalogEntries(); }
TEST_F(CatalogTests, LayoutCatalogTest) { // This test creates a table, changes its layout. // Create another additional layout. // Ensure that default is not changed. // Drops layout and verifies that the default_layout is reset. // It also queries pg_layout to ensure that the entry is removed. auto db_name = "temp_db"; auto table_name = "temp_table"; auto catalog = catalog::Catalog::GetInstance(); // Create database. auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); EXPECT_EQ(ResultType::SUCCESS, catalog->CreateDatabase(db_name, txn)); // Create table. auto val0 = catalog::Column(type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "val0", true); auto val1 = catalog::Column(type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "val1", true); auto val2 = catalog::Column(type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "val2", true); auto val3 = catalog::Column(type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "val3", true); std::unique_ptr<catalog::Schema> table_schema( new catalog::Schema({val0, val1, val2, val3})); EXPECT_EQ(ResultType::SUCCESS, catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, table_name, std::move(table_schema), txn)); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); auto database_oid = catalog->GetDatabaseObject(db_name, txn)->GetDatabaseOid(); auto table_object = catalog->GetTableObject(db_name, DEFAULT_SCHEMA_NAME, table_name, txn); auto table_oid = table_object->GetTableOid(); auto table = catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, table_name, txn); txn_manager.CommitTransaction(txn); // Change default layout. std::map<oid_t, std::pair<oid_t, oid_t>> default_map; default_map[0] = std::make_pair(0, 0); default_map[1] = std::make_pair(0, 1); default_map[2] = std::make_pair(1, 0); default_map[3] = std::make_pair(1, 1); txn = txn_manager.BeginTransaction(); auto default_layout = catalog->CreateDefaultLayout(database_oid, table_oid, default_map, txn); txn_manager.CommitTransaction(txn); EXPECT_NE(nullptr, default_layout); // Create additional layout. std::map<oid_t, std::pair<oid_t, oid_t>> non_default_map; non_default_map[0] = std::make_pair(0, 0); non_default_map[1] = std::make_pair(0, 1); non_default_map[2] = std::make_pair(1, 0); non_default_map[3] = std::make_pair(1, 1); txn = txn_manager.BeginTransaction(); auto other_layout = catalog->CreateLayout(database_oid, table_oid, non_default_map, txn); txn_manager.CommitTransaction(txn); // Check that the default layout is still the same. EXPECT_NE(*other_layout.get(), table->GetDefaultLayout()); // Drop the default layout. auto default_layout_oid = default_layout->GetOid(); txn = txn_manager.BeginTransaction(); EXPECT_EQ(ResultType::SUCCESS, catalog->DropLayout(database_oid, table_oid, default_layout_oid, txn)); txn_manager.CommitTransaction(txn); // Check that default layout is reset and set to row_store. EXPECT_NE(*default_layout.get(), table->GetDefaultLayout()); EXPECT_TRUE(table->GetDefaultLayout().IsRowStore()); // Query pg_layout to ensure that the entry is dropped txn = txn_manager.BeginTransaction(); auto pg_layout = catalog->GetSystemCatalogs(database_oid)->GetLayoutCatalog(); EXPECT_EQ(nullptr, pg_layout->GetLayoutWithOid(table_oid, default_layout_oid, txn)); // The additional layout must be present in pg_layout auto other_layout_oid = other_layout->GetOid(); EXPECT_EQ( *(other_layout.get()), *(pg_layout->GetLayoutWithOid(table_oid, other_layout_oid, txn).get())); txn_manager.CommitTransaction(txn); // Drop database txn = txn_manager.BeginTransaction(); catalog->DropDatabaseWithName(db_name, txn); txn_manager.CommitTransaction(txn); }