From c45dc4853e3e2b4793ff07b435ab5d309dd1b199 Mon Sep 17 00:00:00 2001 From: ksaito7 Date: Tue, 5 Jun 2018 14:25:40 -0400 Subject: [PATCH 01/10] Add pg_constraint catalog table --- src/catalog/catalog.cpp | 325 +++++++++--- src/catalog/column.cpp | 18 +- src/catalog/column_catalog.cpp | 102 ++-- src/catalog/constraint.cpp | 10 +- src/catalog/constraint_catalog.cpp | 478 ++++++++++++++++++ src/catalog/database_catalog.cpp | 17 +- src/catalog/index_catalog.cpp | 45 +- src/catalog/layout_catalog.cpp | 28 +- src/catalog/schema_catalog.cpp | 17 +- src/catalog/system_catalogs.cpp | 14 +- src/catalog/table_catalog.cpp | 128 ++++- src/common/internal_types.cpp | 56 ++ src/executor/create_executor.cpp | 25 +- src/include/catalog/catalog.h | 60 ++- src/include/catalog/catalog_defaults.h | 10 +- src/include/catalog/column.h | 61 ++- src/include/catalog/column_catalog.h | 19 +- src/include/catalog/constraint.h | 48 +- src/include/catalog/constraint_catalog.h | 161 ++++++ src/include/catalog/layout_catalog.h | 3 +- src/include/catalog/schema.h | 16 +- src/include/catalog/system_catalogs.h | 10 + src/include/catalog/table_catalog.h | 23 + src/include/common/internal_types.h | 3 + src/include/storage/data_table.h | 32 +- src/planner/create_plan.cpp | 24 +- src/storage/data_table.cpp | 61 +-- src/storage/database.cpp | 8 +- test/catalog/catalog_test.cpp | 185 ++++++- test/codegen/testing_codegen_util.cpp | 8 +- test/concurrency/testing_transaction_util.cpp | 6 +- test/executor/testing_executor_util.cpp | 16 +- test/statistics/testing_stats_util.cpp | 3 +- 33 files changed, 1682 insertions(+), 338 deletions(-) create mode 100644 src/catalog/constraint_catalog.cpp create mode 100644 src/include/catalog/constraint_catalog.h diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 0759da7d42f..cf479eccfc6 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -13,8 +13,10 @@ #include "catalog/catalog.h" #include "catalog/column_catalog.h" +#include "catalog/constraint_catalog.h" #include "catalog/database_catalog.h" #include "catalog/database_metrics_catalog.h" +#include "catalog/foreign_key.h" #include "catalog/index_catalog.h" #include "catalog/index_metrics_catalog.h" #include "catalog/language_catalog.h" @@ -159,6 +161,28 @@ void Catalog::BootstrapSystemCatalogs(storage::Database *database, CATALOG_SCHEMA_NAME, IndexType::BWTREE, IndexConstraintType::DEFAULT, false, {TableCatalog::ColumnId::DATABASE_OID}, pool_.get(), txn); + system_catalogs->GetIndexCatalog()->InsertIndex( + LAYOUT_CATALOG_PKEY_OID, LAYOUT_CATALOG_NAME "_pkey", LAYOUT_CATALOG_OID, + CATALOG_SCHEMA_NAME, IndexType::BWTREE, IndexConstraintType::PRIMARY_KEY, + true, + {LayoutCatalog::ColumnId::TABLE_OID, LayoutCatalog::ColumnId::LAYOUT_OID}, + pool_.get(), txn); + system_catalogs->GetIndexCatalog()->InsertIndex( + LAYOUT_CATALOG_SKEY0_OID, LAYOUT_CATALOG_NAME "_skey0", LAYOUT_CATALOG_OID, + CATALOG_SCHEMA_NAME, IndexType::BWTREE, IndexConstraintType::DEFAULT, true, + {LayoutCatalog::ColumnId::TABLE_OID}, pool_.get(), txn); + + system_catalogs->GetIndexCatalog()->InsertIndex( + CONSTRAINT_CATALOG_PKEY_OID, CONSTRAINT_CATALOG_NAME "_pkey", + CONSTRAINT_CATALOG_OID, CATALOG_SCHEMA_NAME, IndexType::BWTREE, + IndexConstraintType::PRIMARY_KEY, true, + {ConstraintCatalog::ColumnId::CONSTRAINT_OID}, pool_.get(), txn); + system_catalogs->GetIndexCatalog()->InsertIndex( + CONSTRAINT_CATALOG_SKEY0_OID, CONSTRAINT_CATALOG_NAME "_skey0", + CONSTRAINT_CATALOG_OID, CATALOG_SCHEMA_NAME, IndexType::BWTREE, + IndexConstraintType::DEFAULT, true, + {ConstraintCatalog::ColumnId::TABLE_OID}, pool_.get(), txn); + // Insert records(default + pg_catalog namespace) into pg_namespace system_catalogs->GetSchemaCatalog()->InsertSchema( CATALOG_SCHEMA_OID, CATALOG_SCHEMA_NAME, pool_.get(), txn); @@ -185,6 +209,9 @@ void Catalog::BootstrapSystemCatalogs(storage::Database *database, system_catalogs->GetTableCatalog()->InsertTable( LAYOUT_CATALOG_OID, LAYOUT_CATALOG_NAME, CATALOG_SCHEMA_NAME, database_oid, pool_.get(), txn); + system_catalogs->GetTableCatalog()->InsertTable( + CONSTRAINT_CATALOG_OID, CONSTRAINT_CATALOG_NAME, CATALOG_SCHEMA_NAME, + database_oid, pool_.get(), txn); } void Catalog::Bootstrap() { @@ -363,93 +390,42 @@ ResultType Catalog::CreateTable(const std::string &database_name, // Update pg_table with table info pg_table->InsertTable(table_oid, table_name, schema_name, database_object->GetDatabaseOid(), pool_.get(), txn); + + // Insert column info and constraint info into each catalog oid_t column_id = 0; + std::vector pkey_attrs, unique_attrs; + std::shared_ptr pkey_constraint, unique_constraint; for (const auto &column : table->GetSchema()->GetColumns()) { pg_attribute->InsertColumn(table_oid, column.GetName(), column_id, column.GetOffset(), column.GetType(), - column.IsInlined(), column.GetConstraints(), + column.IsInlined(), column.IsNotNull(), + column.IsDefault(), column.GetDefaultValue(), pool_.get(), txn); - // Create index on unique single column - if (column.IsUnique()) { - std::string col_name = column.GetName(); - std::string index_name = table->GetName() + "_" + col_name + "_UNIQ"; - CreateIndex(database_name, schema_name, table_name, {column_id}, - index_name, true, IndexType::BWTREE, txn); - LOG_DEBUG("Added a UNIQUE index on %s in %s.", col_name.c_str(), - table_name.c_str()); + // Add constraint information into the catalog and create index if need + for (auto constraint : column.GetConstraints()) { + if (constraint->GetType() == ConstraintType::PRIMARY) { + pkey_attrs.push_back(column_id); + pkey_constraint = constraint; + } + else if (constraint->GetType() == ConstraintType::UNIQUE) { + unique_attrs.push_back(column_id); + unique_constraint = constraint; + } + else if (constraint->GetType() != ConstraintType::FOREIGN) { + AddConstraint(database->GetOid(), table_oid, {column_id}, constraint, txn); + } } + column_id++; } - CreatePrimaryIndex(database_object->GetDatabaseOid(), table_oid, schema_name, - txn); - return ResultType::SUCCESS; -} - -/*@brief create primary index on table - * Note that this is a catalog helper function only called within catalog.cpp - * If you want to create index on table outside, call CreateIndex() instead - * @param database_oid the database which the indexed table belongs to - * @param table_oid oid of the table to add index on - * @param schema_name the schema which the indexed table belongs to - * @param txn TransactionContext - * @return TransactionContext ResultType(SUCCESS or FAILURE) - */ -ResultType Catalog::CreatePrimaryIndex(oid_t database_oid, oid_t table_oid, - const std::string &schema_name, - concurrency::TransactionContext *txn) { - LOG_TRACE("Trying to create primary index for table %d", table_oid); - - auto storage_manager = storage::StorageManager::GetInstance(); - auto database = storage_manager->GetDatabaseWithOid(database_oid); - - auto table = database->GetTableWithOid(table_oid); - - std::vector key_attrs; - catalog::Schema *key_schema = nullptr; - index::IndexMetadata *index_metadata = nullptr; - auto schema = table->GetSchema(); - - // Find primary index attributes - int column_idx = 0; - auto &schema_columns = schema->GetColumns(); - for (auto &column : schema_columns) { - if (column.IsPrimary()) { - key_attrs.push_back(column_idx); - } - column_idx++; + if (pkey_attrs.size() > 0) { + AddConstraint(database->GetOid(), table_oid, pkey_attrs, pkey_constraint, txn); + } + if (unique_attrs.size() > 0) { + AddConstraint(database->GetOid(), table_oid, unique_attrs, unique_constraint, txn); } - - if (key_attrs.empty()) return ResultType::FAILURE; - - key_schema = catalog::Schema::CopySchema(schema, key_attrs); - key_schema->SetIndexedColumns(key_attrs); - - std::string index_name = table->GetName() + "_pkey"; - - bool unique_keys = true; - auto pg_index = catalog_map_[database_oid]->GetIndexCatalog(); - oid_t index_oid = pg_index->GetNextOid(); - - index_metadata = new index::IndexMetadata( - index_name, index_oid, table_oid, database_oid, IndexType::BWTREE, - IndexConstraintType::PRIMARY_KEY, schema, key_schema, key_attrs, - unique_keys); - - std::shared_ptr pkey_index( - index::IndexFactory::GetIndex(index_metadata)); - table->AddIndex(pkey_index); - - // put index object into rw_object_set - txn->RecordCreate(database_oid, table_oid, index_oid); - // insert index record into index_catalog(pg_index) table - pg_index->InsertIndex(index_oid, index_name, table_oid, schema_name, - IndexType::BWTREE, IndexConstraintType::PRIMARY_KEY, - unique_keys, key_attrs, pool_.get(), txn); - - LOG_TRACE("Successfully created primary key index '%s' for table '%s'", - index_name.c_str(), table->GetName().c_str()); return ResultType::SUCCESS; } @@ -494,19 +470,23 @@ ResultType Catalog::CreateIndex(const std::string &database_name, throw CatalogException("Can't find table " + schema_name + "." + table_name + " to create index"); + auto pg_index = + catalog_map_[database_object->GetDatabaseOid()]->GetIndexCatalog(); + oid_t index_oid = pg_index->GetNextOid(); IndexConstraintType index_constraint = unique_keys ? IndexConstraintType::UNIQUE : IndexConstraintType::DEFAULT; ResultType success = CreateIndex( database_object->GetDatabaseOid(), table_object->GetTableOid(), key_attrs, - schema_name, index_name, index_type, index_constraint, unique_keys, txn); + schema_name, index_oid, index_name, index_type, index_constraint, + unique_keys, txn); return success; } ResultType Catalog::CreateIndex( oid_t database_oid, oid_t table_oid, const std::vector &key_attrs, - const std::string &schema_name, const std::string &index_name, + const std::string &schema_name, oid_t index_oid, const std::string &index_name, IndexType index_type, IndexConstraintType index_constraint, bool unique_keys, concurrency::TransactionContext *txn, bool is_catalog) { if (txn == nullptr) @@ -535,8 +515,6 @@ ResultType Catalog::CreateIndex( // Passed all checks, now get all index metadata LOG_TRACE("Trying to create index %s on table %d", index_name.c_str(), table_oid); - auto pg_index = catalog_map_[database_oid]->GetIndexCatalog(); - oid_t index_oid = pg_index->GetNextOid(); auto key_schema = catalog::Schema::CopySchema(schema, key_attrs); key_schema->SetIndexedColumns(key_attrs); @@ -553,6 +531,7 @@ ResultType Catalog::CreateIndex( // Put index object into rw_object_set txn->RecordCreate(database_oid, table_oid, index_oid); // Insert index record into pg_index + auto pg_index = catalog_map_[database_oid]->GetIndexCatalog(); pg_index->InsertIndex(index_oid, index_name, table_oid, schema_name, index_type, index_constraint, unique_keys, key_attrs, pool_.get(), txn); @@ -600,6 +579,144 @@ std::shared_ptr Catalog::CreateDefaultLayout( return new_layout; } +//===--------------------------------------------------------------------===// +// ADD FUNCTIONS +//===--------------------------------------------------------------------===// + +/** + * @brief Add a new constraint for a table except for foreign key + * @param database_oid Database to which the table belongs to + * @param table_oid Table to which the constraint has to be added + * @param column_ids Columns that the constraint affects + * @param constraint The new constraint to be registered + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + * note: if add a new foreign key constraint, use AddForeignKeyConstraint + */ +ResultType Catalog::AddConstraint(oid_t database_oid, oid_t table_oid, + const std::vector &column_ids, std::shared_ptr constraint, + concurrency::TransactionContext *txn) { + auto table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn); + auto storage_manager = storage::StorageManager::GetInstance(); + auto table = storage_manager->GetTableWithOid(database_oid, table_oid); + auto schema = table->GetSchema(); + + // If constraint is PRIMARY KEY or UNIQUE, create index + auto index_oid = INVALID_OID; + if (constraint->GetType() == ConstraintType::PRIMARY) { + std::string index_name = table_object->GetTableName() + "_pkey"; + index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); + CreateIndex(database_oid, table_oid, column_ids, table_object->GetSchemaName(), + index_oid, index_name, IndexType::BWTREE, + IndexConstraintType::PRIMARY_KEY, true, txn); + LOG_DEBUG("Added a PRIMARY KEY index in %s.", + table_object->GetTableName().c_str()); + + // set index oid to constraint + constraint->SetIndexOid(index_oid); + + } else if (constraint->GetType() == ConstraintType::UNIQUE) { + // create index for unique + std::stringstream index_name(table->GetName().c_str()); + for (auto column_id : column_ids) + index_name << "_" + schema->GetColumn(column_id).GetName(); + index_name << "_UNIQ"; + index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); + CreateIndex(database_oid, table_oid, column_ids, table_object->GetSchemaName(), + index_oid, index_name.str(), IndexType::BWTREE, + IndexConstraintType::UNIQUE, true, txn); + LOG_DEBUG("Added a UNIQUE index in %s.", + table_object->GetTableName().c_str()); + + // set index oid to constraint + constraint->SetIndexOid(index_oid); + } + + // Insert constraint into pg_constraint + auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); + constraint->SetConstraintOid(pg_constraint->GetNextOid()); + pg_constraint->InsertConstraint(table_oid, column_ids, constraint, + pool_.get(), txn); + + return ResultType::SUCCESS; +} + +/** + * @brief Add a new foreign key constraint for a table + * @param database_oid database to which the table belongs to + * @param src_table_oid table to which the constraint has to be added + * @param src_col_ids Columns that the constraint affects + * @param snk_table_oid sink table + * @param snk_col_ids Columns that limit the source columns + * @param upd_action foreign key constraint action when update + * @param del_action foreign key constraint action when delete + * @param constraint_name constraint name + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + */ +ResultType Catalog::AddForeignKeyConstraint(oid_t database_oid, + oid_t src_table_oid, const std::vector &src_col_ids, + oid_t sink_table_oid, const std::vector &sink_col_ids, + FKConstrActionType upd_action, FKConstrActionType del_action, + const std::string &constraint_name, + concurrency::TransactionContext *txn) { + + auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); + auto constraint_oid = pg_constraint->GetNextOid(); + auto storage_manager = storage::StorageManager::GetInstance(); + auto src_table = + storage_manager->GetTableWithOid(database_oid, src_table_oid); + auto sink_table = + storage_manager->GetTableWithOid(database_oid, sink_table_oid); + + // Create the catalog object and shove it into the table + auto src_fk = new catalog::ForeignKey( + INVALID_OID, sink_table_oid, sink_col_ids, src_col_ids, + upd_action, del_action, constraint_name); + src_table->AddForeignKey(constraint_oid, src_fk); + + // Register FK with the sink table for delete/update actions + auto sink_fk = new catalog::ForeignKey( + src_table_oid, INVALID_OID, sink_col_ids, src_col_ids, + upd_action, del_action, constraint_name); + sink_table->RegisterForeignKeySource(constraint_oid, sink_fk); + + // Add a non-unique index on the source table if needed + auto src_table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(src_table_oid, txn); + auto src_schema = src_table->GetSchema(); + + std::stringstream index_name(src_table_object->GetTableName().c_str()); + for (auto col_id : src_col_ids) + index_name << "_" << src_schema->GetColumn(col_id).GetName(); + index_name << "_fkey"; + oid_t index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); + CreateIndex(database_oid, src_table_oid, src_col_ids, + src_table_object->GetSchemaName(), index_oid, index_name.str(), + IndexType::BWTREE, IndexConstraintType::DEFAULT, false, txn); + + // Insert constraint into pg_constraint + std::shared_ptr constraint( + new Constraint(ConstraintType::FOREIGN, constraint_name, index_oid)); + constraint->SetConstraintOid(constraint_oid); + ForeignKey fk(src_table_oid, sink_table_oid, sink_col_ids, src_col_ids, + upd_action, del_action, constraint_name); + pg_constraint->InsertConstraint(src_table_oid, src_col_ids, constraint, + fk, pool_.get(), txn); + + // add constraint into schema in source table + { + std::lock_guard lock(catalog_mutex); + for (auto fk_column : src_col_ids) { + src_schema->AddConstraint(fk_column, constraint); + } + } + + return ResultType::SUCCESS; +} + + //===----------------------------------------------------------------------===// // DROP FUNCTIONS //===----------------------------------------------------------------------===// @@ -754,6 +871,11 @@ ResultType Catalog::DropTable(oid_t database_oid, oid_t table_oid, pg_trigger->DropTrigger(database_oid, table_oid, trigger_lists->Get(i)->GetTriggerName(), txn); + // delete record in pg_constraint + auto pg_constraint = + catalog_map_[database_object->GetDatabaseOid()]->GetConstraintCatalog(); + pg_constraint->DeleteConstraints(table_oid, txn); + // delete index and records pg_index for (auto it : index_objects) DropIndex(database_oid, it.second->GetIndexOid(), txn); @@ -836,6 +958,49 @@ ResultType Catalog::DropLayout(oid_t database_oid, oid_t table_oid, return ResultType::SUCCESS; } +/** + * @brief Drop a new foreign key constraint for a table + * @param database_oid the database to which the table belongs to + * @param table_oid the table to which the layout belongs + * @param constraint_oid the constraint to be dropped + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + */ +ResultType Catalog::DropConstraint(oid_t database_oid, oid_t table_oid, + oid_t constraint_oid, + concurrency::TransactionContext *txn) { + auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); + auto constraint_object = + pg_constraint->GetConstraintObject(table_oid, constraint_oid, txn); + + // delete constraint object from pg_constraint + if (!pg_constraint->DeleteConstraint(table_oid, constraint_oid, txn)) { + LOG_DEBUG("Failed to delete the constraint: %d", constraint_oid); + return ResultType::FAILURE; + } + + // delete index if exists + if (constraint_object->GetIndexOid() != INVALID_OID) { + DropIndex(database_oid, constraint_object->GetIndexOid(), txn); + } + + // delete constraint from table + auto storage_manager = storage::StorageManager::GetInstance(); + auto table = storage_manager->GetTableWithOid(database_oid, table_oid); + if (constraint_object->GetConstraintType() == ConstraintType::FOREIGN) { + auto sink_table = storage_manager->GetTableWithOid(database_oid, + constraint_object->GetFKSinkTableOid()); + table->DropForeignKey(constraint_object->GetConstraintOid()); + sink_table->DropForeignKeySrc(constraint_object->GetConstraintOid()); + } + if (!table->GetSchema()->DeleteConstraint(table_oid, constraint_oid)) { + LOG_DEBUG("Failed to delete the constraint: %d", constraint_oid); + return ResultType::FAILURE; + } + + return ResultType::SUCCESS; +} + //===--------------------------------------------------------------------===// // GET WITH NAME - CHECK FROM CATALOG TABLES, USING TRANSACTION //===--------------------------------------------------------------------===// diff --git a/src/catalog/column.cpp b/src/catalog/column.cpp index 50406bef954..2dd10d0b144 100644 --- a/src/catalog/column.cpp +++ b/src/catalog/column.cpp @@ -42,6 +42,22 @@ void Column::SetInlined() { } } +bool Column::DeleteConstraint(oid_t constraint_oid) { + for (auto const_itr = constraints.begin(); const_itr != constraints.end(); + const_itr++) { + if ((*const_itr)->GetConstraintOid() == constraint_oid) { + if ((*const_itr)->GetType() == ConstraintType::PRIMARY) { + is_primary_ = false; + } else if ((*const_itr)->GetType() == ConstraintType::UNIQUE) { + is_unique_ = false; + } + constraints.erase(const_itr); + return true; + } + } + return false; +} + const std::string Column::GetInfo() const { std::ostringstream os; @@ -63,7 +79,7 @@ const std::string Column::GetInfo() const { } else { os << ", "; } - os << constraint.GetInfo(); + os << constraint->GetInfo(); } os << "}"; } diff --git a/src/catalog/column_catalog.cpp b/src/catalog/column_catalog.cpp index 8262ffe479c..5913e8dd642 100644 --- a/src/catalog/column_catalog.cpp +++ b/src/catalog/column_catalog.cpp @@ -39,10 +39,19 @@ ColumnCatalogObject::ColumnCatalogObject(executor::LogicalTile *tile, .ToString())), is_inlined(tile->GetValue(tupleId, ColumnCatalog::ColumnId::IS_INLINED) .GetAs()), - is_primary(tile->GetValue(tupleId, ColumnCatalog::ColumnId::IS_PRIMARY) - .GetAs()), is_not_null(tile->GetValue(tupleId, ColumnCatalog::ColumnId::IS_NOT_NULL) - .GetAs()) {} + .GetAs()), + is_default(tile->GetValue(tupleId, ColumnCatalog::ColumnId::IS_DEFAULT) + .GetAs()) { + // deserialize default value if the column has default constraint + if (is_default) { + std::unique_ptr pool(new type::EphemeralPool()); + auto default_value_str = tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::DEFAULT_VALUE).ToString(); + default_value = type::Value::DeserializeFrom(default_value_str.c_str(), + column_type, is_inlined, pool.get()); + } +} ColumnCatalog::ColumnCatalog(storage::Database *pg_catalog, type::AbstractPool *pool, @@ -53,8 +62,9 @@ ColumnCatalog::ColumnCatalog(storage::Database *pg_catalog, AddIndex({ColumnId::TABLE_OID, ColumnId::COLUMN_NAME}, COLUMN_CATALOG_PKEY_OID, COLUMN_CATALOG_NAME "_pkey", IndexConstraintType::PRIMARY_KEY); - AddIndex({ColumnId::TABLE_OID, ColumnId::COLUMN_ID}, COLUMN_CATALOG_SKEY0_OID, - COLUMN_CATALOG_NAME "_skey0", IndexConstraintType::UNIQUE); + AddIndex({ColumnId::TABLE_OID, ColumnId::COLUMN_ID}, + COLUMN_CATALOG_SKEY0_OID, COLUMN_CATALOG_NAME "_skey0", + IndexConstraintType::UNIQUE); AddIndex({ColumnId::TABLE_OID}, COLUMN_CATALOG_SKEY1_OID, COLUMN_CATALOG_NAME "_skey1", IndexConstraintType::DEFAULT); @@ -63,7 +73,8 @@ ColumnCatalog::ColumnCatalog(storage::Database *pg_catalog, for (auto column : catalog_table_->GetSchema()->GetColumns()) { InsertColumn(COLUMN_CATALOG_OID, column.GetName(), column_id, column.GetOffset(), column.GetType(), column.IsInlined(), - column.GetConstraints(), pool, txn); + column.IsNotNull(), column.IsDefault(), + column.GetDefaultValue(), pool, txn); column_id++; } } @@ -74,58 +85,62 @@ ColumnCatalog::~ColumnCatalog() {} * @return unqiue pointer to schema */ std::unique_ptr ColumnCatalog::InitializeSchema() { - const std::string primary_key_constraint_name = "primary_key"; - const std::string not_null_constraint_name = "not_null"; + const std::string primary_key_constraint_name = "con_primary"; + const std::string unique_constraint_name = "con_unique"; auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.AddConstraint(catalog::Constraint( - ConstraintType::PRIMARY, primary_key_constraint_name)); - table_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + table_id_column.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, primary_key_constraint_name, + COLUMN_CATALOG_PKEY_OID)); + table_id_column.AddConstraint(std::make_shared( + ConstraintType::UNIQUE, unique_constraint_name, + COLUMN_CATALOG_SKEY0_OID)); + table_id_column.SetNotNull(); auto column_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "column_name", false); - column_name_column.AddConstraint(catalog::Constraint( - ConstraintType::PRIMARY, primary_key_constraint_name)); - column_name_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + column_name_column.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, primary_key_constraint_name, + COLUMN_CATALOG_PKEY_OID)); + column_name_column.SetNotNull(); auto column_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "column_id", true); - column_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + column_id_column.AddConstraint(std::make_shared( + ConstraintType::UNIQUE, unique_constraint_name, + COLUMN_CATALOG_SKEY0_OID)); + column_id_column.SetNotNull(); auto column_offset_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "column_offset", true); - column_offset_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + column_offset_column.SetNotNull(); auto column_type_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "column_type", false); - column_type_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + column_type_column.SetNotNull(); auto is_inlined_column = catalog::Column( type::TypeId::BOOLEAN, type::Type::GetTypeSize(type::TypeId::BOOLEAN), "is_inlined", true); - is_inlined_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + is_inlined_column.SetNotNull(); auto is_primary_column = catalog::Column( type::TypeId::BOOLEAN, type::Type::GetTypeSize(type::TypeId::BOOLEAN), - "is_primary", true); - is_primary_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + "is_not_null", true); + is_primary_column.SetNotNull(); auto is_not_null_column = catalog::Column( type::TypeId::BOOLEAN, type::Type::GetTypeSize(type::TypeId::BOOLEAN), - "is_not_null", true); - is_not_null_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + "is_default", true); + is_not_null_column.SetNotNull(); + + auto default_value_column = catalog::Column( + type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), + "default_value", false); std::unique_ptr column_catalog_schema(new catalog::Schema( {table_id_column, column_name_column, column_id_column, @@ -139,7 +154,8 @@ bool ColumnCatalog::InsertColumn(oid_t table_oid, const std::string &column_name, oid_t column_id, oid_t column_offset, type::TypeId column_type, bool is_inlined, - const std::vector &constraints, + bool is_not_null, bool is_default, + const std::shared_ptr default_value, type::AbstractPool *pool, concurrency::TransactionContext *txn) { // Create the tuple first @@ -153,17 +169,8 @@ bool ColumnCatalog::InsertColumn(oid_t table_oid, auto val4 = type::ValueFactory::GetVarcharValue(TypeIdToString(column_type), nullptr); auto val5 = type::ValueFactory::GetBooleanValue(is_inlined); - bool is_primary = false, is_not_null = false; - for (auto constraint : constraints) { - if (constraint.GetType() == ConstraintType::PRIMARY) { - is_primary = true; - } else if (constraint.GetType() == ConstraintType::NOT_NULL || - constraint.GetType() == ConstraintType::NOTNULL) { - is_not_null = true; - } - } - auto val6 = type::ValueFactory::GetBooleanValue(is_primary); - auto val7 = type::ValueFactory::GetBooleanValue(is_not_null); + auto val6 = type::ValueFactory::GetBooleanValue(is_not_null); + auto val7 = type::ValueFactory::GetBooleanValue(is_default); tuple->SetValue(ColumnId::TABLE_OID, val0, pool); tuple->SetValue(ColumnId::COLUMN_NAME, val1, pool); @@ -171,8 +178,15 @@ bool ColumnCatalog::InsertColumn(oid_t table_oid, tuple->SetValue(ColumnId::COLUMN_OFFSET, val3, pool); tuple->SetValue(ColumnId::COLUMN_TYPE, val4, pool); tuple->SetValue(ColumnId::IS_INLINED, val5, pool); - tuple->SetValue(ColumnId::IS_PRIMARY, val6, pool); - tuple->SetValue(ColumnId::IS_NOT_NULL, val7, pool); + tuple->SetValue(ColumnId::IS_NOT_NULL, val6, pool); + tuple->SetValue(ColumnId::IS_DEFAULT, val7, pool); + + if (is_default) { + char default_value_str[column_length]; + default_value->SerializeTo(default_value_str, is_inlined, pool); + auto val8 = type::ValueFactory::GetVarcharValue(default_value_str, nullptr); + tuple->SetValue(ColumnId::DEFAULT_VALUE, val8, pool); + } // Insert the tuple return InsertTuple(std::move(tuple), txn); diff --git a/src/catalog/constraint.cpp b/src/catalog/constraint.cpp index 01359e7f309..90e79f7fc1d 100644 --- a/src/catalog/constraint.cpp +++ b/src/catalog/constraint.cpp @@ -19,8 +19,14 @@ namespace catalog { const std::string Constraint::GetInfo() const { std::ostringstream os; - os << "Constraint[" << GetName() << ", " - << ConstraintTypeToString(constraint_type); + os << "Constraint[" << GetName() + << "(" << std::to_string(GetConstraintOid()) << "), " + << ConstraintTypeToString(constraint_type) + << ", index_oid:" << std::to_string(index_oid); + + if (GetType() == ConstraintType::DEFAULT) { + os << "," << default_value->GetInfo(); + } if (GetType() == ConstraintType::CHECK) { os << ", " << exp.first << " " << exp.second.GetInfo(); diff --git a/src/catalog/constraint_catalog.cpp b/src/catalog/constraint_catalog.cpp new file mode 100644 index 00000000000..0ed61fdeb4d --- /dev/null +++ b/src/catalog/constraint_catalog.cpp @@ -0,0 +1,478 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// column_catalog.cpp +// +// Identification: src/catalog/column_catalog.cpp +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include "catalog/constraint_catalog.h" + +#include +#include + +#include "catalog/catalog.h" +#include "catalog/foreign_key.h" +#include "catalog/system_catalogs.h" +#include "catalog/table_catalog.h" +#include "concurrency/transaction_context.h" +#include "storage/data_table.h" +#include "storage/database.h" +#include "storage/storage_manager.h" +#include "type/value_factory.h" + +namespace peloton { +namespace catalog { + +ConstraintCatalogObject::ConstraintCatalogObject(executor::LogicalTile *tile, + int tupleId) + : constraint_oid(tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::CONSTRAINT_OID).GetAs()), + constraint_name(tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::CONSTRAINT_NAME).ToString()), + constraint_type(StringToConstraintType(tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::CONSTRAINT_TYPE).ToString())), + table_oid(tile->GetValue(tupleId, ConstraintCatalog::ColumnId::TABLE_OID) + .GetAs()), + index_oid(tile->GetValue(tupleId, ConstraintCatalog::ColumnId::INDEX_OID) + .GetAs()) { + std::string src_column_ids_str = + tile->GetValue(tupleId, ConstraintCatalog::ColumnId::COLUMN_IDS) + .ToString(); + std::stringstream src_ss(src_column_ids_str.c_str()); + std::string src_tok; + while (std::getline(src_ss, src_tok, ' ')) { + column_ids.push_back(std::stoi(src_tok)); + } + + // create values by type of constraint + switch(constraint_type) { + case ConstraintType::PRIMARY: + case ConstraintType::UNIQUE: + case ConstraintType::NOTNULL: + case ConstraintType::NOT_NULL: + // nothing to do more + break; + + case ConstraintType::FOREIGN: { + fk_sink_table_oid = tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::FK_SINK_TABLE_OID).GetAs(); + std::string snk_column_ids_str = tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::FK_SINK_COL_IDS).ToString(); + std::stringstream snk_ss(snk_column_ids_str.c_str()); + std::string snk_tok; + while (std::getline(snk_ss, snk_tok, ' ')) { + fk_sink_col_ids.push_back(std::stoi(snk_tok)); + } + fk_update_action = StringToFKConstrActionType(tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::FK_UPDATE_ACTION).ToString()); + fk_delete_action = StringToFKConstrActionType(tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::FK_DELETE_ACTION).ToString()); + break; + } + + case ConstraintType::DEFAULT: + default_value = tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::DEFAULT_VALUE).ToString(); + break; + + case ConstraintType::CHECK: + check_cmd = tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::CHECK_CMD).ToString(); + check_exp = tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::CHECK_EXP).ToString(); + break; + + case ConstraintType::EXCLUSION: + default: + break; + } +} + +ConstraintCatalog::ConstraintCatalog(storage::Database *pg_catalog, + UNUSED_ATTRIBUTE type::AbstractPool *pool, + UNUSED_ATTRIBUTE concurrency::TransactionContext *txn) + : AbstractCatalog(CONSTRAINT_CATALOG_OID, CONSTRAINT_CATALOG_NAME, + InitializeSchema().release(), pg_catalog) { + // Add indexes for pg_constraint + AddIndex({ColumnId::CONSTRAINT_OID}, + CONSTRAINT_CATALOG_PKEY_OID, CONSTRAINT_CATALOG_NAME "_pkey", + IndexConstraintType::PRIMARY_KEY); + AddIndex({ColumnId::TABLE_OID}, CONSTRAINT_CATALOG_SKEY0_OID, + CONSTRAINT_CATALOG_NAME "_skey0", IndexConstraintType::DEFAULT); +} + +ConstraintCatalog::~ConstraintCatalog() {} + +/*@brief private function for initialize schema of pg_constraint + * @return unqiue pointer to schema + */ +std::unique_ptr ConstraintCatalog::InitializeSchema() { + const std::string primary_key_constraint_name = "primary_key"; + const std::string not_null_constraint_name = "not_null"; + + auto constraint_oid_column = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "constraint_oid", true); + constraint_oid_column.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, primary_key_constraint_name, + CONSTRAINT_CATALOG_PKEY_OID)); + constraint_oid_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); + + auto constraint_name_column = catalog::Column( + type::TypeId::VARCHAR, max_name_size, "constraint_name_", false); + constraint_name_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); + + auto constraint_type_column = catalog::Column( + type::TypeId::VARCHAR, max_name_size, "constraint_type", false); + constraint_type_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); + + auto table_oid_column = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "table_oid", true); + table_oid_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); + + auto column_ids_column = catalog::Column( + type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), + "column_ids", false); + column_ids_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); + + auto index_oid_column = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "index_oid", true); + index_oid_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); + + auto fk_sink_table_oid_column = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "fk_sink_table_oid", true); + + auto fk_sink_col_ids_column = catalog::Column( + type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), + "fk_sink_col_ids", false); + + auto fk_update_action_column = catalog::Column( + type::TypeId::VARCHAR, max_name_size, "fk_update_action", false); + + auto fk_delete_action_column = catalog::Column( + type::TypeId::VARCHAR, max_name_size, "fk_delete_action", false); + + auto default_value_column = catalog::Column( + type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), + "default_value", false); + + auto check_cmd_column = catalog::Column( + type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), + "check_cmd", false); + + auto check_exp_column = catalog::Column( + type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), + "check_exp", false); + + std::unique_ptr column_catalog_schema(new catalog::Schema( + {constraint_oid_column, constraint_name_column, constraint_type_column, + table_oid_column, column_ids_column, index_oid_column, + fk_sink_table_oid_column, fk_sink_col_ids_column, + fk_update_action_column, fk_delete_action_column, default_value_column, + check_cmd_column, check_exp_column})); + + return column_catalog_schema; +} + +/*@brief Insert a constraint into the pg_constraint table + * This targets PRIMARY KEY, UNIQUE, DEFAULt, CHECK or NOT NULL constraint + * @param table_oid oid of the table related to this constraint + * @param column_ids vector of oids of column related to this constraint + * @param constraint to be inserted into pg_constraint + * @param pool to allocate memory for the column_map column. + * @param txn TransactionContext for adding the constraint. + * @return true on success. + */ +bool ConstraintCatalog::InsertConstraint(oid_t table_oid, + const std::vector &column_ids, + const std::shared_ptr constraint, + type::AbstractPool *pool, concurrency::TransactionContext *txn) { + // Check usage + PELOTON_ASSERT(constraint->GetType() != ConstraintType::FOREIGN); + + // Create the tuple first + std::unique_ptr tuple( + new storage::Tuple(catalog_table_->GetSchema(), true)); + + // Common information of constraint + auto val0 = type::ValueFactory::GetIntegerValue(constraint->GetConstraintOid()); + auto val1 = type::ValueFactory::GetVarcharValue(constraint->GetName(), nullptr); + auto val2 = type::ValueFactory::GetVarcharValue( + ConstraintTypeToString(constraint->GetType()), nullptr); + auto val3 = type::ValueFactory::GetIntegerValue(table_oid); + std::stringstream ss; + for (auto column_oid : column_ids) ss << std::to_string(column_oid) << " "; + auto val4 = type::ValueFactory::GetVarcharValue(ss.str(), nullptr); + auto val5 = type::ValueFactory::GetIntegerValue(constraint->GetIndexOid()); + + tuple->SetValue(ColumnId::CONSTRAINT_OID, val0, pool); + tuple->SetValue(ColumnId::CONSTRAINT_NAME, val1, pool); + tuple->SetValue(ColumnId::CONSTRAINT_TYPE, val2, pool); + tuple->SetValue(ColumnId::TABLE_OID, val3, pool); + tuple->SetValue(ColumnId::COLUMN_IDS, val4, pool); + tuple->SetValue(ColumnId::INDEX_OID, val5, pool); + + // create values by type of constraint + switch(constraint->GetType()) { + case ConstraintType::PRIMARY: + case ConstraintType::UNIQUE: + // nothing to do more + // need to set a valid index oid + PELOTON_ASSERT(constraint->GetIndexOid() != INVALID_OID); + break; + + case ConstraintType::NOTNULL: + case ConstraintType::NOT_NULL: + // nothing to do more + break; + + case ConstraintType::DEFAULT: { + // set value of default value + PELOTON_ASSERT(column_ids.size() == 1); + auto column = storage::StorageManager::GetInstance() + ->GetTableWithOid(database_oid, table_oid)->GetSchema() + ->GetColumn(column_ids.at(0)); + char default_value_str[column.GetLength()]; + constraint->getDefaultValue()->SerializeTo(default_value_str, column.IsInlined(), + pool); + auto val6 = type::ValueFactory::GetVarcharValue(default_value_str, nullptr); + + tuple->SetValue(ColumnId::DEFAULT_VALUE, val6, pool); + break; + } + + case ConstraintType::CHECK: { + // set value of check expression + PELOTON_ASSERT(column_ids.size() == 1); + auto val6 = + type::ValueFactory::GetVarcharValue(constraint->GetCheckCmd(), nullptr); + auto exp = constraint->GetCheckExpression(); + auto column = storage::StorageManager::GetInstance() + ->GetTableWithOid(database_oid, table_oid)->GetSchema() + ->GetColumn(column_ids.at(0)); + char exp_value_str[column.GetLength()]; + exp.second.SerializeTo(exp_value_str, column.IsInlined(), pool); + std::stringstream exp_ss; + exp_ss << ExpressionTypeToString(exp.first) << " " << exp_value_str; + auto val7 = type::ValueFactory::GetVarcharValue(exp_ss.str(), nullptr); + + tuple->SetValue(ColumnId::CHECK_CMD, val6, pool); + tuple->SetValue(ColumnId::CHECK_EXP, val7, pool); + break; + } + + case ConstraintType::FOREIGN: + case ConstraintType::EXCLUSION: + default: + // unexpected constraint type + throw CatalogException("Unexpected constraint type '" + + ConstraintTypeToString(constraint->GetType()) + + "' appears in insertion into pg_constraint "); + return false; + } + + + // Insert the tuple + return InsertTuple(std::move(tuple), txn); +} + +/*@brief Insert a constraint into the pg_constraint table + * This targets only FOREIGN KEY constraint + * @param table_oid oid of the table related to this constraint + * @param column_ids vector of oids of column related to this constraint + * @param constraint to be inserted into pg_constraint + * @param foreign_key foreign key information as constraint + * @param pool to allocate memory for the column_map column. + * @param txn TransactionContext for adding the constraint. + * @return true on success. + */ +bool ConstraintCatalog::InsertConstraint(oid_t table_oid, + const std::vector &column_ids, + const std::shared_ptr constraint, + const ForeignKey &foreign_key, type::AbstractPool *pool, + concurrency::TransactionContext *txn) { + // Check usage + PELOTON_ASSERT(constraint->GetType() == ConstraintType::FOREIGN); + PELOTON_ASSERT(constraint->GetIndexOid() != INVALID_OID); + + // Create the tuple first + std::unique_ptr tuple( + new storage::Tuple(catalog_table_->GetSchema(), true)); + + auto val0 = type::ValueFactory::GetIntegerValue(constraint->GetConstraintOid()); + auto val1 = type::ValueFactory::GetVarcharValue(constraint->GetName(), nullptr); + auto val2 = + type::ValueFactory::GetVarcharValue(ConstraintTypeToString(constraint->GetType()), + nullptr); + auto val3 = type::ValueFactory::GetIntegerValue(table_oid); + std::stringstream src_ss; + for (auto column_oid : column_ids) src_ss << std::to_string(column_oid) << " "; + auto val4 = type::ValueFactory::GetVarcharValue(src_ss.str(), nullptr); + auto val5 = type::ValueFactory::GetIntegerValue(constraint->GetIndexOid()); + auto val6 = type::ValueFactory::GetIntegerValue(foreign_key.GetSinkTableOid()); + std::stringstream snk_ss; + for (auto column_oid : foreign_key.GetSinkColumnIds()) + snk_ss << std::to_string(column_oid) << " "; + auto val7 = type::ValueFactory::GetVarcharValue(snk_ss.str(), nullptr); + auto val8 = type::ValueFactory::GetVarcharValue( + FKConstrActionTypeToString(foreign_key.GetUpdateAction()), nullptr); + auto val9 = type::ValueFactory::GetVarcharValue( + FKConstrActionTypeToString(foreign_key.GetDeleteAction()), nullptr); + + tuple->SetValue(ColumnId::CONSTRAINT_OID, val0, pool); + tuple->SetValue(ColumnId::CONSTRAINT_NAME, val1, pool); + tuple->SetValue(ColumnId::CONSTRAINT_TYPE, val2, pool); + tuple->SetValue(ColumnId::TABLE_OID, val3, pool); + tuple->SetValue(ColumnId::COLUMN_IDS, val4, pool); + tuple->SetValue(ColumnId::INDEX_OID, val5, pool); + tuple->SetValue(ColumnId::FK_SINK_TABLE_OID, val6, pool); + tuple->SetValue(ColumnId::FK_SINK_COL_IDS, val7, pool); + tuple->SetValue(ColumnId::FK_UPDATE_ACTION, val8, pool); + tuple->SetValue(ColumnId::FK_DELETE_ACTION, val9, pool); + + // Insert the tuple + return InsertTuple(std::move(tuple), txn); +} + +/* @brief delete all constraint records from the same table + * this function is useful when calling DropTable + * @param table_oid + * @param txn TransactionContext + * @return a vector of table oid + */ +bool ConstraintCatalog::DeleteConstraints(oid_t table_oid, + concurrency::TransactionContext *txn) { + oid_t index_offset = IndexId::SKEY_TABLE_OID; // Index of table_oid + std::vector values; + values.push_back(type::ValueFactory::GetIntegerValue(table_oid).Copy()); + + // delete columns from cache + auto pg_table = Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetTableCatalog(); + auto table_object = pg_table->GetTableObject(table_oid, txn); + table_object->EvictAllConstraintObjects(); + + return DeleteWithIndexScan(index_offset, values, txn); +} + +/** @brief Delete a constraint from the pg_constraint table. + * @param table_oid oid of the table to which the old constraint belongs. + * @param constraint_oid oid of the constraint to be deleted. + * @param txn TransactionContext for deleting the constraint. + * @return true on success. + */ +bool ConstraintCatalog::DeleteConstraint(oid_t table_oid, + oid_t constraint_oid, + concurrency::TransactionContext *txn) { + oid_t index_offset = IndexId::PRIMARY_KEY; // Index of constraint_oid + std::vector values; + values.push_back(type::ValueFactory::GetIntegerValue(constraint_oid).Copy()); + + // delete column from cache + auto pg_table = Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetTableCatalog(); + auto table_object = pg_table->GetTableObject(table_oid, txn); + table_object->EvictConstraintObject(constraint_oid); + + return DeleteWithIndexScan(index_offset, values, txn); +} + +/** @brief Get all constraint objects correponding to a table + * from the pg_constraint. + * @param table_oid oid of the table to fetch all constraints. + * @param txn TransactionContext for getting the constraints. + * @return unordered_map containing a constraint_oid -> + * constraint object mapping. + */ +const std::unordered_map> +ConstraintCatalog::GetConstraintObjects(oid_t table_oid, + concurrency::TransactionContext *txn) { + // try get from cache + auto pg_table = Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetTableCatalog(); + auto table_object = pg_table->GetTableObject(table_oid, txn); + PELOTON_ASSERT(table_object && table_object->GetTableOid() == table_oid); + + auto constraint_objects = table_object->GetConstraintObjects(true); + if (constraint_objects.size() != 0) return constraint_objects; + + // cache miss, get from pg_attribute + std::vector column_ids(all_column_ids); + oid_t index_offset = IndexId::SKEY_TABLE_OID; // Index of table_oid + std::vector values; + values.push_back(type::ValueFactory::GetIntegerValue(table_oid).Copy()); + + auto result_tiles = + GetResultWithIndexScan(column_ids, index_offset, values, txn); + + for (auto &tile : (*result_tiles)) { + for (auto tuple_id : *tile) { + auto constraint_object = + std::make_shared(tile.get(), tuple_id); + table_object->InsertConstraintObject(constraint_object); + } + } + + return table_object->GetConstraintObjects(); +} + +/** @brief Get the constraint object by constraint_oid from + * the pg_constraint. + * @param table_oid oid of the table to fetch the constraint. + * @param constraint_oid oid of the constraint being queried. + * @param txn TransactionContext for getting the constraint. + * @return shared_ptr constraint object to the constraint_oid if found. + * nullptr otherwise. + */ +const std::shared_ptr +ConstraintCatalog::GetConstraintObject(oid_t table_oid, oid_t constraint_oid, + concurrency::TransactionContext *txn) { + // try get from cache + auto pg_table = Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetTableCatalog(); + auto table_object = pg_table->GetTableObject(table_oid, txn); + PELOTON_ASSERT(table_object && table_object->GetTableOid() == table_oid); + + auto constraint_object = + table_object->GetConstraintObject(constraint_oid, true); + if (constraint_object != nullptr) return constraint_object; + + // cache miss, get from pg_attribute + std::vector column_ids(all_column_ids); + oid_t index_offset = IndexId::PRIMARY_KEY; // Index of table_oid + std::vector values; + values.push_back(type::ValueFactory::GetIntegerValue(constraint_oid).Copy()); + + auto result_tiles = + GetResultWithIndexScan(column_ids, index_offset, values, txn); + + if (result_tiles->size() == 1 && (*result_tiles)[0]->GetTupleCount() == 1) { + auto constraint_object = + std::make_shared((*result_tiles)[0].get()); + table_object->InsertConstraintObject(constraint_object); + return constraint_object; + } + + return nullptr; +} + +} // namespace catalog +} // namespace peloton diff --git a/src/catalog/database_catalog.cpp b/src/catalog/database_catalog.cpp index fc0b81c64d0..25267ca6e51 100644 --- a/src/catalog/database_catalog.cpp +++ b/src/catalog/database_catalog.cpp @@ -271,19 +271,24 @@ DatabaseCatalog::~DatabaseCatalog() {} std::unique_ptr DatabaseCatalog::InitializeSchema() { const std::string not_null_constraint_name = "not_null"; const std::string primary_key_constraint_name = "primary_key"; + const std::string unique_constraint_name = "con_unique"; auto database_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "database_oid", true); - database_id_column.AddConstraint(catalog::Constraint( - ConstraintType::PRIMARY, primary_key_constraint_name)); - database_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + database_id_column.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, primary_key_constraint_name, + DATABASE_CATALOG_PKEY_OID)); + database_id_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto database_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "database_name", false); - database_name_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + database_name_column.AddConstraint(std::make_shared( + ConstraintType::UNIQUE, unique_constraint_name, + DATABASE_CATALOG_SKEY0_OID)); + database_name_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); std::unique_ptr database_catalog_schema( new catalog::Schema({database_id_column, database_name_column})); diff --git a/src/catalog/index_catalog.cpp b/src/catalog/index_catalog.cpp index da666f36f60..47a730c8c24 100644 --- a/src/catalog/index_catalog.cpp +++ b/src/catalog/index_catalog.cpp @@ -76,53 +76,62 @@ IndexCatalog::~IndexCatalog() {} std::unique_ptr IndexCatalog::InitializeSchema() { const std::string not_null_constraint_name = "not_null"; const std::string primary_key_constraint_name = "primary_key"; + const std::string unique_constraint_name = "con_unique"; auto index_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "index_oid", true); - index_id_column.AddConstraint(catalog::Constraint( - ConstraintType::PRIMARY, primary_key_constraint_name)); - index_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + index_id_column.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, primary_key_constraint_name, + INDEX_CATALOG_PKEY_OID)); + index_id_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto index_name_column = catalog::Column(type::TypeId::VARCHAR, max_name_size, "index_name", false); - index_name_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + index_name_column.AddConstraint(std::make_shared( + ConstraintType::UNIQUE, unique_constraint_name, + INDEX_CATALOG_SKEY0_OID)); + index_name_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + table_id_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto schema_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "schema_name", false); - schema_name_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + schema_name_column.AddConstraint(std::make_shared( + ConstraintType::UNIQUE, unique_constraint_name, + INDEX_CATALOG_SKEY0_OID)); + schema_name_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto index_type_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "index_type", true); - index_type_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + index_type_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto index_constraint_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "index_constraint", true); - index_constraint_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + index_constraint_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto unique_keys = catalog::Column( type::TypeId::BOOLEAN, type::Type::GetTypeSize(type::TypeId::BOOLEAN), "unique_keys", true); - unique_keys.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + unique_keys.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto indexed_attributes_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "indexed_attributes", false); - indexed_attributes_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + indexed_attributes_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); + std::unique_ptr index_schema(new catalog::Schema( {index_id_column, index_name_column, table_id_column, schema_name_column, index_type_column, index_constraint_column, unique_keys, diff --git a/src/catalog/layout_catalog.cpp b/src/catalog/layout_catalog.cpp index aca1556d51c..c11ac4a38d7 100644 --- a/src/catalog/layout_catalog.cpp +++ b/src/catalog/layout_catalog.cpp @@ -50,30 +50,32 @@ std::unique_ptr LayoutCatalog::InitializeSchema() { auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.AddConstraint(catalog::Constraint( - ConstraintType::PRIMARY, primary_key_constraint_name)); - table_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + table_id_column.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, primary_key_constraint_name, + LAYOUT_CATALOG_PKEY_OID)); + table_id_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto layout_oid_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "layout_oid", true); - layout_oid_column.AddConstraint(catalog::Constraint( - ConstraintType::PRIMARY, primary_key_constraint_name)); - layout_oid_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + layout_oid_column.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, primary_key_constraint_name, + LAYOUT_CATALOG_PKEY_OID)); + layout_oid_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto num_columns_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "num_columns", true); - num_columns_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + num_columns_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto column_map_column = catalog::Column( type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), "column_map", false); - column_map_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + column_map_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); std::unique_ptr column_catalog_schema( new catalog::Schema({table_id_column, layout_oid_column, @@ -227,4 +229,4 @@ std::shared_ptr LayoutCatalog::GetLayoutWithOid( } } // namespace catalog -} // namespace peloton \ No newline at end of file +} // namespace peloton diff --git a/src/catalog/schema_catalog.cpp b/src/catalog/schema_catalog.cpp index 4761bb0e776..ad676e2a71d 100644 --- a/src/catalog/schema_catalog.cpp +++ b/src/catalog/schema_catalog.cpp @@ -52,19 +52,24 @@ SchemaCatalog::~SchemaCatalog() {} std::unique_ptr SchemaCatalog::InitializeSchema() { const std::string not_null_constraint_name = "not_null"; const std::string primary_key_constraint_name = "primary_key"; + const std::string unique_constraint_name = "con_unique"; auto schema_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "schema_oid", true); - schema_id_column.AddConstraint(catalog::Constraint( - ConstraintType::PRIMARY, primary_key_constraint_name)); - schema_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + schema_id_column.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, primary_key_constraint_name, + SCHEMA_CATALOG_PKEY_OID)); + schema_id_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto schema_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "schema_name", false); - schema_name_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + schema_name_column.AddConstraint(std::make_shared( + ConstraintType::UNIQUE, unique_constraint_name, + SCHEMA_CATALOG_SKEY0_OID)); + schema_name_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); std::unique_ptr schema( new catalog::Schema({schema_id_column, schema_name_column})); diff --git a/src/catalog/system_catalogs.cpp b/src/catalog/system_catalogs.cpp index 3900c165f74..4b7d53220b2 100644 --- a/src/catalog/system_catalogs.cpp +++ b/src/catalog/system_catalogs.cpp @@ -40,15 +40,18 @@ SystemCatalogs::SystemCatalogs(storage::Database *database, pg_table_ = new TableCatalog(database, pool, txn); pg_index_ = new IndexCatalog(database, pool, txn); pg_layout_ = new LayoutCatalog(database, pool, txn); + pg_constraint_ = new ConstraintCatalog(database, pool, txn); // TODO: can we move this to BootstrapSystemCatalogs()? // insert column information into pg_attribute + // and insert constraint information into pg_constraint std::vector> shared_tables = { {CATALOG_DATABASE_OID, DATABASE_CATALOG_OID}, {database_oid, TABLE_CATALOG_OID}, {database_oid, SCHEMA_CATALOG_OID}, {database_oid, INDEX_CATALOG_OID}, - {database_oid, LAYOUT_CATALOG_OID}}; + {database_oid, LAYOUT_CATALOG_OID}, + {database_oid, CONSTRAINT_CATALOG_OID}}; for (int i = 0; i < (int)shared_tables.size(); i++) { oid_t column_id = 0; @@ -60,7 +63,13 @@ SystemCatalogs::SystemCatalogs(storage::Database *database, pg_attribute_->InsertColumn(shared_tables[i].second, column.GetName(), column_id, column.GetOffset(), column.GetType(), column.IsInlined(), - column.GetConstraints(), pool, txn); + column.IsNotNull(), column.IsDefault(), + column.GetDefaultValue(), pool, txn); + for (auto constraint : column.GetConstraints()) { + constraint->SetConstraintOid(pg_constraint_->GetNextOid()); + pg_constraint_->InsertConstraint(shared_tables[i].second, {column_id}, + constraint, pool, txn); + } column_id++; } } @@ -72,6 +81,7 @@ SystemCatalogs::~SystemCatalogs() { delete pg_table_; delete pg_attribute_; delete pg_namespace_; + delete pg_constraint_; if (pg_trigger_) delete pg_trigger_; // if (pg_proc) delete pg_proc; if (pg_table_metrics_) delete pg_table_metrics_; diff --git a/src/catalog/table_catalog.cpp b/src/catalog/table_catalog.cpp index 9f181d4c0dc..dce91e2b6df 100644 --- a/src/catalog/table_catalog.cpp +++ b/src/catalog/table_catalog.cpp @@ -16,6 +16,7 @@ #include "catalog/catalog.h" #include "catalog/column_catalog.h" +#include "catalog/constraint_catalog.h" #include "catalog/database_catalog.h" #include "catalog/index_catalog.h" #include "catalog/layout_catalog.h" @@ -47,6 +48,8 @@ TableCatalogObject::TableCatalogObject(executor::LogicalTile *tile, column_objects(), column_names(), valid_column_objects(false), + valid_layout_objects_(false), + valid_constraint_objects_(false), txn(txn) {} /* @brief insert index catalog object into cache @@ -372,7 +375,7 @@ TableCatalogObject::GetLayouts(bool cached_only) { ->GetSystemCatalogs(database_oid) ->GetLayoutCatalog(); pg_layout->GetLayouts(table_oid, txn); - valid_column_objects = true; + valid_layout_objects_ = true; } return layout_objects_; } @@ -412,6 +415,97 @@ bool TableCatalogObject::EvictLayout(oid_t layout_id) { return true; } + +/** @brief Insert constraint object into the cache. + * @param constraint_object Constraint object to be inserted + * @return false if the constraint object already exists in cache + */ +bool TableCatalogObject::InsertConstraintObject( + std::shared_ptr constraint_object) { + // Invalid object + if (!constraint_object + || (constraint_object->GetConstraintOid() == INVALID_OID)) { + return false; + } + + oid_t constraint_oid = constraint_object->GetConstraintOid(); + // layout is already present in the cache. + if (constraint_objects_.find(constraint_oid) != constraint_objects_.end()) { + LOG_DEBUG("Constraint Object %u already exists in cache!", constraint_oid); + return false; + } + + constraint_objects_.insert(std::make_pair(constraint_oid, constraint_object)); + return true; +} + + +/** @brief Evict constraint object from the cache. + * @param constraint_oid Id of the constraint to be deleted. + * @return true if constraint_oid is found and evicted; false if not found. + */ +bool TableCatalogObject::EvictConstraintObject(oid_t constraint_oid) { + if (!valid_constraint_objects_) return false; + + // find the constraint object from the cache + auto it = constraint_objects_.find(constraint_oid); + if (it == constraint_objects_.end()) { + return false; // constraint_oid not found in cache + } + + auto constraint_object = it->second; + PELOTON_ASSERT(constraint_object); + constraint_objects_.erase(it); + return true; +} + +/** @brief evict all constraint objects from cache. */ +void TableCatalogObject::EvictAllConstraintObjects() { + constraint_objects_.clear(); + valid_constraint_objects_ = false; +} + +/** @brief Get all constraint objects of this table. + * Add it to the cache if necessary. + * @param cached_only If set to true, don't fetch the constraint objects. + * @return Map from constraint_oid to cached constraint object. + */ +std::unordered_map> +TableCatalogObject::GetConstraintObjects(bool cached_only) { + if (!valid_constraint_objects_ && !cached_only) { + // get constraint catalog objects from pg_constraint + auto pg_constraint = Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetConstraintCatalog(); + pg_constraint->GetConstraintObjects(table_oid, txn); + valid_constraint_objects_ = true; + } + return constraint_objects_; +} + +/** @brief Get the constraint catalog object of the given constraint_oid. + * @param constraint_oid The id of the constraint to be fetched. + * @param cached_only If set to true, don't fetch the constraint objects. + * @return Constraint catalog object of corresponding to the oid if present. + */ +std::shared_ptr +TableCatalogObject::GetConstraintObject(oid_t constraint_oid, bool cached_only){ + auto it = constraint_objects_.find(constraint_oid); + if (it != constraint_objects_.end()) return it->second; + + if (cached_only) { + // cache miss return empty object + return nullptr; + } else { + // cache miss get from pg_table + auto pg_constraint = Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetConstraintCatalog(); + return pg_constraint->GetConstraintObject(table_oid, constraint_oid, txn); + } +} + + TableCatalog::~TableCatalog() {} /*@brief private function for initialize schema of pg_table @@ -420,36 +514,44 @@ TableCatalog::~TableCatalog() {} std::unique_ptr TableCatalog::InitializeSchema() { const std::string primary_key_constraint_name = "primary_key"; const std::string not_null_constraint_name = "not_null"; + const std::string unique_constraint_name = "con_unique"; auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.AddConstraint(catalog::Constraint( - ConstraintType::PRIMARY, primary_key_constraint_name)); - table_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + table_id_column.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, primary_key_constraint_name, + TABLE_CATALOG_PKEY_OID)); + table_id_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto table_name_column = catalog::Column(type::TypeId::VARCHAR, max_name_size, "table_name", false); - table_name_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + table_name_column.AddConstraint(std::make_shared( + ConstraintType::UNIQUE, unique_constraint_name, + TABLE_CATALOG_SKEY0_OID)); + table_name_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto schema_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "schema_name", false); - schema_name_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + schema_name_column.AddConstraint(std::make_shared( + ConstraintType::UNIQUE, unique_constraint_name, + TABLE_CATALOG_SKEY0_OID)); + schema_name_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto database_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "database_oid", true); - database_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + database_id_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); auto version_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "version_id", true); - version_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + version_id_column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); std::unique_ptr table_catalog_schema(new catalog::Schema( {table_id_column, table_name_column, schema_name_column, diff --git a/src/common/internal_types.cpp b/src/common/internal_types.cpp index b93da7f3b13..61aea8ca7e5 100644 --- a/src/common/internal_types.cpp +++ b/src/common/internal_types.cpp @@ -2116,6 +2116,62 @@ std::ostream &operator<<(std::ostream &os, const ConstraintType &type) { return os; } +//===--------------------------------------------------------------------===// +// Foreign Key Action Type - String Utilities +//===--------------------------------------------------------------------===// + +std::string FKConstrActionTypeToString(FKConstrActionType type) { + switch (type) { + case FKConstrActionType::NOACTION: { + return ("NOACTION"); + } + case FKConstrActionType::RESTRICT: { + return ("RESTRICT"); + } + case FKConstrActionType::CASCADE: { + return ("CASCADE"); + } + case FKConstrActionType::SETNULL: { + return ("SETNULL"); + } + case FKConstrActionType::SETDEFAULT: { + return ("SETDEFAULT"); + } + default: { + throw ConversionException(StringUtil::Format( + "No string conversion for FKConstrActionType value '%d'", + static_cast(type))); + } + } +return "INVALID"; +} + +FKConstrActionType StringToFKConstrActionType(const std::string &str){ + std::string upper_str = StringUtil::Upper(str); + if (upper_str == "NOACTION") { + return FKConstrActionType::NOACTION; + } else if (upper_str == "RESTRICT") { + return FKConstrActionType::RESTRICT; + } else if (upper_str == "CASCADE") { + return FKConstrActionType::CASCADE; + } else if (upper_str == "SETNULL") { + return FKConstrActionType::SETNULL; + } else if (upper_str == "SETDEFAULT") { + return FKConstrActionType::SETDEFAULT; + } else { + throw ConversionException(StringUtil::Format( + "No FKConstrActionType conversion from string '%s'", + upper_str.c_str())); + } + return FKConstrActionType::NOACTION; +} + + +std::ostream &operator<<(std::ostream &os, const FKConstrActionType &type) { + os << FKConstrActionTypeToString(type); + return os; +} + //===--------------------------------------------------------------------===// // SetOpType - String Utilities //===--------------------------------------------------------------------===// diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index 83e85c92c48..731ff5298ba 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -128,7 +128,6 @@ bool CreateExecutor::CreateTable(const planner::CreatePlan &node) { // Add the foreign key constraint (or other multi-column constraints) if (node.GetForeignKeys().empty() == false) { - int count = 1; auto catalog = catalog::Catalog::GetInstance(); auto source_table = catalog->GetTableWithName(database_name, schema_name, table_name, current_txn); @@ -167,27 +166,13 @@ bool CreateExecutor::CreateTable(const planner::CreatePlan &node) { PELOTON_ASSERT(sink_col_ids.size() == fk.foreign_key_sinks.size()); // Create the catalog object and shove it into the table - auto catalog_fk = new catalog::ForeignKey( - INVALID_OID, sink_table->GetOid(), sink_col_ids, source_col_ids, - fk.upd_action, fk.del_action, fk.constraint_name); - source_table->AddForeignKey(catalog_fk); - - // Register FK with the sink table for delete/update actions - catalog_fk = new catalog::ForeignKey( - source_table->GetOid(), INVALID_OID, sink_col_ids, source_col_ids, - fk.upd_action, fk.del_action, fk.constraint_name); - sink_table->RegisterForeignKeySource(catalog_fk); - - // Add a non-unique index on the source table if needed - std::vector source_col_names = fk.foreign_key_sources; - std::string index_name = table_name + "_FK_" + sink_table->GetName() + - "_" + std::to_string(count); - catalog->CreateIndex(database_name, schema_name, table_name, - source_col_ids, index_name, false, - IndexType::BWTREE, current_txn); - count++; + catalog->AddForeignKeyConstraint(source_table->GetDatabaseOid(), + source_table->GetOid(), source_col_ids, sink_table->GetOid(), + sink_col_ids, fk.upd_action, fk.del_action, fk.constraint_name, + current_txn); #ifdef LOG_DEBUG_ENABLED + std::vector source_col_names = fk.foreign_key_sources; LOG_DEBUG("Added a FOREIGN index on in %s.\n", table_name.c_str()); LOG_DEBUG("Foreign key column names: \n"); for (auto c : source_col_names) { diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h index 5b9d4fd2ba1..ebc2e830eda 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -20,6 +20,8 @@ namespace peloton { namespace catalog { +class ForeignKey; +class Constraint; class Schema; class DatabaseCatalogObject; class TableCatalogObject; @@ -119,7 +121,8 @@ class Catalog { ResultType CreateIndex(oid_t database_oid, oid_t table_oid, const std::vector &key_attrs, const std::string &schema_name, - const std::string &index_name, IndexType index_type, + oid_t index_oid, const std::string &index_name, + IndexType index_type, IndexConstraintType index_constraint, bool unique_keys, concurrency::TransactionContext *txn, bool is_catalog = false); @@ -151,6 +154,47 @@ class Catalog { oid_t database_oid, oid_t table_oid, const column_map_type &column_map, concurrency::TransactionContext *txn); + //===--------------------------------------------------------------------===// + // ADD FUNCTIONS + //===--------------------------------------------------------------------===// + + /** + * @brief Add a new constraint for a table except for foreign key + * @param database_oid Database to which the table belongs to + * @param table_oid Table to which the constraint has to be added + * @param column_ids Columns that the constraint affects + * @param constraint The new constraint to be registered + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + * note: if add a new foreign key constraint, use AddForeignKeyConstraint + */ + ResultType AddConstraint(oid_t database_oid, oid_t table_oid, + const std::vector &column_ids, + std::shared_ptr constraint, + concurrency::TransactionContext *txn); + + /** + * @brief Add a new foreign key constraint for a table + * @param database_oid database to which the table belongs to + * @param src_table_oid table to which the constraint has to be added + * @param src_col_ids Columns that the constraint affects + * @param snk_table_oid sink table + * @param snk_col_ids Columns that limit the source columns + * @param upd_action foreign key constraint action when update + * @param del_action foreign key constraint action when delete + * @param constraint_name constraint name + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + */ + ResultType AddForeignKeyConstraint(oid_t database_oid, oid_t src_table_oid, + const std::vector &src_col_ids, + oid_t sink_table_oid, + const std::vector &sink_col_ids, + FKConstrActionType upd_action, + FKConstrActionType del_action, + const std::string &constraint_name, + concurrency::TransactionContext *txn); + //===--------------------------------------------------------------------===// // DROP FUNCTIONS //===--------------------------------------------------------------------===// @@ -189,6 +233,20 @@ class Catalog { */ ResultType DropLayout(oid_t database_oid, oid_t table_oid, oid_t layout_oid, concurrency::TransactionContext *txn); + + /** + * @brief Drop a new foreign key constraint for a table + * @param database_oid the database to which the table belongs to + * @param table_oid the table to which the layout belongs + * @param constraint_oid the constraint to be dropped + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + */ + ResultType DropConstraint(oid_t database_oid, oid_t table_oid, + oid_t constraint_oid, + concurrency::TransactionContext *txn); + + //===--------------------------------------------------------------------===// // GET WITH NAME - CHECK FROM CATALOG TABLES, USING TRANSACTION //===--------------------------------------------------------------------===// diff --git a/src/include/catalog/catalog_defaults.h b/src/include/catalog/catalog_defaults.h index 117a7e8ab6d..abaec7d387d 100644 --- a/src/include/catalog/catalog_defaults.h +++ b/src/include/catalog/catalog_defaults.h @@ -33,10 +33,11 @@ namespace catalog { #define INDEX_CATALOG_NAME "pg_index" #define COLUMN_CATALOG_NAME "pg_attribute" #define LAYOUT_CATALOG_NAME "pg_layout" +#define CONSTRAINT_CATALOG_NAME "pg_constraint" // Local oids from START_OID = 0 to START_OID + OID_OFFSET are reserved #define OID_OFFSET 100 -#define CATALOG_TABLES_COUNT 9 +#define CATALOG_TABLES_COUNT 10 // Oid mask for each type #define DATABASE_OID_MASK (static_cast(catalog::CatalogType::DATABASE)) @@ -46,6 +47,7 @@ namespace catalog { #define TRIGGER_OID_MASK (static_cast(catalog::CatalogType::TRIGGER)) #define LANGUAGE_OID_MASK (static_cast(catalog::CatalogType::LANGUAGE)) #define PROC_OID_MASK (static_cast(catalog::CatalogType::PROC)) +#define CONSTRAINT_OID_MASK (static_cast(catalog::CatalogType::CONSTRAINT)) // Reserved peloton database oid #define CATALOG_DATABASE_OID (0 | DATABASE_OID_MASK) @@ -64,6 +66,7 @@ namespace catalog { #define INDEX_CATALOG_OID (3 | TABLE_OID_MASK) #define COLUMN_CATALOG_OID (4 | TABLE_OID_MASK) #define LAYOUT_CATALOG_OID (5 | TABLE_OID_MASK) +#define CONSTRAINT_CATALOG_OID (6 | TABLE_OID_MASK) // Reserved pg_column index oid #define COLUMN_CATALOG_PKEY_OID (0 | INDEX_OID_MASK) @@ -92,6 +95,10 @@ namespace catalog { #define LAYOUT_CATALOG_PKEY_OID (13 | INDEX_OID_MASK) #define LAYOUT_CATALOG_SKEY0_OID (14 | INDEX_OID_MASK) +// Reserve pg_layout index oid +#define CONSTRAINT_CATALOG_PKEY_OID (15 | INDEX_OID_MASK) +#define CONSTRAINT_CATALOG_SKEY0_OID (16 | INDEX_OID_MASK) + // Use upper 8 bits indicating catalog type #define CATALOG_TYPE_OFFSET 24 @@ -105,6 +112,7 @@ enum class CatalogType : uint32_t { TRIGGER = 6 << CATALOG_TYPE_OFFSET, LANGUAGE = 7 << CATALOG_TYPE_OFFSET, PROC = 8 << CATALOG_TYPE_OFFSET, + CONSTRAINT = 9 << CATALOG_TYPE_OFFSET, // To be added }; diff --git a/src/include/catalog/column.h b/src/include/catalog/column.h index f351f72c5b9..53657cd3a70 100644 --- a/src/include/catalog/column.h +++ b/src/include/catalog/column.h @@ -80,28 +80,65 @@ class Column : public Printable { inline bool IsInlined() const { return is_inlined; } + // Constraint check functions for NOT NULL and DEFAULT inline bool IsPrimary() const { return is_primary_; } inline bool IsUnique() const { return is_unique_; } + inline bool IsNotNull() const { return is_not_null_; } + + inline bool IsDefault() const { return is_default_; } + + // Manage NOT NULL constraint + void SetNotNull() { is_not_null_ = true; } + + void ClearNotNull() { is_not_null_ = false; } + + // Manage DEFAULT constraint + void SetDefaultValue(std::shared_ptr value) { + default_value_ = value; + is_default_ = true; + } + + inline std::shared_ptr GetDefaultValue() const { + return default_value_; + } + + void ClearDefaultValue() { + default_value_.reset(); + is_default_ = false; } + // Add a constraint to the column - void AddConstraint(const catalog::Constraint &constraint) { - if (constraint.GetType() == ConstraintType::DEFAULT) { + void AddConstraint(const std::shared_ptr constraint) { + if (constraint->GetType() == ConstraintType::DEFAULT) { // Add the default constraint to the front constraints.insert(constraints.begin(), constraint); } else { constraints.push_back(constraint); } - if (constraint.GetType() == ConstraintType::PRIMARY) { + if (constraint->GetType() == ConstraintType::PRIMARY) { is_primary_ = true; } - if (constraint.GetType() == ConstraintType::UNIQUE) { + if (constraint->GetType() == ConstraintType::UNIQUE) { is_unique_ = true; } } - const std::vector &GetConstraints() const { return constraints; } + // Delete a constraint from the column + bool DeleteConstraint(const oid_t constraint_oid); + + const std::vector> &GetConstraints() const { + return constraints; + } + + std::shared_ptr GetConstraint(oid_t constraint_oid) { + for (auto constraint : constraints) { + if (constraint->GetConstraintOid() == constraint_oid) + return constraint; + } + return nullptr; + } hash_t Hash() const { hash_t hash = HashUtil::Hash(&column_type); @@ -143,17 +180,17 @@ class Column : public Printable { // is the column inlined ? bool is_inlined = false; - // is the column contained the primary key? - bool is_primary_ = false; + // is the column allowed null + bool is_not_null_ = false; + + // is the column contained the default value + bool is_default_ = false; - // is the column unique - bool is_unique_ = false; + // default value + std::shared_ptr default_value_; // offset of column in tuple oid_t column_offset = INVALID_OID; - - // Constraints - std::vector constraints; }; } // namespace catalog diff --git a/src/include/catalog/column_catalog.h b/src/include/catalog/column_catalog.h index 7dcdf96e4a5..045818d348e 100644 --- a/src/include/catalog/column_catalog.h +++ b/src/include/catalog/column_catalog.h @@ -59,8 +59,9 @@ class ColumnCatalogObject { uint32_t column_offset; type::TypeId column_type; bool is_inlined; - bool is_primary; bool is_not_null; + bool is_default; + std::shared_ptr default_value; }; class ColumnCatalog : public AbstractCatalog { @@ -83,9 +84,16 @@ class ColumnCatalog : public AbstractCatalog { bool InsertColumn(oid_t table_oid, const std::string &column_name, oid_t column_id, oid_t column_offset, type::TypeId column_type, bool is_inlined, - const std::vector &constraints, + const std::vector> constraints, type::AbstractPool *pool, concurrency::TransactionContext *txn); + bool InsertColumn(oid_t table_oid, const std::string &column_name, + oid_t column_id, oid_t column_offset, + type::TypeId column_type, bool is_inlined, + bool is_not_null, bool is_default, + const std::shared_ptr default_value, + type::AbstractPool *pool, + concurrency::TransactionContext *txn); bool DeleteColumn(oid_t table_oid, const std::string &column_name, concurrency::TransactionContext *txn); bool DeleteColumns(oid_t table_oid, concurrency::TransactionContext *txn); @@ -106,11 +114,12 @@ class ColumnCatalog : public AbstractCatalog { COLUMN_OFFSET = 3, COLUMN_TYPE = 4, IS_INLINED = 5, - IS_PRIMARY = 6, - IS_NOT_NULL = 7, + IS_NOT_NULL = 6, + IS_DEFAULT = 7, + DEFAULT_VALUE = 8, // Add new columns here in creation order }; - std::vector all_column_ids = {0, 1, 2, 3, 4, 5, 6, 7}; + std::vector all_column_ids = {0, 1, 2, 3, 4, 5, 6, 7, 8}; enum IndexId { PRIMARY_KEY = 0, diff --git a/src/include/catalog/constraint.h b/src/include/catalog/constraint.h index c63b881c727..20383ecbeaa 100644 --- a/src/include/catalog/constraint.h +++ b/src/include/catalog/constraint.h @@ -29,33 +29,31 @@ namespace catalog { class Constraint : public Printable { public: - Constraint(ConstraintType type, std::string constraint_name) - : constraint_type(type), constraint_name(constraint_name) {} Constraint(ConstraintType type, std::string constraint_name, - std::string check_cmd) - : constraint_type(type), - constraint_name(constraint_name), - check_cmd(check_cmd) {} + oid_t index_oid = INVALID_OID) + : constraint_type(type), constraint_name(constraint_name), + index_oid(index_oid) {} + + Constraint(ConstraintType type, std::string constraint_name, + std::string check_cmd, oid_t index_oid = INVALID_OID) + : constraint_type(type), constraint_name(constraint_name), + index_oid(index_oid), check_cmd(check_cmd) {} //===--------------------------------------------------------------------===// // ACCESSORS //===--------------------------------------------------------------------===// - ConstraintType GetType() const { return constraint_type; } - - std::pair GetCheckExpression() { return exp; } + void SetConstraintOid(oid_t oid) { constraint_oid = oid; } - // Offset into the list of "reference tables" in the Table. - void SetForeignKeyListOffset(oid_t offset) { fk_list_offset = offset; } + oid_t GetConstraintOid() const { return constraint_oid; } - // Offset into the list of "unique indices" in the Table. - void SetUniqueIndexOffset(oid_t offset) { unique_index_list_offset = offset; } + ConstraintType GetType() const { return constraint_type; } - // Get the offset - oid_t GetForeignKeyListOffset() const { return fk_list_offset; } + // Set index oid indicating the index constructing the constraint + void SetIndexOid(oid_t oid) { index_oid = oid; } - // Get the offset - oid_t GetUniqueIndexOffset() const { return unique_index_list_offset; } + // Get the index oid + oid_t GetIndexOid() const { return index_oid; } std::string GetName() const { return constraint_name; } @@ -72,7 +70,7 @@ class Constraint : public Printable { default_value.reset(new peloton::type::Value(value)); } - type::Value* getDefaultValue() { + type::Value* getDefaultValue() const { return default_value.get(); } @@ -82,21 +80,25 @@ class Constraint : public Printable { return; }; + std::pair GetCheckExpression() const { return exp; } + + std::string GetCheckCmd() const { return check_cmd; } + private: //===--------------------------------------------------------------------===// // MEMBERS //===--------------------------------------------------------------------===// + oid_t constraint_oid = INVALID_OID; + // The type of constraint ConstraintType constraint_type = ConstraintType::INVALID; - // Offsets into the Unique index and reference table lists in Table - oid_t fk_list_offset = INVALID_OID; - - oid_t unique_index_list_offset = INVALID_OID; - std::string constraint_name; + // The index constructing the constraint + oid_t index_oid; + std::shared_ptr default_value; std::string check_cmd = ""; diff --git a/src/include/catalog/constraint_catalog.h b/src/include/catalog/constraint_catalog.h new file mode 100644 index 00000000000..f0d8243354f --- /dev/null +++ b/src/include/catalog/constraint_catalog.h @@ -0,0 +1,161 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// constraint_catalog.h +// +// Identification: src/include/catalog/constraint_catalog.h +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// pg_constraint +// +// Schema: (column offset: column_name) +// 0: constraint_oid (pkey) +// 1: constraint_name (name of the constraint, not unique!) +// 2: constraint_type (type of the constraint) +// 3: table_oid (table created for the constraint) +// 4: column_ids (list of column id related to the constraint) +// 5: index_oid (index created for the constraint) +// 6: fk_sink_table_oid (for FOREIGN KEY) +// 7: fk_sink_col_ids (for FOREIGN KEY) +// 8: fk_update_action (for FOREIGN KEY) +// 9: fk_delete_action (for FOREIGN KEY) +// 10: default_value (for DEFAULT) +// 11: check_cmd (for CHECK) +// 12: check_exp (for CHECK) +// +// Indexes: (index offset: indexed columns) +// 0: constraint_oid (unique & primary key) +// 1: table_oid (non-unique) +// +// Note: Exclusive constraint is not supported yet +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "catalog/abstract_catalog.h" +#include "executor/logical_tile.h" + +namespace peloton { +namespace catalog { + +class Constraint; +class ForeignKey; + +class ConstraintCatalogObject { + friend class ConstraintCatalog; + + public: + ConstraintCatalogObject(executor::LogicalTile *tile, int tupleId = 0); + + inline oid_t GetConstraintOid() { return constraint_oid; } + inline const std::string &GetConstraintName() { return constraint_name; } + inline ConstraintType GetConstraintType() { return constraint_type; } + inline oid_t GetTableOid() { return table_oid; } + inline const std::vector &GetColumnIds() { return column_ids; } + inline oid_t GetIndexOid() { return index_oid; } + inline oid_t GetFKSinkTableOid() { return fk_sink_table_oid; } + inline const std::vector &GetFKSinkColumnIds() { return fk_sink_col_ids; } + inline FKConstrActionType GetFKUpdateAction() { return fk_update_action; } + inline FKConstrActionType GetFKDeleteAction() { return fk_delete_action; } + inline const std::string &GetDefaultValue() { return default_value; } + inline const std::string &GetCheckCmd() { return check_cmd; } + inline const std::string &GetCheckExp() { return check_exp; } + + private: + // member variables + oid_t constraint_oid; + std::string constraint_name; + ConstraintType constraint_type; + oid_t table_oid; + std::vector column_ids; + oid_t index_oid; + oid_t fk_sink_table_oid; + std::vector fk_sink_col_ids; + FKConstrActionType fk_update_action; + FKConstrActionType fk_delete_action; + std::string default_value; // original : std::shared_ptr + std::string check_cmd; + std::string check_exp; // original : std::pair +}; + +class ConstraintCatalog : public AbstractCatalog { + friend class ConstraintCatalogObject; + friend class TableCatalogObject; + friend class Catalog; + + public: + ConstraintCatalog(storage::Database *pg_catalog, type::AbstractPool *pool, + concurrency::TransactionContext *txn); + + ~ConstraintCatalog(); + + inline oid_t GetNextOid() { return oid_++ | CONSTRAINT_OID_MASK; } + + void UpdateOid(oid_t add_value) { oid_ += add_value; } + + //===--------------------------------------------------------------------===// + // write Related API + //===--------------------------------------------------------------------===// + // Basic insert for primary key, unique, check, default or not null constraint + bool InsertConstraint(oid_t table_oid, const std::vector &column_ids, + const std::shared_ptr constraint, + type::AbstractPool *pool, + concurrency::TransactionContext *txn); + + // insert for foreign key constraint + bool InsertConstraint(oid_t table_oid, const std::vector &column_ids, + const std::shared_ptr constraint, + const ForeignKey &foreign_key, type::AbstractPool *pool, + concurrency::TransactionContext *txn); + + bool DeleteConstraints(oid_t table_oid, concurrency::TransactionContext *txn); + + bool DeleteConstraint(oid_t table_oid, oid_t constraint_oid, + concurrency::TransactionContext *txn); + + private: + //===--------------------------------------------------------------------===// + // Read Related API(only called within table catalog object) + //===--------------------------------------------------------------------===// + const std::unordered_map> + GetConstraintObjects(oid_t table_oid, concurrency::TransactionContext *txn); + + const std::shared_ptr + GetConstraintObject(oid_t table_oid, oid_t constraint_oid, + concurrency::TransactionContext *txn); + + std::unique_ptr InitializeSchema(); + + enum ColumnId { + CONSTRAINT_OID = 0, + CONSTRAINT_NAME = 1, + CONSTRAINT_TYPE = 2, + TABLE_OID = 3, + COLUMN_IDS = 4, + INDEX_OID = 5, + FK_SINK_TABLE_OID = 6, + FK_SINK_COL_IDS = 7, + FK_UPDATE_ACTION = 8, + FK_DELETE_ACTION = 9, + DEFAULT_VALUE = 10, + CHECK_CMD = 11, + CHECK_EXP = 12, + // Add new columns here in creation order + }; + std::vector all_column_ids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + + enum IndexId { + PRIMARY_KEY = 0, + SKEY_TABLE_OID = 1, + // Add new indexes here in creation order + }; +}; + +} // namespace catalog +} // namespace peloton diff --git a/src/include/catalog/layout_catalog.h b/src/include/catalog/layout_catalog.h index 0fc224f094d..9d91892bef4 100644 --- a/src/include/catalog/layout_catalog.h +++ b/src/include/catalog/layout_catalog.h @@ -23,6 +23,7 @@ class Layout; namespace catalog { class LayoutCatalog : public AbstractCatalog { + friend class Catalog; public: LayoutCatalog(storage::Database *pg_catalog, type::AbstractPool *pool, @@ -72,4 +73,4 @@ class LayoutCatalog : public AbstractCatalog { }; } // namespace catalog -} // namespace peloton \ No newline at end of file +} // namespace peloton diff --git a/src/include/catalog/schema.h b/src/include/catalog/schema.h index 43a62d6444f..a925d1cfe98 100644 --- a/src/include/catalog/schema.h +++ b/src/include/catalog/schema.h @@ -177,7 +177,7 @@ class Schema : public Printable { // Get the nullability of the column at a given index. inline bool AllowNull(const oid_t column_id) const { for (auto constraint : columns[column_id].GetConstraints()) { - if (constraint.GetType() == ConstraintType::NOTNULL) return false; + if (constraint->GetType() == ConstraintType::NOTNULL) return false; } return true; } @@ -185,7 +185,7 @@ class Schema : public Printable { // For single column default inline bool AllowDefault(const oid_t column_id) const { for (auto constraint : columns[column_id].GetConstraints()) { - if (constraint.GetType() == ConstraintType::DEFAULT) { + if (constraint->GetType() == ConstraintType::DEFAULT) { return true; } } @@ -196,8 +196,8 @@ class Schema : public Printable { // Get the default value for the column inline type::Value* GetDefaultValue(const oid_t column_id) const { for (auto constraint : columns[column_id].GetConstraints()) { - if (constraint.GetType() == ConstraintType::DEFAULT) { - return constraint.getDefaultValue(); + if (constraint->GetType() == ConstraintType::DEFAULT) { + return constraint->getDefaultValue(); } } @@ -206,13 +206,13 @@ class Schema : public Printable { // Add constraint for column by id inline void AddConstraint(oid_t column_id, - const catalog::Constraint &constraint) { + const std::shared_ptr constraint) { columns[column_id].AddConstraint(constraint); } // Add constraint for column by name inline void AddConstraint(std::string column_name, - const catalog::Constraint &constraint) { + const std::shared_ptr constraint) { for (size_t column_itr = 0; column_itr < columns.size(); column_itr++) { if (columns[column_itr].GetName() == column_name) { columns[column_itr].AddConstraint(constraint); @@ -220,6 +220,10 @@ class Schema : public Printable { } } + inline bool DeleteConstraint(oid_t column_id, oid_t constraint_oid) { + return columns[column_id].DeleteConstraint(constraint_oid); + } + inline void AddMultiConstraints(const catalog::MultiConstraint &mc) { multi_constraints.push_back(mc); } diff --git a/src/include/catalog/system_catalogs.h b/src/include/catalog/system_catalogs.h index 9792d180f9d..5a31187bb0a 100644 --- a/src/include/catalog/system_catalogs.h +++ b/src/include/catalog/system_catalogs.h @@ -14,6 +14,7 @@ #include +#include "catalog/constraint_catalog.h" #include "catalog/database_catalog.h" #include "catalog/index_metrics_catalog.h" #include "catalog/query_metrics_catalog.h" @@ -35,6 +36,7 @@ class TableCatalog; class IndexCatalog; class ColumnCatalog; class LayoutCatalog; +class ConstraintCatalog; class SystemCatalogs { public: @@ -87,6 +89,13 @@ class SystemCatalogs { return pg_layout_; } + ConstraintCatalog *GetConstraintCatalog() { + if (!pg_constraint_) { + throw CatalogException("Layout catalog has not been initialized"); + } + return pg_constraint_; + } + TriggerCatalog *GetTriggerCatalog() { if (!pg_trigger_) { throw CatalogException("Trigger catalog has not been initialized"); @@ -121,6 +130,7 @@ class SystemCatalogs { TableCatalog *pg_table_; IndexCatalog *pg_index_; LayoutCatalog *pg_layout_; + ConstraintCatalog *pg_constraint_; TriggerCatalog *pg_trigger_; // ProcCatalog *pg_proc; diff --git a/src/include/catalog/table_catalog.h b/src/include/catalog/table_catalog.h index 9a01ee6e07f..55b343ff345 100644 --- a/src/include/catalog/table_catalog.h +++ b/src/include/catalog/table_catalog.h @@ -45,12 +45,14 @@ namespace catalog { class IndexCatalogObject; class ColumnCatalogObject; +class ConstraintCatalogObject; class TableCatalogObject { friend class TableCatalog; friend class IndexCatalog; friend class ColumnCatalog; friend class LayoutCatalog; + friend class ConstraintCatalog; public: TableCatalogObject(executor::LogicalTile *tile, @@ -88,6 +90,15 @@ class TableCatalogObject { std::shared_ptr GetLayout(oid_t layout_id, bool cached_entry = false); + // Evict all layouts from the cache + void EvictAllConstraintObjects(); + + // Get constraints + std::unordered_map> + GetConstraintObjects(bool cached_only = false); + std::shared_ptr + GetConstraintObject(oid_t constraint_oid, bool cached_entry = false); + inline oid_t GetTableOid() { return table_oid; } inline const std::string &GetTableName() { return table_name; } inline const std::string &GetSchemaName() { return schema_name; } @@ -117,6 +128,12 @@ class TableCatalogObject { // Evict layout_id from the table object bool EvictLayout(oid_t layout_id); + // Insert constraint object table object + bool InsertConstraintObject( + std::shared_ptr constraint_object); + // Evict constraint_oid from the table object + bool EvictConstraintObject(oid_t constraint_oid); + // cache for *all* index catalog objects in this table std::unordered_map> index_objects; std::unordered_map> @@ -135,6 +152,11 @@ class TableCatalogObject { layout_objects_; bool valid_layout_objects_; + // cache for *all* layout objects in the table + std::unordered_map> + constraint_objects_; + bool valid_constraint_objects_; + // Pointer to its corresponding transaction concurrency::TransactionContext *txn; }; @@ -145,6 +167,7 @@ class TableCatalog : public AbstractCatalog { friend class ColumnCatalog; friend class IndexCatalog; friend class LayoutCatalog; + friend class ConstraintCatalog; friend class Catalog; public: diff --git a/src/include/common/internal_types.h b/src/include/common/internal_types.h index 995a92cea2d..4f8df921b86 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -904,6 +904,9 @@ enum class FKConstrActionType { SETNULL = 3, SETDEFAULT = 4 }; +std::string FKConstrActionTypeToString(FKConstrActionType type); +FKConstrActionType StringToFKConstrActionType(const std::string &str); +std::ostream &operator<<(std::ostream &os, const FKConstrActionType &type); enum class FKConstrMatchType { SIMPLE = 0, PARTIAL = 1, FULL = 2 }; diff --git a/src/include/storage/data_table.h b/src/include/storage/data_table.h index 02878e1ab42..3fce557f7a3 100644 --- a/src/include/storage/data_table.h +++ b/src/include/storage/data_table.h @@ -208,19 +208,33 @@ class DataTable : public AbstractTable { executor::ExecutorContext *context, bool is_update); - void AddForeignKey(catalog::ForeignKey *key); + void AddForeignKey(oid_t constraint_oid, catalog::ForeignKey *key); - catalog::ForeignKey *GetForeignKey(const oid_t &key_offset) const; + std::unordered_map GetForeignKeys() const { + return foreign_keys_; + } + + catalog::ForeignKey *GetForeignKey(oid_t constraint_oid) const { + return foreign_keys_.at(constraint_oid); + } + + size_t GetForeignKeyCount() const { return foreign_keys_.size(); } - void DropForeignKey(const oid_t &key_offset); + void DropForeignKey(oid_t constraint_oid); - size_t GetForeignKeyCount() const; + void RegisterForeignKeySource(oid_t constraint_oid, catalog::ForeignKey *key); - void RegisterForeignKeySource(catalog::ForeignKey *key); + size_t GetForeignKeySrcCount() const { return foreign_key_sources_.size(); } - size_t GetForeignKeySrcCount() const; + std::unordered_map GetForeignKeySrcs() const { + return foreign_key_sources_; + } + + catalog::ForeignKey *GetForeignKeySrc(oid_t constraint_oid) const { + return foreign_key_sources_.at(constraint_oid); + } - catalog::ForeignKey *GetForeignKeySrc(const size_t) const; + void DropForeignKeySrc(oid_t constraint_oid); //===--------------------------------------------------------------------===// // TRANSFORMERS @@ -424,11 +438,11 @@ class DataTable : public AbstractTable { // CONSTRAINTS // fk constraints for which this table is the source - std::vector foreign_keys_; + std::unordered_map foreign_keys_; // fk constraints for which this table is the sink // The complete information is stored so no need to lookup the table // everytime there is a constraint check - std::vector foreign_key_sources_; + std::unordered_map foreign_key_sources_; // has a primary key ? std::atomic has_primary_key_ = ATOMIC_VAR_INIT(false); diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index 2a23a75abb4..c05ddc717cc 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -53,7 +53,7 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { schema_name = std::string(parse_tree->GetSchemaName()); database_name = std::string(parse_tree->GetDatabaseName()); std::vector columns; - std::vector column_constraints; + std::vector> column_constraints; create_type = CreateType::TABLE; @@ -71,23 +71,24 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { // Check main constraints if (col->primary) { - catalog::Constraint constraint(ConstraintType::PRIMARY, - "con_primary"); + std::shared_ptr constraint( + new catalog::Constraint(ConstraintType::PRIMARY, "con_primary")); column_constraints.push_back(constraint); LOG_TRACE("Added a primary key constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); } if (col->not_null) { - catalog::Constraint constraint(ConstraintType::NOTNULL, - "con_not_null"); + std::shared_ptr constraint( + new catalog::Constraint(ConstraintType::NOTNULL, "con_not_null")); column_constraints.push_back(constraint); LOG_TRACE("Added a not-null constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); } if (col->unique) { - catalog::Constraint constraint(ConstraintType::UNIQUE, "con_unique"); + std::shared_ptr constraint( + new catalog::Constraint(ConstraintType::UNIQUE, "con_unique")); column_constraints.push_back(constraint); LOG_TRACE("Added a unique constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); @@ -104,10 +105,10 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { dynamic_cast( col->default_value.get()); - catalog::Constraint constraint(ConstraintType::DEFAULT, - "con_default"); + std::shared_ptr constraint( + new catalog::Constraint(ConstraintType::DEFAULT, "con_default")); type::Value v = const_expr_elem->GetValue(); - constraint.addDefaultValue(v); + constraint->addDefaultValue(v); column_constraints.push_back(constraint); LOG_TRACE("Added a default constraint %s on column \"%s.%s\"", v.ToString().c_str(), table_name.c_str(), @@ -120,14 +121,15 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { if (col->check_expression != nullptr) { // TODO: more expression types need to be supported if (col->check_expression->GetValueType() == type::TypeId::BOOLEAN) { - catalog::Constraint constraint(ConstraintType::CHECK, "con_check"); + std::shared_ptr constraint( + new catalog::Constraint(ConstraintType::CHECK, "con_check")); const expression::ConstantValueExpression *const_expr_elem = dynamic_cast( col->check_expression->GetChild(1)); type::Value tmp_value = const_expr_elem->GetValue(); - constraint.AddCheck( + constraint->AddCheck( std::move(col->check_expression->GetExpressionType()), std::move(tmp_value)); column_constraints.push_back(constraint); diff --git a/src/storage/data_table.cpp b/src/storage/data_table.cpp index 64b8e3eb29b..2d6553989b7 100644 --- a/src/storage/data_table.cpp +++ b/src/storage/data_table.cpp @@ -111,12 +111,12 @@ DataTable::~DataTable() { // clean up foreign keys for (auto foreign_key : foreign_keys_) { - delete foreign_key; + delete foreign_key.second; } foreign_keys_.clear(); for (auto foreign_key_src : foreign_key_sources_) { - delete foreign_key_src; + delete foreign_key_src.second; } foreign_key_sources_.clear(); @@ -156,10 +156,9 @@ bool DataTable::CheckConstraints(const AbstractTuple *tuple) const { // look at each column individually. oid_t column_count = schema->GetColumnCount(); for (oid_t column_itr = 0; column_itr < column_count; column_itr++) { - std::vector column_cons = - schema->GetColumn(column_itr).GetConstraints(); + auto column_cons = schema->GetColumn(column_itr).GetConstraints(); for (auto cons : column_cons) { - ConstraintType type = cons.GetType(); + ConstraintType type = cons->GetType(); switch (type) { case ConstraintType::NOTNULL: { if (CheckNotNulls(tuple, column_itr) == false) { @@ -755,7 +754,8 @@ bool DataTable::CheckForeignKeySrcAndCascade( */ bool DataTable::CheckForeignKeyConstraints( const AbstractTuple *tuple, concurrency::TransactionContext *transaction) { - for (auto foreign_key : foreign_keys_) { + for (auto foreign_key_pair : foreign_keys_) { + auto foreign_key = foreign_key_pair.second; oid_t sink_table_id = foreign_key->GetSinkTableOid(); storage::DataTable *ref_table = nullptr; try { @@ -1150,50 +1150,29 @@ oid_t DataTable::GetValidIndexCount() const { // FOREIGN KEYS //===--------------------------------------------------------------------===// -void DataTable::AddForeignKey(catalog::ForeignKey *key) { - { - std::lock_guard lock(data_table_mutex_); - catalog::Constraint constraint(ConstraintType::FOREIGN, - key->GetConstraintName()); - constraint.SetForeignKeyListOffset(GetForeignKeyCount()); - for (auto fk_column : key->GetSourceColumnIds()) { - schema->AddConstraint(fk_column, constraint); - } - foreign_keys_.push_back(key); - } -} - -catalog::ForeignKey *DataTable::GetForeignKey(const oid_t &key_offset) const { - catalog::ForeignKey *key = nullptr; - key = foreign_keys_.at(key_offset); - return key; +void DataTable::AddForeignKey(oid_t constraint_oid, + catalog::ForeignKey *key) { + std::lock_guard lock(data_table_mutex_); + foreign_keys_[constraint_oid] = key; } -void DataTable::DropForeignKey(const oid_t &key_offset) { - { - std::lock_guard lock(data_table_mutex_); - PELOTON_ASSERT(key_offset < foreign_keys_.size()); - foreign_keys_.erase(foreign_keys_.begin() + key_offset); - } +void DataTable::DropForeignKey(oid_t constraint_oid) { + std::lock_guard lock(data_table_mutex_); + foreign_keys_.erase(constraint_oid); } -size_t DataTable::GetForeignKeyCount() const { return foreign_keys_.size(); } - // Adds to the list of tables for which this table's PK is the foreign key sink -void DataTable::RegisterForeignKeySource(catalog::ForeignKey *key) { - { - std::lock_guard lock(data_table_mutex_); - foreign_key_sources_.push_back(key); - } +void DataTable::RegisterForeignKeySource(oid_t constraint_oid, + catalog::ForeignKey *key) { + std::lock_guard lock(data_table_mutex_); + foreign_key_sources_[constraint_oid] = key; } -size_t DataTable::GetForeignKeySrcCount() const { - return foreign_key_sources_.size(); +void DataTable::DropForeignKeySrc(oid_t constraint_oid) { + std::lock_guard lock(data_table_mutex_); + foreign_key_sources_.erase(constraint_oid); } -catalog::ForeignKey *DataTable::GetForeignKeySrc(const size_t offset) const { - return foreign_key_sources_[offset]; -} // Get the schema for the new transformed tile group std::vector TransformTileGroupSchema( diff --git a/src/storage/database.cpp b/src/storage/database.cpp index 8a7506805c8..8d7e9ed2131 100644 --- a/src/storage/database.cpp +++ b/src/storage/database.cpp @@ -149,12 +149,8 @@ const std::string Database::GetInfo() const { if (table->HasForeignKeys()) { os << "foreign tables \n"; - oid_t foreign_key_count = table->GetForeignKeyCount(); - for (oid_t foreign_key_itr = 0; foreign_key_itr < foreign_key_count; - foreign_key_itr++) { - auto foreign_key = table->GetForeignKey(foreign_key_itr); - - auto sink_table_oid = foreign_key->GetSinkTableOid(); + for (auto foreign_key : table->GetForeignKeys()) { + auto sink_table_oid = foreign_key.second->GetSinkTableOid(); auto sink_table = GetTableWithOid(sink_table_oid); os << "table name : " << sink_table->GetName() << std::endl; diff --git a/test/catalog/catalog_test.cpp b/test/catalog/catalog_test.cpp index 36af866b958..9d9cc0abe48 100644 --- a/test/catalog/catalog_test.cpp +++ b/test/catalog/catalog_test.cpp @@ -11,9 +11,11 @@ //===----------------------------------------------------------------------===// #include "catalog/catalog.h" +#include "catalog/column.h" #include "catalog/column_catalog.h" #include "catalog/database_catalog.h" #include "catalog/database_metrics_catalog.h" +#include "catalog/foreign_key.h" #include "catalog/index_catalog.h" #include "catalog/layout_catalog.h" #include "catalog/query_metrics_catalog.h" @@ -25,6 +27,7 @@ #include "sql/testing_sql_util.h" #include "storage/storage_manager.h" #include "type/ephemeral_pool.h" +#include "type/value_factory.h" namespace peloton { namespace test { @@ -69,7 +72,7 @@ TEST_F(CatalogTests, CreatingTable) { type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); id_column.AddConstraint( - catalog::Constraint(ConstraintType::PRIMARY, "primary_key")); + std::make_shared(ConstraintType::PRIMARY, "primary_key")); auto name_column = catalog::Column(type::TypeId::VARCHAR, 32, "name", true); std::unique_ptr table_schema( @@ -413,5 +416,185 @@ TEST_F(CatalogTests, LayoutCatalogTest) { txn_manager.CommitTransaction(txn); } + +TEST_F(CatalogTests, ConstraintCatalogTest) { + auto db_name = "con_db"; + auto sink_table_name = "sink_table"; + auto con_table_name = "con_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 for foreign key. + auto sink_val0 = catalog::Column(type::TypeId::INTEGER, + type::Type::GetTypeSize(type::TypeId::INTEGER), "sink_val0", true); + sink_val0.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, "con_primary")); + std::unique_ptr sink_table_schema( + new catalog::Schema({sink_val0})); + EXPECT_EQ(ResultType::SUCCESS, + catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, sink_table_name, + std::move(sink_table_schema), txn)); + + // Create table for constraint catalog test. + auto con_val0 = catalog::Column(type::TypeId::INTEGER, + type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val0", true); + auto con_val1 = catalog::Column(type::TypeId::INTEGER, + type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val1", true); + auto con_val2 = catalog::Column(type::TypeId::INTEGER, + type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val2", true); + auto con_val3 = catalog::Column(type::TypeId::INTEGER, + type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val3", true); + auto con_val4 = catalog::Column(type::TypeId::INTEGER, + type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val4", true); + auto con_val5 = catalog::Column(type::TypeId::INTEGER, + type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val5", true); + auto con_val6 = catalog::Column(type::TypeId::INTEGER, + type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val6", true); + con_val0.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, "con_primary")); + con_val1.AddConstraint(std::make_shared( + ConstraintType::PRIMARY, "con_primary")); + con_val2.AddConstraint(std::make_shared( + ConstraintType::NOT_NULL, "con_not_null")); + con_val3.AddConstraint(std::make_shared( + ConstraintType::UNIQUE, "con_unique")); + std::shared_ptr con_def( + new catalog::Constraint(ConstraintType::DEFAULT, "con_default")); + con_def->addDefaultValue(type::ValueFactory::GetIntegerValue(0)); + con_val4.AddConstraint(con_def); + std::shared_ptr con_chk( + new catalog::Constraint(ConstraintType::CHECK, "con_check")); + con_chk->AddCheck(ExpressionType::COMPARE_GREATERTHAN, + type::ValueFactory::GetIntegerValue(0)); + con_val5.AddConstraint(con_chk); + std::unique_ptr con_table_schema( + new catalog::Schema({con_val0, con_val1, con_val2, con_val3, con_val4, + con_val5, con_val6})); + EXPECT_EQ(ResultType::SUCCESS, + catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, con_table_name, + std::move(con_table_schema), txn)); + + LOG_DEBUG("Success two table creations"); + + auto database_oid = + catalog->GetDatabaseObject(db_name, txn)->GetDatabaseOid(); + auto sink_table_object = + catalog->GetTableObject(db_name, DEFAULT_SCHEMA_NAME, sink_table_name, txn); + auto sink_table = + catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, sink_table_name, txn); + auto sink_table_oid = sink_table_object->GetTableOid(); + auto con_table_object = + catalog->GetTableObject(db_name, DEFAULT_SCHEMA_NAME, con_table_name, txn); + auto con_table = + catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, con_table_name, txn); + auto con_table_oid = con_table_object->GetTableOid(); + + LOG_DEBUG("create foreign key"); + + // Add foreign key + catalog->AddForeignKeyConstraint(database_oid, con_table_oid, {6}, + sink_table_oid, {0}, FKConstrActionType::NOACTION, + FKConstrActionType::NOACTION, "con_foreign", txn); + + LOG_DEBUG("Success all constraint creations"); + + // Check constraint + std::unique_ptr pool(new type::EphemeralPool()); + auto constraint_objects = sink_table_object->GetConstraintObjects(); + EXPECT_EQ(1, constraint_objects.size()); + for (auto constraint_object_pair : constraint_objects) { + auto con_oid = constraint_object_pair.first; + auto con_object = constraint_object_pair.second; + auto column_ids = con_object->GetColumnIds(); + EXPECT_LE(1, column_ids.size()); + for (auto column_id : column_ids) { + auto column = sink_table->GetSchema()->GetColumn(column_id); + auto constraint = column.GetConstraint(con_oid); + EXPECT_EQ(constraint->GetName(), con_object->GetConstraintName()); + EXPECT_EQ(constraint->GetType(), con_object->GetConstraintType()); + EXPECT_EQ(sink_table_oid, con_object->GetTableOid()); + EXPECT_EQ(constraint->GetIndexOid(), con_object->GetIndexOid()); + } + } + + LOG_DEBUG("Complete check for sink table"); + + constraint_objects = con_table_object->GetConstraintObjects(); + EXPECT_EQ(6, constraint_objects.size()); + for (auto constraint_object_pair : constraint_objects) { + auto con_oid = constraint_object_pair.first; + auto con_object = constraint_object_pair.second; + + LOG_DEBUG("Check constraint:%s (%s)", con_object->GetConstraintName().c_str(), + ConstraintTypeToString(con_object->GetConstraintType()).c_str()); + + auto column_ids = con_object->GetColumnIds(); + for (auto column_id : column_ids) { + auto column = con_table->GetSchema()->GetColumn(column_id); + auto constraint = column.GetConstraint(con_oid); + if (constraint == nullptr) continue; + EXPECT_EQ(constraint->GetName(), con_object->GetConstraintName()); + EXPECT_EQ(constraint->GetType(), con_object->GetConstraintType()); + EXPECT_EQ(con_table_oid, con_object->GetTableOid()); + EXPECT_EQ(constraint->GetIndexOid(), con_object->GetIndexOid()); + + if (con_object->GetConstraintType() == ConstraintType::FOREIGN) { + auto fk = con_table->GetForeignKey(con_object->GetConstraintOid()); + EXPECT_EQ(fk->GetConstraintName(), con_object->GetConstraintName()); + EXPECT_EQ(fk->GetSourceColumnIds().size(), column_ids.size()); + EXPECT_EQ(fk->GetSinkTableOid(), con_object->GetFKSinkTableOid()); + EXPECT_EQ(fk->GetSinkColumnIds().size(), + con_object->GetFKSinkColumnIds().size()); + EXPECT_EQ(fk->GetUpdateAction(), con_object->GetFKUpdateAction()); + EXPECT_EQ(fk->GetDeleteAction(), con_object->GetFKDeleteAction()); + } else if (con_object->GetConstraintType() == ConstraintType::DEFAULT) { + auto dv_str = con_object->GetDefaultValue(); + auto default_value = + type::Value::DeserializeFrom(dv_str.c_str(), column.GetType(), + column.IsInlined(), pool.get()); + EXPECT_EQ(constraint->getDefaultValue()->CompareEquals(default_value), + CmpBool::CmpTrue); + } else if (con_object->GetConstraintType() == ConstraintType::CHECK) { + EXPECT_EQ(constraint->GetCheckCmd(), con_object->GetCheckCmd()); + std::stringstream exp_ss(con_object->GetCheckExp().c_str()); + std::string exp_type_str, exp_value_str; + std::getline(exp_ss, exp_type_str, ' '); + std::getline(exp_ss, exp_value_str, ' '); + auto exp_value = type::Value::DeserializeFrom(exp_value_str.c_str(), + column.GetType(), column.IsInlined(), pool.get()); + auto exp_type = StringToExpressionType(exp_type_str); + EXPECT_EQ(constraint->GetCheckExpression().first, exp_type); + EXPECT_EQ(constraint->GetCheckExpression().second.CompareEquals(exp_value), + CmpBool::CmpTrue); + } + } + } + txn_manager.CommitTransaction(txn); + + LOG_DEBUG("Complete check for constraint table"); + + // Drop constraint + txn = txn_manager.BeginTransaction(); + for (auto column : con_table->GetSchema()->GetColumns()) { + for (auto constraint : column.GetConstraints()) { + auto result = catalog->DropConstraint(database_oid, con_table_oid, + constraint->GetConstraintOid(), txn); + EXPECT_EQ(ResultType::SUCCESS, result); + } + } + txn_manager.CommitTransaction(txn); + + LOG_DEBUG("Complete delete constraints in constraint table"); + + // Drop database + txn = txn_manager.BeginTransaction(); + catalog->DropDatabaseWithName(db_name, txn); + txn_manager.CommitTransaction(txn); +} + + } // namespace test } // namespace peloton diff --git a/test/codegen/testing_codegen_util.cpp b/test/codegen/testing_codegen_util.cpp index 5302eae3daf..55f57f835b9 100644 --- a/test/codegen/testing_codegen_util.cpp +++ b/test/codegen/testing_codegen_util.cpp @@ -89,15 +89,15 @@ std::unique_ptr PelotonCodeGenTest::CreateTestSchema( // Add NOT NULL constraints on COL_A, COL_C, COL_D cols[0].AddConstraint( - catalog::Constraint{ConstraintType::NOTNULL, "not_null"}); + std::make_shared(ConstraintType::NOTNULL, "not_null")); if (add_primary) { cols[0].AddConstraint( - catalog::Constraint{ConstraintType::PRIMARY, "con_primary"}); + std::make_shared(ConstraintType::PRIMARY, "con_primary")); } cols[2].AddConstraint( - catalog::Constraint{ConstraintType::NOTNULL, "not_null"}); + std::make_shared(ConstraintType::NOTNULL, "not_null")); cols[3].AddConstraint( - catalog::Constraint{ConstraintType::NOTNULL, "not_null"}); + std::make_shared(ConstraintType::NOTNULL, "not_null")); // Return the schema return std::unique_ptr{new catalog::Schema(cols)}; diff --git a/test/concurrency/testing_transaction_util.cpp b/test/concurrency/testing_transaction_util.cpp index 7f61cc0b765..5f45a0f16af 100644 --- a/test/concurrency/testing_transaction_util.cpp +++ b/test/concurrency/testing_transaction_util.cpp @@ -44,12 +44,12 @@ storage::DataTable *TestingTransactionUtil::CreateCombinedPrimaryKeyTable() { type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, "not_null")); + std::make_shared(ConstraintType::NOTNULL, "not_null")); auto value_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "value", true); value_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, "not_null")); + std::make_shared(ConstraintType::NOTNULL, "not_null")); // Create the table catalog::Schema *table_schema = @@ -93,7 +93,7 @@ storage::DataTable *TestingTransactionUtil::CreatePrimaryKeyUniqueKeyTable() { type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, "not_null")); + std::make_shared(ConstraintType::NOTNULL, "not_null")); auto value_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "value", true); diff --git a/test/executor/testing_executor_util.cpp b/test/executor/testing_executor_util.cpp index cd923c11ed8..fc061c78a69 100644 --- a/test/executor/testing_executor_util.cpp +++ b/test/executor/testing_executor_util.cpp @@ -89,8 +89,8 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "COL_A", is_inlined); - column.AddConstraint(catalog::Constraint(ConstraintType::NOTNULL, - not_null_constraint_name)); + column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); return column; } break; @@ -99,8 +99,8 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "COL_B", is_inlined); - column.AddConstraint(catalog::Constraint(ConstraintType::NOTNULL, - not_null_constraint_name)); + column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); return column; } break; @@ -109,8 +109,8 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { type::TypeId::DECIMAL, type::Type::GetTypeSize(type::TypeId::DECIMAL), "COL_C", is_inlined); - column.AddConstraint(catalog::Constraint(ConstraintType::NOTNULL, - not_null_constraint_name)); + column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); return column; } break; @@ -119,8 +119,8 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { catalog::Column(type::TypeId::VARCHAR, 25, // Column length. "COL_D", !is_inlined); // inlined. - column.AddConstraint(catalog::Constraint(ConstraintType::NOTNULL, - not_null_constraint_name)); + column.AddConstraint(std::make_shared( + ConstraintType::NOTNULL, not_null_constraint_name)); return column; } break; diff --git a/test/statistics/testing_stats_util.cpp b/test/statistics/testing_stats_util.cpp index 5c087e4aba4..dca7aca2dee 100644 --- a/test/statistics/testing_stats_util.cpp +++ b/test/statistics/testing_stats_util.cpp @@ -113,7 +113,8 @@ void TestingStatsUtil::CreateTable(bool has_primary_key) { type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "dept_id", true); if (has_primary_key) { - catalog::Constraint constraint(ConstraintType::PRIMARY, "con_primary"); + std::shared_ptr constraint( + new catalog::Constraint(ConstraintType::PRIMARY, "con_primary")); id_column.AddConstraint(constraint); } auto name_column = From f05450c97fc5ff0a013c1966947d68159273da12 Mon Sep 17 00:00:00 2001 From: ksaito7 Date: Sat, 16 Jun 2018 09:26:37 -0400 Subject: [PATCH 02/10] Reconstruct constraints --- src/catalog/abstract_catalog.cpp | 21 +- src/catalog/catalog.cpp | 424 +++++++++++++----- src/catalog/column.cpp | 62 +-- src/catalog/column_catalog.cpp | 147 ++++-- src/catalog/constraint.cpp | 37 +- src/catalog/constraint_catalog.cpp | 212 +++------ src/catalog/database_catalog.cpp | 29 +- src/catalog/index_catalog.cpp | 60 ++- src/catalog/layout_catalog.cpp | 32 +- src/catalog/manager.cpp | 1 - src/catalog/multi_constraint.cpp | 39 -- src/catalog/schema.cpp | 24 +- src/catalog/schema_catalog.cpp | 31 +- src/catalog/system_catalogs.cpp | 20 +- src/catalog/table_catalog.cpp | 52 +-- src/common/internal_types.cpp | 27 -- src/executor/create_executor.cpp | 159 ++++--- src/executor/update_executor.cpp | 3 +- src/include/catalog/catalog.h | 85 ++-- src/include/catalog/catalog_defaults.h | 28 +- src/include/catalog/column.h | 113 ++--- src/include/catalog/column_catalog.h | 23 +- src/include/catalog/constraint.h | 106 +++-- src/include/catalog/constraint_catalog.h | 26 +- src/include/catalog/foreign_key.h | 76 ---- src/include/catalog/multi_constraint.h | 70 --- src/include/catalog/schema.h | 180 ++++++-- src/include/common/internal_types.h | 13 +- src/include/planner/create_plan.h | 40 +- src/include/storage/abstract_table.h | 10 - src/include/storage/data_table.h | 49 +- src/include/storage/temp_table.h | 6 - .../stats/column_stats_collector.cpp | 9 +- src/optimizer/stats/stats_storage.cpp | 2 +- src/planner/create_plan.cpp | 145 +++--- src/planner/update_plan.cpp | 12 +- src/storage/data_table.cpp | 199 +++----- src/storage/database.cpp | 7 +- test/catalog/catalog_test.cpp | 278 +++++++----- test/catalog/constraints_test.cpp | 134 +++--- test/codegen/testing_codegen_util.cpp | 28 +- test/common/internal_types_test.cpp | 8 +- test/concurrency/testing_transaction_util.cpp | 39 +- test/executor/drop_test.cpp | 2 +- test/executor/testing_executor_util.cpp | 21 +- test/executor/update_test.cpp | 19 +- test/gc/garbage_collection_test.cpp | 13 +- test/gc/transaction_level_gc_manager_test.cpp | 18 +- .../catalog/testing_constraints_util.h | 55 +-- test/include/codegen/testing_codegen_util.h | 3 +- test/optimizer/stats_storage_test.cpp | 2 +- test/planner/plan_util_test.cpp | 16 +- test/planner/planner_test.cpp | 6 +- test/sql/optimizer_sql_test.cpp | 2 +- test/statistics/stats_test.cpp | 6 +- test/statistics/testing_stats_util.cpp | 26 +- 56 files changed, 1718 insertions(+), 1537 deletions(-) delete mode 100644 src/catalog/multi_constraint.cpp delete mode 100644 src/include/catalog/foreign_key.h delete mode 100644 src/include/catalog/multi_constraint.h diff --git a/src/catalog/abstract_catalog.cpp b/src/catalog/abstract_catalog.cpp index 53c0b938279..bdbe468495a 100644 --- a/src/catalog/abstract_catalog.cpp +++ b/src/catalog/abstract_catalog.cpp @@ -29,6 +29,7 @@ #include "planner/seq_scan_plan.h" #include "executor/executor_context.h" +#include "executor/create_executor.h" #include "executor/delete_executor.h" #include "executor/index_scan_executor.h" #include "executor/insert_executor.h" @@ -59,24 +60,22 @@ AbstractCatalog::AbstractCatalog(oid_t catalog_table_oid, AbstractCatalog::AbstractCatalog(const std::string &catalog_table_ddl, concurrency::TransactionContext *txn) { - // get catalog table schema + // Execute create catalog table auto &peloton_parser = parser::PostgresParser::GetInstance(); + std::unique_ptr context( + new executor::ExecutorContext(txn)); auto create_plan = std::dynamic_pointer_cast( optimizer::Optimizer().BuildPelotonPlanTree( peloton_parser.BuildParseTree(catalog_table_ddl), txn)); - auto catalog_table_schema = create_plan->GetSchema(); - auto catalog_table_name = create_plan->GetTableName(); - auto catalog_schema_name = create_plan->GetSchemaName(); - auto catalog_database_name = create_plan->GetDatabaseName(); - PELOTON_ASSERT(catalog_schema_name == std::string(CATALOG_SCHEMA_NAME)); - // create catalog table - Catalog::GetInstance()->CreateTable( - catalog_database_name, catalog_schema_name, catalog_table_name, - std::unique_ptr(catalog_table_schema), txn, true); + executor::CreateExecutor executor(create_plan.get(), context.get()); + + executor.Init(); + executor.Execute(); // get catalog table oid auto catalog_table_object = Catalog::GetInstance()->GetTableObject( - catalog_database_name, catalog_schema_name, catalog_table_name, txn); + create_plan->GetDatabaseName(), create_plan->GetSchemaName(), + create_plan->GetTableName(), txn); // set catalog_table_ try { diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 2c3071668fe..3a86766b906 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -16,7 +16,6 @@ #include "catalog/constraint_catalog.h" #include "catalog/database_catalog.h" #include "catalog/database_metrics_catalog.h" -#include "catalog/foreign_key.h" #include "catalog/index_catalog.h" #include "catalog/index_metrics_catalog.h" #include "catalog/language_catalog.h" @@ -398,7 +397,7 @@ ResultType Catalog::CreateTable(const std::string &database_name, database_object->GetDatabaseOid(), table->GetDefaultLayout()->GetOid(), pool_.get(), txn); - // Insert column info and constraint info into each catalog + // Insert column info into each catalog oid_t column_id = 0; std::vector pkey_attrs, unique_attrs; std::shared_ptr pkey_constraint, unique_constraint; @@ -406,35 +405,11 @@ ResultType Catalog::CreateTable(const std::string &database_name, pg_attribute->InsertColumn(table_oid, column.GetName(), column_id, column.GetOffset(), column.GetType(), column.GetLength(), column.IsInlined(), - column.IsNotNull(), column.IsDefault(), + column.IsNotNull(), column.HasDefault(), column.GetDefaultValue(), pool_.get(), txn); - - // Add constraint information into the catalog and create index if need - for (auto constraint : column.GetConstraints()) { - if (constraint->GetType() == ConstraintType::PRIMARY) { - pkey_attrs.push_back(column_id); - pkey_constraint = constraint; - } - else if (constraint->GetType() == ConstraintType::UNIQUE) { - unique_attrs.push_back(column_id); - unique_constraint = constraint; - } - else if (constraint->GetType() != ConstraintType::FOREIGN) { - AddConstraint(database->GetOid(), table_oid, {column_id}, constraint, txn); - } - } - column_id++; } - // Add multi-column constraint for primary key and unique - if (pkey_attrs.size() > 0) { - AddConstraint(database->GetOid(), table_oid, pkey_attrs, pkey_constraint, txn); - } - if (unique_attrs.size() > 0) { - AddConstraint(database->GetOid(), table_oid, unique_attrs, unique_constraint, txn); - } - // Create layout as default layout auto pg_layout = catalog_map_[database_object->GetDatabaseOid()]->GetLayoutCatalog(); @@ -600,64 +575,186 @@ std::shared_ptr Catalog::CreateDefaultLayout( } //===--------------------------------------------------------------------===// -// ADD FUNCTIONS +// SET FUNCTIONS FOR COLUMN CONSTRAINT +//===--------------------------------------------------------------------===// + +/** + * @brief Set not null constraint for a column + * @param database_oid Database to which the table belongs to + * @param table_oid Table to which the constraint has to be set + * @param column_id Column that the constraint affects + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + */ +ResultType Catalog::SetNotNullConstraint(oid_t database_oid, oid_t table_oid, + oid_t column_id, concurrency::TransactionContext *txn) { + auto table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn); + auto schema = storage::StorageManager::GetInstance() + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); + auto column = schema->GetColumn(column_id); + + // Check not null + if (column.IsNotNull()) { + throw CatalogException("Column " + column.GetName() + + " in table " + table_object->GetTableName() + + " is already NOT NULL."); + } + + + // Update pg_column to set constraint of the column + auto pg_column = catalog_map_[database_oid]->GetColumnCatalog(); + pg_column->UpdateNotNullConstraint(table_oid, column.GetName(), true, txn); + + // Set not null constraint in the schema + { + std::lock_guard lock(catalog_mutex); + schema->SetNotNull(column_id); + } + + return ResultType::SUCCESS; +} + +/** + * @brief Set default constraint for a column + * @param database_oid Database to which the table belongs to + * @param table_oid Table to which the constraint has to be set + * @param column_id Column that the constraint affects + * @param default_value Value for the default constraint + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + */ +ResultType Catalog::SetDefaultConstraint(oid_t database_oid, oid_t table_oid, + oid_t column_id, const type::Value &default_value, + concurrency::TransactionContext *txn) { + auto table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn); + auto schema = storage::StorageManager::GetInstance() + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); + auto column = schema->GetColumn(column_id); + + // Check default + if (column.HasDefault()) { + throw CatalogException("Column " + column.GetName() + + " in table" + table_object->GetTableName() + + " is already set default value '" + column.GetDefaultValue()->ToString() + + "'."); + } + + // Update pg_column to set constraint of the column + auto pg_column = catalog_map_[database_oid]->GetColumnCatalog(); + pg_column->UpdateDefaultConstraint(table_oid, column.GetName(), true, &default_value, txn); + + // Set default constraint in the schema + { + std::lock_guard lock(catalog_mutex); + schema->SetDefaultValue(column_id, default_value); + } + + return ResultType::SUCCESS; +} + + +//===--------------------------------------------------------------------===// +// ADD FUNCTIONS FOR TABLE CONSTRAINT //===--------------------------------------------------------------------===// /** - * @brief Add a new constraint for a table except for foreign key + * @brief Add a new primary constraint for a table * @param database_oid Database to which the table belongs to * @param table_oid Table to which the constraint has to be added * @param column_ids Columns that the constraint affects - * @param constraint The new constraint to be registered + * @param constraint_name constraint name * @param txn TransactionContext * @return ResultType(SUCCESS or FAILURE) - * note: if add a new foreign key constraint, use AddForeignKeyConstraint */ -ResultType Catalog::AddConstraint(oid_t database_oid, oid_t table_oid, - const std::vector &column_ids, std::shared_ptr constraint, +ResultType Catalog::AddPrimaryKeyConstraint(oid_t database_oid, oid_t table_oid, + const std::vector &column_ids, const std::string &constraint_name, concurrency::TransactionContext *txn) { auto table_object = catalog_map_[database_oid]->GetTableCatalog() ->GetTableObject(table_oid, txn); - auto storage_manager = storage::StorageManager::GetInstance(); - auto table = storage_manager->GetTableWithOid(database_oid, table_oid); - auto schema = table->GetSchema(); - - // If constraint is PRIMARY KEY or UNIQUE, create index - auto index_oid = INVALID_OID; - if (constraint->GetType() == ConstraintType::PRIMARY) { - std::string index_name = table_object->GetTableName() + "_pkey"; - index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); - CreateIndex(database_oid, table_oid, column_ids, table_object->GetSchemaName(), - index_oid, index_name, IndexType::BWTREE, - IndexConstraintType::PRIMARY_KEY, true, txn); - LOG_DEBUG("Added a PRIMARY KEY index in %s.", - table_object->GetTableName().c_str()); - - // set index oid to constraint - constraint->SetIndexOid(index_oid); - - } else if (constraint->GetType() == ConstraintType::UNIQUE) { - // create index for unique - std::stringstream index_name(table->GetName().c_str()); - for (auto column_id : column_ids) - index_name << "_" + schema->GetColumn(column_id).GetName(); - index_name << "_UNIQ"; - index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); - CreateIndex(database_oid, table_oid, column_ids, table_object->GetSchemaName(), - index_oid, index_name.str(), IndexType::BWTREE, - IndexConstraintType::UNIQUE, true, txn); - LOG_DEBUG("Added a UNIQUE index in %s.", - table_object->GetTableName().c_str()); - - // set index oid to constraint - constraint->SetIndexOid(index_oid); + auto schema = storage::StorageManager::GetInstance() + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); + + // Check primary key in the table + if (schema->HasPrimary()) { + throw CatalogException("Table " + table_object->GetTableName() + + " already has primary key."); } + // Create index + std::string index_name = table_object->GetTableName() + "_pkey"; + auto index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); + CreateIndex(database_oid, table_oid, column_ids, table_object->GetSchemaName(), + index_oid, index_name, IndexType::BWTREE, + IndexConstraintType::PRIMARY_KEY, true, txn); + // Insert constraint into pg_constraint auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); - constraint->SetConstraintOid(pg_constraint->GetNextOid()); - pg_constraint->InsertConstraint(table_oid, column_ids, constraint, - pool_.get(), txn); + std::shared_ptr constraint( + new Constraint(pg_constraint->GetNextOid(), ConstraintType::PRIMARY, + constraint_name, table_oid, column_ids, index_oid)); + pg_constraint->InsertConstraint(constraint, pool_.get(), txn); + + // Add constraint into the schema + { + std::lock_guard lock(catalog_mutex); + schema->AddConstraint(constraint); + } + + LOG_DEBUG("Added a PRIMARY KEY constraint in %s.", + table_object->GetTableName().c_str()); + + return ResultType::SUCCESS; +} + +/** + * @brief Add a new unique constraint for a table + * @param database_oid Database to which the table belongs to + * @param table_oid Table to which the constraint has to be added + * @param column_ids Columns that the constraint affects + * @param constraint_name constraint name + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + * note: if add a new foreign key constraint, use AddForeignKeyConstraint + */ +ResultType Catalog::AddUniqueConstraint(oid_t database_oid, oid_t table_oid, + const std::vector &column_ids, const std::string &constraint_name, + concurrency::TransactionContext *txn) { + auto table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn); + auto schema = storage::StorageManager::GetInstance() + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); + + // Create index + std::stringstream index_name(table_object->GetTableName().c_str()); + for (auto column_id : column_ids) + index_name << "_" + schema->GetColumn(column_id).GetName(); + index_name << "_UNIQ"; + auto index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); + CreateIndex(database_oid, table_oid, column_ids, table_object->GetSchemaName(), + index_oid, index_name.str(), IndexType::BWTREE, + IndexConstraintType::UNIQUE, true, txn); + + // Insert constraint into pg_constraint + auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); + std::shared_ptr constraint( + new Constraint(pg_constraint->GetNextOid(), ConstraintType::UNIQUE, + constraint_name, table_oid, column_ids, index_oid)); + pg_constraint->InsertConstraint(constraint, pool_.get(), txn); + + // Add constraint into the schema + { + std::lock_guard lock(catalog_mutex); + schema->AddConstraint(constraint); + } + + LOG_DEBUG("Added a UNIQUE constraint in %s.", + table_object->GetTableName().c_str()); return ResultType::SUCCESS; } @@ -667,8 +764,8 @@ ResultType Catalog::AddConstraint(oid_t database_oid, oid_t table_oid, * @param database_oid database to which the table belongs to * @param src_table_oid table to which the constraint has to be added * @param src_col_ids Columns that the constraint affects - * @param snk_table_oid sink table - * @param snk_col_ids Columns that limit the source columns + * @param sink_table_oid sink table + * @param sink_col_ids Columns that limit the source columns * @param upd_action foreign key constraint action when update * @param del_action foreign key constraint action when delete * @param constraint_name constraint name @@ -690,18 +787,6 @@ ResultType Catalog::AddForeignKeyConstraint(oid_t database_oid, auto sink_table = storage_manager->GetTableWithOid(database_oid, sink_table_oid); - // Create the catalog object and shove it into the table - auto src_fk = new catalog::ForeignKey( - INVALID_OID, sink_table_oid, sink_col_ids, src_col_ids, - upd_action, del_action, constraint_name); - src_table->AddForeignKey(constraint_oid, src_fk); - - // Register FK with the sink table for delete/update actions - auto sink_fk = new catalog::ForeignKey( - src_table_oid, INVALID_OID, sink_col_ids, src_col_ids, - upd_action, del_action, constraint_name); - sink_table->RegisterForeignKeySource(constraint_oid, sink_fk); - // Add a non-unique index on the source table if needed auto src_table_object = catalog_map_[database_oid]->GetTableCatalog() ->GetTableObject(src_table_oid, txn); @@ -718,24 +803,69 @@ ResultType Catalog::AddForeignKeyConstraint(oid_t database_oid, // Insert constraint into pg_constraint std::shared_ptr constraint( - new Constraint(ConstraintType::FOREIGN, constraint_name, index_oid)); - constraint->SetConstraintOid(constraint_oid); - ForeignKey fk(src_table_oid, sink_table_oid, sink_col_ids, src_col_ids, - upd_action, del_action, constraint_name); - pg_constraint->InsertConstraint(src_table_oid, src_col_ids, constraint, - fk, pool_.get(), txn); - - // add constraint into schema in source table + new Constraint(constraint_oid, ConstraintType::FOREIGN, constraint_name, + src_table_oid, src_col_ids, index_oid, sink_table_oid, + sink_col_ids, upd_action, del_action)); + pg_constraint->InsertConstraint(constraint, pool_.get(), txn); + + // add constraint into schema in source table and sink table { std::lock_guard lock(catalog_mutex); - for (auto fk_column : src_col_ids) { - src_schema->AddConstraint(fk_column, constraint); - } + src_schema->AddConstraint(constraint); + sink_table->GetSchema()->RegisterForeignKeySource(constraint); } + LOG_DEBUG("Added a FOREIGN KEY constraint in %s to %s.", + src_table_object->GetTableName().c_str(), + catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(sink_table_oid, txn) + ->GetTableName().c_str()); + return ResultType::SUCCESS; } +/** + * @brief Add a new check constraint for a table + * @param database_oid Database to which the table belongs to + * @param table_oid Table to which the constraint has to be added + * @param column_ids Columns that the constraint affects + * @param cmd Command string for check constraint + * @param exp Expression for check constraint + * @param constraint_name constraint name + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + * note: if add a new foreign key constraint, use AddForeignKeyConstraint + */ +ResultType Catalog::AddCheckConstraint(oid_t database_oid, oid_t table_oid, + const std::vector &column_ids, + const std::pair &exp, + const std::string &constraint_name, + concurrency::TransactionContext *txn) { + auto table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn); + auto schema = storage::StorageManager::GetInstance() + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); + + // Insert constraint into pg_constraint + auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); + std::shared_ptr constraint( + new Constraint(pg_constraint->GetNextOid(), ConstraintType::CHECK, + constraint_name, table_oid, column_ids, INVALID_OID, + exp)); + pg_constraint->InsertConstraint(constraint, pool_.get(), txn); + + // Add constraint into the schema + { + std::lock_guard lock(catalog_mutex); + schema->AddConstraint(constraint); + } + + LOG_DEBUG("Added a CHECK constraint in %s.", + table_object->GetTableName().c_str()); + + return ResultType::SUCCESS; +} //===----------------------------------------------------------------------===// // DROP FUNCTIONS @@ -990,10 +1120,88 @@ ResultType Catalog::DropLayout(oid_t database_oid, oid_t table_oid, return ResultType::SUCCESS; } + /** - * @brief Drop a new foreign key constraint for a table + * @brief Drop not null constraint for a column * @param database_oid the database to which the table belongs to - * @param table_oid the table to which the layout belongs + * @param table_oid the table to which the column belongs to + * @param column_id the column which has the not null constraint + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + */ +ResultType Catalog::DropNotNullConstraint(oid_t database_oid, + oid_t table_oid, oid_t column_id, + concurrency::TransactionContext *txn) { + auto table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn); + auto schema = storage::StorageManager::GetInstance() + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); + auto column = schema->GetColumn(column_id); + + // Check not null + if (!column.IsNotNull()) { + throw CatalogException("Column " + column.GetName() + + " in table " + table_object->GetTableName() + + " isn't NOT NULL."); + } + + // Update pg_column to set constraint of the column + auto pg_column = catalog_map_[database_oid]->GetColumnCatalog(); + pg_column->UpdateNotNullConstraint(table_oid, column.GetName(), false, txn); + + // Set not null constraint in the schema + { + std::lock_guard lock(catalog_mutex); + schema->DropNotNull(column_id); + } + + return ResultType::SUCCESS; + +} + +/** + * @brief Drop default constraint for a column + * @param database_oid the database to which the table belongs to + * @param table_oid the table to which the column belongs to + * @param column_id the column which has the default constraint + * @param txn TransactionContext + * @return ResultType(SUCCESS or FAILURE) + */ +ResultType Catalog::DropDefaultConstraint(oid_t database_oid, + oid_t table_oid, oid_t column_id, + concurrency::TransactionContext *txn) { + auto table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn); + auto schema = storage::StorageManager::GetInstance() + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); + auto column = schema->GetColumn(column_id); + + // Check default + if (!column.HasDefault()) { + throw CatalogException("Column " + column.GetName() + + " in table" + table_object->GetTableName() + + " doesn't have default value."); + } + + // Update pg_column to set constraint of the column + auto pg_column = catalog_map_[database_oid]->GetColumnCatalog(); + pg_column->UpdateDefaultConstraint(table_oid, column.GetName(), false, nullptr, txn); + + // Set default constraint in the schema + { + std::lock_guard lock(catalog_mutex); + schema->DropDefaultValue(column_id); + } + + return ResultType::SUCCESS; +} + +/** + * @brief Drop a constraint for a table + * @param database_oid the database to which the table belongs to + * @param table_oid the table which has the constraint * @param constraint_oid the constraint to be dropped * @param txn TransactionContext * @return ResultType(SUCCESS or FAILURE) @@ -1007,8 +1215,8 @@ ResultType Catalog::DropConstraint(oid_t database_oid, oid_t table_oid, // delete constraint object from pg_constraint if (!pg_constraint->DeleteConstraint(table_oid, constraint_oid, txn)) { - LOG_DEBUG("Failed to delete the constraint: %d", constraint_oid); - return ResultType::FAILURE; + throw CatalogException("Failed to delete the constraint: " + + std::to_string(constraint_oid)); } // delete index if exists @@ -1019,17 +1227,21 @@ ResultType Catalog::DropConstraint(oid_t database_oid, oid_t table_oid, // delete constraint from table auto storage_manager = storage::StorageManager::GetInstance(); auto table = storage_manager->GetTableWithOid(database_oid, table_oid); + table->GetSchema()->DropConstraint(constraint_oid); if (constraint_object->GetConstraintType() == ConstraintType::FOREIGN) { - auto sink_table = storage_manager->GetTableWithOid(database_oid, - constraint_object->GetFKSinkTableOid()); - table->DropForeignKey(constraint_object->GetConstraintOid()); - sink_table->DropForeignKeySrc(constraint_object->GetConstraintOid()); - } - if (!table->GetSchema()->DeleteConstraint(table_oid, constraint_oid)) { - LOG_DEBUG("Failed to delete the constraint: %d", constraint_oid); - return ResultType::FAILURE; + auto sink_table = storage_manager + ->GetTableWithOid(database_oid, + constraint_object->GetFKSinkTableOid()); + sink_table->GetSchema() + ->DeleteForeignKeySource(constraint_object->GetConstraintOid()); } + LOG_DEBUG("Drop a %s constraint in %s.", + ConstraintTypeToString(constraint_object->GetConstraintType()).c_str(), + catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn) + ->GetTableName().c_str()); + return ResultType::SUCCESS; } diff --git a/src/catalog/column.cpp b/src/catalog/column.cpp index 2dd10d0b144..be841da3392 100644 --- a/src/catalog/column.cpp +++ b/src/catalog/column.cpp @@ -21,68 +21,50 @@ namespace catalog { void Column::SetLength(size_t column_length) { // Set the column length based on whether it is inlined - if (is_inlined) { - fixed_length = column_length; - variable_length = 0; + if (is_inlined_) { + fixed_length_ = column_length; + variable_length_ = 0; } else { - fixed_length = sizeof(uintptr_t); - variable_length = column_length; + fixed_length_ = sizeof(uintptr_t); + variable_length_ = column_length; } } void Column::SetInlined() { - switch (column_type) { + switch (column_type_) { case type::TypeId::VARCHAR: case type::TypeId::VARBINARY: break; // No change of inlined setting default: - is_inlined = true; + is_inlined_ = true; break; } } -bool Column::DeleteConstraint(oid_t constraint_oid) { - for (auto const_itr = constraints.begin(); const_itr != constraints.end(); - const_itr++) { - if ((*const_itr)->GetConstraintOid() == constraint_oid) { - if ((*const_itr)->GetType() == ConstraintType::PRIMARY) { - is_primary_ = false; - } else if ((*const_itr)->GetType() == ConstraintType::UNIQUE) { - is_unique_ = false; - } - constraints.erase(const_itr); - return true; - } - } - return false; -} - const std::string Column::GetInfo() const { std::ostringstream os; - os << "Column[" << column_name << ", " << TypeIdToString(column_type) << ", " - << "Offset:" << column_offset << ", "; + os << "Column[" << column_name_ << ", " + << TypeIdToString(column_type_) << ", " + << "Offset:" << column_offset_ << ", "; - if (is_inlined) { - os << "FixedLength:" << fixed_length; + if (is_inlined_) { + os << "FixedLength:" << fixed_length_; } else { - os << "VarLength:" << variable_length; + os << "VarLength:" << variable_length_; } - if (constraints.empty() == false) { - os << ", {"; - bool first = true; - for (auto constraint : constraints) { - if (first) { - first = false; - } else { - os << ", "; - } - os << constraint->GetInfo(); - } - os << "}"; + if (is_not_null_ && has_default_) { + os << ", {NOT NULL, DEFAULT:" + << default_value_->ToString() << "}"; + } else if (is_not_null_) { + os << ", {NOT NULL}"; + } else if (has_default_) { + os << ", {DEFAULT:" + << default_value_->ToString() << "}"; } + os << "]"; return (os.str()); diff --git a/src/catalog/column_catalog.cpp b/src/catalog/column_catalog.cpp index cba9206f272..6c8a8b06022 100644 --- a/src/catalog/column_catalog.cpp +++ b/src/catalog/column_catalog.cpp @@ -18,6 +18,7 @@ #include "concurrency/transaction_context.h" #include "storage/data_table.h" #include "storage/database.h" +#include "type/ephemeral_pool.h" #include "type/value_factory.h" namespace peloton { @@ -44,15 +45,13 @@ ColumnCatalogObject::ColumnCatalogObject(executor::LogicalTile *tile, .GetAs()), is_not_null(tile->GetValue(tupleId, ColumnCatalog::ColumnId::IS_NOT_NULL) .GetAs()), - is_default(tile->GetValue(tupleId, ColumnCatalog::ColumnId::IS_DEFAULT) + has_default(tile->GetValue(tupleId, ColumnCatalog::ColumnId::HAS_DEFAULT) .GetAs()) { // deserialize default value if the column has default constraint - if (is_default) { - std::unique_ptr pool(new type::EphemeralPool()); - auto default_value_str = tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::DEFAULT_VALUE).ToString(); - default_value = type::Value::DeserializeFrom(default_value_str.c_str(), - column_type, is_inlined, pool.get()); + if (has_default) { + auto dv_val = tile->GetValue(tupleId, ColumnCatalog::ColumnId::DEFAULT_VALUE_BIN); + CopySerializeInput input_buffer(dv_val.GetData(), dv_val.GetLength()); + default_value = type::Value::DeserializeFrom(input_buffer, column_type); } } @@ -76,7 +75,7 @@ ColumnCatalog::ColumnCatalog(storage::Database *pg_catalog, for (auto column : catalog_table_->GetSchema()->GetColumns()) { InsertColumn(COLUMN_CATALOG_OID, column.GetName(), column_id, column.GetOffset(), column.GetType(), column.GetLength(), - column.IsInlined(), column.IsNotNull(), column.IsDefault(), + column.IsInlined(), column.IsNotNull(), column.HasDefault(), column.GetDefaultValue(), pool, txn); column_id++; } @@ -88,33 +87,18 @@ ColumnCatalog::~ColumnCatalog() {} * @return unqiue pointer to schema */ std::unique_ptr ColumnCatalog::InitializeSchema() { - const std::string primary_key_constraint_name = "con_primary"; - const std::string unique_constraint_name = "con_unique"; - auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, primary_key_constraint_name, - COLUMN_CATALOG_PKEY_OID)); - table_id_column.AddConstraint(std::make_shared( - ConstraintType::UNIQUE, unique_constraint_name, - COLUMN_CATALOG_SKEY0_OID)); table_id_column.SetNotNull(); auto column_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "column_name", false); - column_name_column.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, primary_key_constraint_name, - COLUMN_CATALOG_PKEY_OID)); column_name_column.SetNotNull(); auto column_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "column_id", true); - column_id_column.AddConstraint(std::make_shared( - ConstraintType::UNIQUE, unique_constraint_name, - COLUMN_CATALOG_SKEY0_OID)); column_id_column.SetNotNull(); auto column_offset_column = catalog::Column( @@ -141,20 +125,34 @@ std::unique_ptr ColumnCatalog::InitializeSchema() { "is_not_null", true); is_not_null_column.SetNotNull(); - auto is_default_column = catalog::Column( + auto has_default_column = catalog::Column( type::TypeId::BOOLEAN, type::Type::GetTypeSize(type::TypeId::BOOLEAN), - "is_default", true); - is_default_column.SetNotNull(); + "has_default", true); + has_default_column.SetNotNull(); - auto default_value_column = catalog::Column( + auto default_value_src_column = catalog::Column( type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), - "default_value", false); + "default_value_src", false); + + auto default_value_bin_column = catalog::Column( + type::TypeId::VARBINARY, type::Type::GetTypeSize(type::TypeId::VARBINARY), + "default_value_bin", false); std::unique_ptr column_catalog_schema(new catalog::Schema( {table_id_column, column_name_column, column_id_column, column_offset_column, column_type_column, column_length_column, - is_inlined_column, is_not_null_column, is_default_column, - default_value_column})); + is_inlined_column, is_not_null_column, has_default_column, + default_value_src_column, default_value_bin_column})); + + column_catalog_schema->AddConstraint(std::make_shared( + COLUMN_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + COLUMN_CATALOG_OID, std::vector{ColumnId::TABLE_OID, ColumnId::COLUMN_NAME}, + COLUMN_CATALOG_PKEY_OID)); + + column_catalog_schema->AddConstraint(std::make_shared( + COLUMN_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", + COLUMN_CATALOG_OID, std::vector{ColumnId::TABLE_OID, ColumnId::COLUMN_ID}, + COLUMN_CATALOG_SKEY0_OID)); return column_catalog_schema; } @@ -191,14 +189,19 @@ bool ColumnCatalog::InsertColumn(oid_t table_oid, tuple->SetValue(ColumnId::COLUMN_LENGTH, val5, pool); tuple->SetValue(ColumnId::IS_INLINED, val6, pool); tuple->SetValue(ColumnId::IS_NOT_NULL, val7, pool); - tuple->SetValue(ColumnId::IS_DEFAULT, val8, pool); + tuple->SetValue(ColumnId::HAS_DEFAULT, val8, pool); // set default value if the column has default constraint if (is_default) { - char default_value_str[column_length]; - default_value->SerializeTo(default_value_str, is_inlined, pool); - auto val9 = type::ValueFactory::GetVarcharValue(default_value_str, nullptr); - tuple->SetValue(ColumnId::DEFAULT_VALUE, val9, pool); + auto val9 = + type::ValueFactory::GetVarcharValue(default_value->ToString(), nullptr); + CopySerializeOutput output_buffer; + default_value->SerializeTo(output_buffer); + auto val10 = type::ValueFactory::GetVarbinaryValue( + (unsigned char*)output_buffer.Data(), output_buffer.Size(), true, pool); + + tuple->SetValue(ColumnId::DEFAULT_VALUE_SRC, val9, pool); + tuple->SetValue(ColumnId::DEFAULT_VALUE_BIN, val10, pool); } // Insert the tuple @@ -247,6 +250,80 @@ bool ColumnCatalog::DeleteColumns(oid_t table_oid, return DeleteWithIndexScan(index_offset, values, txn); } + +bool ColumnCatalog::UpdateNotNullConstraint(oid_t table_oid, + const std::string &column_name, + bool is_not_null, + concurrency::TransactionContext *txn) { + std::vector update_columns({ColumnId::IS_NOT_NULL}); + oid_t index_offset = IndexId::PRIMARY_KEY; // Index of table_oid & column_name + // values to execute index scan + std::vector scan_values; + scan_values.push_back(type::ValueFactory::GetIntegerValue(table_oid).Copy()); + scan_values.push_back( + type::ValueFactory::GetVarcharValue(column_name, nullptr).Copy()); + + // values to update + std::vector update_values; + update_values.push_back( + type::ValueFactory::GetBooleanValue(is_not_null).Copy()); + + // delete column from cache + auto pg_table = Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetTableCatalog(); + auto table_object = pg_table->GetTableObject(table_oid, txn); + table_object->EvictColumnObject(column_name); + + return UpdateWithIndexScan(update_columns, update_values, scan_values, + index_offset, txn); +} + +bool ColumnCatalog::UpdateDefaultConstraint(oid_t table_oid, + const std::string &column_name, + bool has_default, + const type::Value *default_value, + concurrency::TransactionContext *txn) { + std::vector update_columns({ColumnId::HAS_DEFAULT, + ColumnId::DEFAULT_VALUE_SRC, + ColumnId::DEFAULT_VALUE_BIN}); + oid_t index_offset = IndexId::PRIMARY_KEY; // Index of table_oid & column_name + // values to execute index scan + std::vector scan_values; + scan_values.push_back(type::ValueFactory::GetIntegerValue(table_oid).Copy()); + scan_values.push_back( + type::ValueFactory::GetVarcharValue(column_name, nullptr).Copy()); + + // values to update + std::vector update_values; + update_values.push_back( + type::ValueFactory::GetBooleanValue(has_default).Copy()); + if (has_default) { + PELOTON_ASSERT(default_value != nullptr); + update_values.push_back( + type::ValueFactory::GetVarcharValue(default_value->ToString()).Copy()); + CopySerializeOutput output_buffer; + default_value->SerializeTo(output_buffer); + update_values.push_back(type::ValueFactory::GetVarbinaryValue( + (unsigned char*)output_buffer.Data(), output_buffer.Size(), true).Copy()); + } else { + update_values.push_back( + type::ValueFactory::GetNullValueByType(type::TypeId::VARCHAR)); + update_values.push_back( + type::ValueFactory::GetNullValueByType(type::TypeId::VARBINARY)); + } + + // delete column from cache + auto pg_table = Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetTableCatalog(); + auto table_object = pg_table->GetTableObject(table_oid, txn); + table_object->EvictColumnObject(column_name); + + return UpdateWithIndexScan(update_columns, update_values, scan_values, + index_offset, txn); +} + const std::unordered_map> ColumnCatalog::GetColumnObjects(oid_t table_oid, concurrency::TransactionContext *txn) { diff --git a/src/catalog/constraint.cpp b/src/catalog/constraint.cpp index 90e79f7fc1d..364cc634c4c 100644 --- a/src/catalog/constraint.cpp +++ b/src/catalog/constraint.cpp @@ -19,17 +19,38 @@ namespace catalog { const std::string Constraint::GetInfo() const { std::ostringstream os; - os << "Constraint[" << GetName() - << "(" << std::to_string(GetConstraintOid()) << "), " - << ConstraintTypeToString(constraint_type) - << ", index_oid:" << std::to_string(index_oid); + os << "Constraint[" << GetName() << ", " + << "OID=" << constraint_oid << ", " + << ConstraintTypeToString(constraint_type) << ", "; - if (GetType() == ConstraintType::DEFAULT) { - os << "," << default_value->GetInfo(); + os << "Column: ("; + bool first = true; + for (auto col_id : column_ids) { + if(first) first = false; + else os << ", "; + os << std::to_string(col_id); } + os << "), "; - if (GetType() == ConstraintType::CHECK) { - os << ", " << exp.first << " " << exp.second.GetInfo(); + os << "index_oid:" << std::to_string(index_oid); + + if (constraint_type == ConstraintType::FOREIGN) { + os << ", Foreign key: (Sink table:" + << std::to_string(fk_sink_table_oid) << ", " + << "Column:("; + bool first = true; + for (auto col_id : fk_sink_col_ids) { + if(first) first = false; + else os << ", "; + os << std::to_string(col_id); + } + os << "), " << FKConstrActionTypeToString(fk_update_action) << ", " + << FKConstrActionTypeToString(fk_delete_action) << ")"; + } + + if (constraint_type == ConstraintType::CHECK) { + os << ", Check: (" << check_exp.first << " " + << check_exp.second.GetInfo() << ")"; } os << "]"; return os.str(); diff --git a/src/catalog/constraint_catalog.cpp b/src/catalog/constraint_catalog.cpp index 0ed61fdeb4d..a45c4ba5cfb 100644 --- a/src/catalog/constraint_catalog.cpp +++ b/src/catalog/constraint_catalog.cpp @@ -16,7 +16,6 @@ #include #include "catalog/catalog.h" -#include "catalog/foreign_key.h" #include "catalog/system_catalogs.h" #include "catalog/table_catalog.h" #include "concurrency/transaction_context.h" @@ -53,8 +52,6 @@ ConstraintCatalogObject::ConstraintCatalogObject(executor::LogicalTile *tile, switch(constraint_type) { case ConstraintType::PRIMARY: case ConstraintType::UNIQUE: - case ConstraintType::NOTNULL: - case ConstraintType::NOT_NULL: // nothing to do more break; @@ -75,17 +72,16 @@ ConstraintCatalogObject::ConstraintCatalogObject(executor::LogicalTile *tile, break; } - case ConstraintType::DEFAULT: - default_value = tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::DEFAULT_VALUE).ToString(); - break; - - case ConstraintType::CHECK: - check_cmd = tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::CHECK_CMD).ToString(); - check_exp = tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::CHECK_EXP).ToString(); + case ConstraintType::CHECK: { + auto dv_val = + tile->GetValue(tupleId, ConstraintCatalog::ColumnId::CHECK_EXP_BIN); + CopySerializeInput input_buffer(dv_val.GetData(), dv_val.GetLength()); + ExpressionType exp_type = (ExpressionType)input_buffer.ReadInt(); + type::TypeId value_type = (type::TypeId)input_buffer.ReadInt(); + auto exp_value = type::Value::DeserializeFrom(input_buffer, value_type); + check_exp = std::make_pair(exp_type, exp_value); break; + } case ConstraintType::EXCLUSION: default: @@ -112,45 +108,33 @@ ConstraintCatalog::~ConstraintCatalog() {} * @return unqiue pointer to schema */ std::unique_ptr ConstraintCatalog::InitializeSchema() { - const std::string primary_key_constraint_name = "primary_key"; - const std::string not_null_constraint_name = "not_null"; - auto constraint_oid_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "constraint_oid", true); - constraint_oid_column.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, primary_key_constraint_name, - CONSTRAINT_CATALOG_PKEY_OID)); - constraint_oid_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + constraint_oid_column.SetNotNull(); auto constraint_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "constraint_name_", false); - constraint_name_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + constraint_name_column.SetNotNull(); auto constraint_type_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "constraint_type", false); - constraint_type_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + constraint_type_column.SetNotNull(); auto table_oid_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_oid_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + table_oid_column.SetNotNull(); auto column_ids_column = catalog::Column( type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), "column_ids", false); - column_ids_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + column_ids_column.SetNotNull(); auto index_oid_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "index_oid", true); - index_oid_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + index_oid_column.SetNotNull(); auto fk_sink_table_oid_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), @@ -166,30 +150,30 @@ std::unique_ptr ConstraintCatalog::InitializeSchema() { auto fk_delete_action_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "fk_delete_action", false); - auto default_value_column = catalog::Column( + auto check_exp_src_column = catalog::Column( type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), - "default_value", false); + "check_exp_src", false); - auto check_cmd_column = catalog::Column( - type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), - "check_cmd", false); - - auto check_exp_column = catalog::Column( - type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), - "check_exp", false); + auto check_exp_bin_column = catalog::Column( + type::TypeId::VARBINARY, type::Type::GetTypeSize(type::TypeId::VARBINARY), + "check_exp_bin", false); - std::unique_ptr column_catalog_schema(new catalog::Schema( + std::unique_ptr constraint_catalog_schema(new catalog::Schema( {constraint_oid_column, constraint_name_column, constraint_type_column, table_oid_column, column_ids_column, index_oid_column, - fk_sink_table_oid_column, fk_sink_col_ids_column, - fk_update_action_column, fk_delete_action_column, default_value_column, - check_cmd_column, check_exp_column})); + fk_sink_table_oid_column, fk_sink_col_ids_column, fk_update_action_column, + fk_delete_action_column, check_exp_src_column, check_exp_bin_column})); - return column_catalog_schema; + constraint_catalog_schema->AddConstraint(std::make_shared( + CONSTRAINT_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + CONSTRAINT_CATALOG_OID, std::vector{ColumnId::CONSTRAINT_OID}, + CONSTRAINT_CATALOG_PKEY_OID)); + + return constraint_catalog_schema; } /*@brief Insert a constraint into the pg_constraint table - * This targets PRIMARY KEY, UNIQUE, DEFAULt, CHECK or NOT NULL constraint + * This targets PRIMARY KEY, FOREIGN KEY, UNIQUE or CHECK constraint * @param table_oid oid of the table related to this constraint * @param column_ids vector of oids of column related to this constraint * @param constraint to be inserted into pg_constraint @@ -197,14 +181,9 @@ std::unique_ptr ConstraintCatalog::InitializeSchema() { * @param txn TransactionContext for adding the constraint. * @return true on success. */ -bool ConstraintCatalog::InsertConstraint(oid_t table_oid, - const std::vector &column_ids, - const std::shared_ptr constraint, +bool ConstraintCatalog::InsertConstraint(const std::shared_ptr constraint, type::AbstractPool *pool, concurrency::TransactionContext *txn) { - // Check usage - PELOTON_ASSERT(constraint->GetType() != ConstraintType::FOREIGN); - - // Create the tuple first + // Create the tuple first std::unique_ptr tuple( new storage::Tuple(catalog_table_->GetSchema(), true)); @@ -213,9 +192,10 @@ bool ConstraintCatalog::InsertConstraint(oid_t table_oid, auto val1 = type::ValueFactory::GetVarcharValue(constraint->GetName(), nullptr); auto val2 = type::ValueFactory::GetVarcharValue( ConstraintTypeToString(constraint->GetType()), nullptr); - auto val3 = type::ValueFactory::GetIntegerValue(table_oid); + auto val3 = type::ValueFactory::GetIntegerValue(constraint->GetTableOid()); std::stringstream ss; - for (auto column_oid : column_ids) ss << std::to_string(column_oid) << " "; + for (auto column_oid : constraint->GetColumnIds()) + ss << std::to_string(column_oid) << " "; auto val4 = type::ValueFactory::GetVarcharValue(ss.str(), nullptr); auto val5 = type::ValueFactory::GetIntegerValue(constraint->GetIndexOid()); @@ -235,47 +215,53 @@ bool ConstraintCatalog::InsertConstraint(oid_t table_oid, PELOTON_ASSERT(constraint->GetIndexOid() != INVALID_OID); break; - case ConstraintType::NOTNULL: - case ConstraintType::NOT_NULL: - // nothing to do more - break; + case ConstraintType::FOREIGN: { + // need to set a valid index oid + PELOTON_ASSERT(constraint->GetIndexOid() != INVALID_OID); - case ConstraintType::DEFAULT: { - // set value of default value - PELOTON_ASSERT(column_ids.size() == 1); - auto column = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, table_oid)->GetSchema() - ->GetColumn(column_ids.at(0)); - char default_value_str[column.GetLength()]; - constraint->getDefaultValue()->SerializeTo(default_value_str, column.IsInlined(), - pool); - auto val6 = type::ValueFactory::GetVarcharValue(default_value_str, nullptr); - - tuple->SetValue(ColumnId::DEFAULT_VALUE, val6, pool); + auto val6 = type::ValueFactory::GetIntegerValue(constraint->GetFKSinkTableOid()); + std::stringstream snk_ss; + for (auto column_oid : constraint->GetFKSinkColumnIds()) + snk_ss << std::to_string(column_oid) << " "; + auto val7 = type::ValueFactory::GetVarcharValue(snk_ss.str(), nullptr); + auto val8 = type::ValueFactory::GetVarcharValue( + FKConstrActionTypeToString(constraint->GetFKUpdateAction()), nullptr); + auto val9 = type::ValueFactory::GetVarcharValue( + FKConstrActionTypeToString(constraint->GetFKDeleteAction()), nullptr); + + tuple->SetValue(ColumnId::FK_SINK_TABLE_OID, val6, pool); + tuple->SetValue(ColumnId::FK_SINK_COL_IDS, val7, pool); + tuple->SetValue(ColumnId::FK_UPDATE_ACTION, val8, pool); + tuple->SetValue(ColumnId::FK_DELETE_ACTION, val9, pool); break; } case ConstraintType::CHECK: { // set value of check expression - PELOTON_ASSERT(column_ids.size() == 1); - auto val6 = - type::ValueFactory::GetVarcharValue(constraint->GetCheckCmd(), nullptr); + PELOTON_ASSERT(constraint->GetColumnIds().size() == 1); auto exp = constraint->GetCheckExpression(); auto column = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, table_oid)->GetSchema() - ->GetColumn(column_ids.at(0)); - char exp_value_str[column.GetLength()]; - exp.second.SerializeTo(exp_value_str, column.IsInlined(), pool); - std::stringstream exp_ss; - exp_ss << ExpressionTypeToString(exp.first) << " " << exp_value_str; - auto val7 = type::ValueFactory::GetVarcharValue(exp_ss.str(), nullptr); + ->GetTableWithOid(database_oid, constraint->GetTableOid())->GetSchema() + ->GetColumn(constraint->GetColumnIds().at(0)); - tuple->SetValue(ColumnId::CHECK_CMD, val6, pool); - tuple->SetValue(ColumnId::CHECK_EXP, val7, pool); + std::stringstream exp_ss; + exp_ss << column.GetName() + << " " << ExpressionTypeToString(exp.first) + << " " << exp.second.ToString(); + auto val6 = type::ValueFactory::GetVarcharValue(exp_ss.str(), nullptr); + + CopySerializeOutput output_buffer; + output_buffer.WriteInt((int)exp.first); + output_buffer.WriteInt((int)column.GetType()); + exp.second.SerializeTo(output_buffer); + auto val7 = type::ValueFactory::GetVarbinaryValue( + (unsigned char*)output_buffer.Data(), output_buffer.Size(), true, pool); + + tuple->SetValue(ColumnId::CHECK_EXP_SRC, val6, pool); + tuple->SetValue(ColumnId::CHECK_EXP_BIN, val7, pool); break; } - case ConstraintType::FOREIGN: case ConstraintType::EXCLUSION: default: // unexpected constraint type @@ -290,64 +276,6 @@ bool ConstraintCatalog::InsertConstraint(oid_t table_oid, return InsertTuple(std::move(tuple), txn); } -/*@brief Insert a constraint into the pg_constraint table - * This targets only FOREIGN KEY constraint - * @param table_oid oid of the table related to this constraint - * @param column_ids vector of oids of column related to this constraint - * @param constraint to be inserted into pg_constraint - * @param foreign_key foreign key information as constraint - * @param pool to allocate memory for the column_map column. - * @param txn TransactionContext for adding the constraint. - * @return true on success. - */ -bool ConstraintCatalog::InsertConstraint(oid_t table_oid, - const std::vector &column_ids, - const std::shared_ptr constraint, - const ForeignKey &foreign_key, type::AbstractPool *pool, - concurrency::TransactionContext *txn) { - // Check usage - PELOTON_ASSERT(constraint->GetType() == ConstraintType::FOREIGN); - PELOTON_ASSERT(constraint->GetIndexOid() != INVALID_OID); - - // Create the tuple first - std::unique_ptr tuple( - new storage::Tuple(catalog_table_->GetSchema(), true)); - - auto val0 = type::ValueFactory::GetIntegerValue(constraint->GetConstraintOid()); - auto val1 = type::ValueFactory::GetVarcharValue(constraint->GetName(), nullptr); - auto val2 = - type::ValueFactory::GetVarcharValue(ConstraintTypeToString(constraint->GetType()), - nullptr); - auto val3 = type::ValueFactory::GetIntegerValue(table_oid); - std::stringstream src_ss; - for (auto column_oid : column_ids) src_ss << std::to_string(column_oid) << " "; - auto val4 = type::ValueFactory::GetVarcharValue(src_ss.str(), nullptr); - auto val5 = type::ValueFactory::GetIntegerValue(constraint->GetIndexOid()); - auto val6 = type::ValueFactory::GetIntegerValue(foreign_key.GetSinkTableOid()); - std::stringstream snk_ss; - for (auto column_oid : foreign_key.GetSinkColumnIds()) - snk_ss << std::to_string(column_oid) << " "; - auto val7 = type::ValueFactory::GetVarcharValue(snk_ss.str(), nullptr); - auto val8 = type::ValueFactory::GetVarcharValue( - FKConstrActionTypeToString(foreign_key.GetUpdateAction()), nullptr); - auto val9 = type::ValueFactory::GetVarcharValue( - FKConstrActionTypeToString(foreign_key.GetDeleteAction()), nullptr); - - tuple->SetValue(ColumnId::CONSTRAINT_OID, val0, pool); - tuple->SetValue(ColumnId::CONSTRAINT_NAME, val1, pool); - tuple->SetValue(ColumnId::CONSTRAINT_TYPE, val2, pool); - tuple->SetValue(ColumnId::TABLE_OID, val3, pool); - tuple->SetValue(ColumnId::COLUMN_IDS, val4, pool); - tuple->SetValue(ColumnId::INDEX_OID, val5, pool); - tuple->SetValue(ColumnId::FK_SINK_TABLE_OID, val6, pool); - tuple->SetValue(ColumnId::FK_SINK_COL_IDS, val7, pool); - tuple->SetValue(ColumnId::FK_UPDATE_ACTION, val8, pool); - tuple->SetValue(ColumnId::FK_DELETE_ACTION, val9, pool); - - // Insert the tuple - return InsertTuple(std::move(tuple), txn); -} - /* @brief delete all constraint records from the same table * this function is useful when calling DropTable * @param table_oid diff --git a/src/catalog/database_catalog.cpp b/src/catalog/database_catalog.cpp index 25267ca6e51..32b0a7af461 100644 --- a/src/catalog/database_catalog.cpp +++ b/src/catalog/database_catalog.cpp @@ -269,29 +269,28 @@ DatabaseCatalog::~DatabaseCatalog() {} * @return unqiue pointer to schema */ std::unique_ptr DatabaseCatalog::InitializeSchema() { - const std::string not_null_constraint_name = "not_null"; - const std::string primary_key_constraint_name = "primary_key"; - const std::string unique_constraint_name = "con_unique"; - - auto database_id_column = catalog::Column( + auto database_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "database_oid", true); - database_id_column.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, primary_key_constraint_name, - DATABASE_CATALOG_PKEY_OID)); - database_id_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + database_id_column.SetNotNull(); auto database_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "database_name", false); - database_name_column.AddConstraint(std::make_shared( - ConstraintType::UNIQUE, unique_constraint_name, - DATABASE_CATALOG_SKEY0_OID)); - database_name_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + database_name_column.SetNotNull(); std::unique_ptr database_catalog_schema( new catalog::Schema({database_id_column, database_name_column})); + + database_catalog_schema->AddConstraint(std::make_shared( + DATABASE_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + DATABASE_CATALOG_OID, std::vector{ColumnId::DATABASE_OID}, + DATABASE_CATALOG_PKEY_OID)); + + database_catalog_schema->AddConstraint(std::make_shared( + DATABASE_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", + DATABASE_CATALOG_OID, std::vector{ColumnId::DATABASE_NAME}, + DATABASE_CATALOG_SKEY0_OID)); + return database_catalog_schema; } diff --git a/src/catalog/index_catalog.cpp b/src/catalog/index_catalog.cpp index 64baa12e78b..a7f026122dc 100644 --- a/src/catalog/index_catalog.cpp +++ b/src/catalog/index_catalog.cpp @@ -60,12 +60,12 @@ IndexCatalog::IndexCatalog( : AbstractCatalog(INDEX_CATALOG_OID, INDEX_CATALOG_NAME, InitializeSchema().release(), pg_catalog) { // Add indexes for pg_index - AddIndex({0}, INDEX_CATALOG_PKEY_OID, INDEX_CATALOG_NAME "_pkey", - IndexConstraintType::PRIMARY_KEY); - AddIndex({1, 3}, INDEX_CATALOG_SKEY0_OID, INDEX_CATALOG_NAME "_skey0", - IndexConstraintType::UNIQUE); - AddIndex({2}, INDEX_CATALOG_SKEY1_OID, INDEX_CATALOG_NAME "_skey1", - IndexConstraintType::DEFAULT); + AddIndex({ColumnId::INDEX_OID}, INDEX_CATALOG_PKEY_OID, + INDEX_CATALOG_NAME "_pkey", IndexConstraintType::PRIMARY_KEY); + AddIndex({ColumnId::INDEX_NAME, ColumnId::SCHEMA_NAME}, INDEX_CATALOG_SKEY0_OID, + INDEX_CATALOG_NAME "_skey0", IndexConstraintType::UNIQUE); + AddIndex({ColumnId::TABLE_OID}, INDEX_CATALOG_SKEY1_OID, + INDEX_CATALOG_NAME "_skey1", IndexConstraintType::DEFAULT); } IndexCatalog::~IndexCatalog() {} @@ -74,68 +74,58 @@ IndexCatalog::~IndexCatalog() {} * @return unqiue pointer to schema */ std::unique_ptr IndexCatalog::InitializeSchema() { - const std::string not_null_constraint_name = "not_null"; - const std::string primary_key_constraint_name = "primary_key"; - const std::string unique_constraint_name = "con_unique"; - auto index_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "index_oid", true); - index_id_column.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, primary_key_constraint_name, - INDEX_CATALOG_PKEY_OID)); - index_id_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + index_id_column.SetNotNull(); auto index_name_column = catalog::Column(type::TypeId::VARCHAR, max_name_size, "index_name", false); - index_name_column.AddConstraint(std::make_shared( - ConstraintType::UNIQUE, unique_constraint_name, - INDEX_CATALOG_SKEY0_OID)); - index_name_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + index_name_column.SetNotNull(); auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + table_id_column.SetNotNull(); auto schema_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "schema_name", false); - schema_name_column.AddConstraint(std::make_shared( - ConstraintType::UNIQUE, unique_constraint_name, - INDEX_CATALOG_SKEY0_OID)); - schema_name_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + schema_name_column.SetNotNull(); auto index_type_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "index_type", true); - index_type_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + index_type_column.SetNotNull(); auto index_constraint_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "index_constraint", true); - index_constraint_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + index_constraint_column.SetNotNull(); auto unique_keys = catalog::Column( type::TypeId::BOOLEAN, type::Type::GetTypeSize(type::TypeId::BOOLEAN), "unique_keys", true); - unique_keys.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + unique_keys.SetNotNull(); auto indexed_attributes_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "indexed_attributes", false); - indexed_attributes_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + indexed_attributes_column.SetNotNull(); std::unique_ptr index_schema(new catalog::Schema( {index_id_column, index_name_column, table_id_column, schema_name_column, index_type_column, index_constraint_column, unique_keys, indexed_attributes_column})); + + index_schema->AddConstraint(std::make_shared( + INDEX_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + INDEX_CATALOG_OID, std::vector{ColumnId::INDEX_OID}, + INDEX_CATALOG_PKEY_OID)); + + index_schema->AddConstraint(std::make_shared( + INDEX_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", + INDEX_CATALOG_OID, std::vector{ColumnId::INDEX_NAME, ColumnId::SCHEMA_NAME}, + INDEX_CATALOG_SKEY0_OID)); + return index_schema; } diff --git a/src/catalog/layout_catalog.cpp b/src/catalog/layout_catalog.cpp index 266f6ea4a87..45961838b67 100644 --- a/src/catalog/layout_catalog.cpp +++ b/src/catalog/layout_catalog.cpp @@ -44,44 +44,36 @@ LayoutCatalog::~LayoutCatalog() {} * @return unique_ptr of the schema for pg_layout. */ std::unique_ptr LayoutCatalog::InitializeSchema() { - const std::string primary_key_constraint_name = "primary_key"; - const std::string not_null_constraint_name = "not_null"; - - auto table_id_column = catalog::Column( + auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, primary_key_constraint_name, - LAYOUT_CATALOG_PKEY_OID)); - table_id_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + table_id_column.SetNotNull(); auto layout_oid_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "layout_oid", true); - layout_oid_column.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, primary_key_constraint_name, - LAYOUT_CATALOG_PKEY_OID)); - layout_oid_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + layout_oid_column.SetNotNull(); auto num_columns_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "num_columns", true); - num_columns_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + num_columns_column.SetNotNull(); auto column_map_column = catalog::Column( type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), "column_map", false); - column_map_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + column_map_column.SetNotNull(); - std::unique_ptr column_catalog_schema( + std::unique_ptr layout_catalog_schema( new catalog::Schema({table_id_column, layout_oid_column, num_columns_column, column_map_column})); - return column_catalog_schema; + layout_catalog_schema->AddConstraint(std::make_shared( + LAYOUT_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + LAYOUT_CATALOG_OID, std::vector{ColumnId::TABLE_OID, ColumnId::LAYOUT_OID}, + LAYOUT_CATALOG_PKEY_OID)); + + return layout_catalog_schema; } /** @brief Insert a layout into the pg_layout table. diff --git a/src/catalog/manager.cpp b/src/catalog/manager.cpp index c16400fb97e..4b76c6ef643 100644 --- a/src/catalog/manager.cpp +++ b/src/catalog/manager.cpp @@ -13,7 +13,6 @@ #include "common/exception.h" #include "common/logger.h" #include "catalog/manager.h" -#include "catalog/foreign_key.h" #include "storage/database.h" #include "storage/data_table.h" #include "concurrency/transaction_manager_factory.h" diff --git a/src/catalog/multi_constraint.cpp b/src/catalog/multi_constraint.cpp deleted file mode 100644 index 0261bccc3c2..00000000000 --- a/src/catalog/multi_constraint.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Peloton -// -// multi_constraint.cpp -// -// Identification: src/catalog/multi_constraint.cpp -// -// Copyright (c) 2015-2017, Carnegie Mellon University Database Group -// -//===----------------------------------------------------------------------===// - -#include "catalog/multi_constraint.h" -#include "common/internal_types.h" - -#include - -namespace peloton { -namespace catalog { - -const std::string MultiConstraint::GetInfo() const { - std::ostringstream os; - os << "Constraint[" << GetName() << ", " - << ConstraintTypeToString(constraint_type) << " , related columns: ("; - bool first = true; - for (auto id : column_ids) { - if (first) { - os << id; - first = false; - } else { - os << " ," << id; - } - } - os << ")]"; - return os.str(); -} - -} // namespace catalog -} // namespace peloton diff --git a/src/catalog/schema.cpp b/src/catalog/schema.cpp index ab38f8c8501..feb946d95b0 100644 --- a/src/catalog/schema.cpp +++ b/src/catalog/schema.cpp @@ -76,10 +76,14 @@ Schema::Schema(const std::vector &columns) CreateTupleSchema(column_types, column_lengths, column_names, is_inlined); - // Add constraints + // Set constraints for (oid_t column_itr = 0; column_itr < column_count; column_itr++) { - for (auto constraint : columns[column_itr].GetConstraints()) - AddConstraint(column_itr, constraint); + if (columns[column_itr].IsNotNull()) { + SetNotNull(column_itr); + } + if (columns[column_itr].HasDefault()) { + SetDefaultValue(column_itr, *(columns[column_itr].GetDefaultValue())); + } } } @@ -292,6 +296,20 @@ const std::string Schema::GetInfo() const { } os << ")"; + if (constraints.empty() == false) { + os << ", {"; + bool first = true; + for (auto constraint : constraints) { + if (first) { + first = false; + } else { + os << ", "; + } + os << constraint.second->GetInfo(); + } + os << "}"; + } + return os.str(); } diff --git a/src/catalog/schema_catalog.cpp b/src/catalog/schema_catalog.cpp index ad676e2a71d..f34ddbd3146 100644 --- a/src/catalog/schema_catalog.cpp +++ b/src/catalog/schema_catalog.cpp @@ -38,9 +38,9 @@ SchemaCatalog::SchemaCatalog( : AbstractCatalog(SCHEMA_CATALOG_OID, SCHEMA_CATALOG_NAME, InitializeSchema().release(), database) { // Add indexes for pg_namespace - AddIndex({0}, SCHEMA_CATALOG_PKEY_OID, SCHEMA_CATALOG_NAME "_pkey", + AddIndex({ColumnId::SCHEMA_OID}, SCHEMA_CATALOG_PKEY_OID, SCHEMA_CATALOG_NAME "_pkey", IndexConstraintType::PRIMARY_KEY); - AddIndex({1}, SCHEMA_CATALOG_SKEY0_OID, SCHEMA_CATALOG_NAME "_skey0", + AddIndex({ColumnId::SCHEMA_NAME}, SCHEMA_CATALOG_SKEY0_OID, SCHEMA_CATALOG_NAME "_skey0", IndexConstraintType::UNIQUE); } @@ -50,29 +50,28 @@ SchemaCatalog::~SchemaCatalog() {} * @return unqiue pointer to schema */ std::unique_ptr SchemaCatalog::InitializeSchema() { - const std::string not_null_constraint_name = "not_null"; - const std::string primary_key_constraint_name = "primary_key"; - const std::string unique_constraint_name = "con_unique"; - auto schema_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "schema_oid", true); - schema_id_column.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, primary_key_constraint_name, - SCHEMA_CATALOG_PKEY_OID)); - schema_id_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + schema_id_column.SetNotNull(); auto schema_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "schema_name", false); - schema_name_column.AddConstraint(std::make_shared( - ConstraintType::UNIQUE, unique_constraint_name, - SCHEMA_CATALOG_SKEY0_OID)); - schema_name_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + schema_name_column.SetNotNull(); std::unique_ptr schema( new catalog::Schema({schema_id_column, schema_name_column})); + + schema->AddConstraint(std::make_shared( + SCHEMA_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + SCHEMA_CATALOG_OID, std::vector{ColumnId::SCHEMA_OID}, + SCHEMA_CATALOG_PKEY_OID)); + + schema->AddConstraint(std::make_shared( + SCHEMA_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", + SCHEMA_CATALOG_OID, std::vector{ColumnId::SCHEMA_NAME}, + SCHEMA_CATALOG_SKEY0_OID)); + return schema; } diff --git a/src/catalog/system_catalogs.cpp b/src/catalog/system_catalogs.cpp index 672d745ff96..c9d89740026 100644 --- a/src/catalog/system_catalogs.cpp +++ b/src/catalog/system_catalogs.cpp @@ -54,25 +54,22 @@ SystemCatalogs::SystemCatalogs(storage::Database *database, {database_oid, CONSTRAINT_CATALOG_OID}}; for (int i = 0; i < (int)shared_tables.size(); i++) { + auto schema = storage::StorageManager::GetInstance() + ->GetTableWithOid(shared_tables[i].first, shared_tables[i].second) + ->GetSchema(); oid_t column_id = 0; - for (auto column : - storage::StorageManager::GetInstance() - ->GetTableWithOid(shared_tables[i].first, shared_tables[i].second) - ->GetSchema() - ->GetColumns()) { + for (auto column : schema->GetColumns()) { pg_attribute_->InsertColumn(shared_tables[i].second, column.GetName(), column_id, column.GetOffset(), column.GetType(), column.GetLength(), column.IsInlined(), column.IsNotNull(), - column.IsDefault(), column.GetDefaultValue(), + column.HasDefault(), column.GetDefaultValue(), pool, txn); - for (auto constraint : column.GetConstraints()) { - constraint->SetConstraintOid(pg_constraint_->GetNextOid()); - pg_constraint_->InsertConstraint(shared_tables[i].second, {column_id}, - constraint, pool, txn); - } column_id++; } + for (auto constraint : schema->GetConstraints()) { + pg_constraint_->InsertConstraint(constraint.second, pool, txn); + } } } @@ -124,6 +121,7 @@ void SystemCatalogs::Bootstrap(const std::string &database_name, pg_namespace_->UpdateOid(OID_FOR_USER_OFFSET); pg_table_->UpdateOid(OID_FOR_USER_OFFSET); pg_index_->UpdateOid(OID_FOR_USER_OFFSET); + pg_constraint_->UpdateOid(OID_FOR_USER_OFFSET); // pg_layout_->UpdateOid(OID_FOR_USER_OFFSET); pg_trigger_->UpdateOid(OID_FOR_USER_OFFSET); // pg_proc->UpdateOid(OID_FOR_USER_OFFSET); diff --git a/src/catalog/table_catalog.cpp b/src/catalog/table_catalog.cpp index b234b94b4b5..de1d7a37c9f 100644 --- a/src/catalog/table_catalog.cpp +++ b/src/catalog/table_catalog.cpp @@ -328,12 +328,13 @@ TableCatalog::TableCatalog( : AbstractCatalog(TABLE_CATALOG_OID, TABLE_CATALOG_NAME, InitializeSchema().release(), database) { // Add indexes for pg_namespace - AddIndex({0}, TABLE_CATALOG_PKEY_OID, TABLE_CATALOG_NAME "_pkey", - IndexConstraintType::PRIMARY_KEY); - AddIndex({1, 2}, TABLE_CATALOG_SKEY0_OID, TABLE_CATALOG_NAME "_skey0", + AddIndex({ColumnId::TABLE_OID}, TABLE_CATALOG_PKEY_OID, + TABLE_CATALOG_NAME "_pkey", IndexConstraintType::PRIMARY_KEY); + AddIndex({ColumnId::TABLE_NAME, ColumnId::SCHEMA_NAME}, + TABLE_CATALOG_SKEY0_OID, TABLE_CATALOG_NAME "_skey0", IndexConstraintType::UNIQUE); - AddIndex({3}, TABLE_CATALOG_SKEY1_OID, TABLE_CATALOG_NAME "_skey1", - IndexConstraintType::DEFAULT); + AddIndex({ColumnId::DATABASE_OID}, TABLE_CATALOG_SKEY1_OID, + TABLE_CATALOG_NAME "_skey1", IndexConstraintType::DEFAULT); } /** @brief Insert layout object into the cache. @@ -514,57 +515,48 @@ TableCatalog::~TableCatalog() {} * @return unqiue pointer to schema */ std::unique_ptr TableCatalog::InitializeSchema() { - const std::string primary_key_constraint_name = "primary_key"; - const std::string not_null_constraint_name = "not_null"; - const std::string unique_constraint_name = "con_unique"; - auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, primary_key_constraint_name, - TABLE_CATALOG_PKEY_OID)); - table_id_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + table_id_column.SetNotNull(); auto table_name_column = catalog::Column(type::TypeId::VARCHAR, max_name_size, "table_name", false); - table_name_column.AddConstraint(std::make_shared( - ConstraintType::UNIQUE, unique_constraint_name, - TABLE_CATALOG_SKEY0_OID)); - table_name_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + table_name_column.SetNotNull(); auto schema_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size, "schema_name", false); - schema_name_column.AddConstraint(std::make_shared( - ConstraintType::UNIQUE, unique_constraint_name, - TABLE_CATALOG_SKEY0_OID)); - schema_name_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + schema_name_column.SetNotNull(); auto database_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "database_oid", true); - database_id_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + database_id_column.SetNotNull(); auto version_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "version_id", true); - version_id_column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + version_id_column.SetNotNull(); auto default_layout_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "default_layout_oid", true); - default_layout_id_column.AddConstraint( - catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); + default_layout_id_column.SetNotNull(); std::unique_ptr table_catalog_schema(new catalog::Schema( {table_id_column, table_name_column, schema_name_column, database_id_column, version_id_column, default_layout_id_column})); + table_catalog_schema->AddConstraint(std::make_shared( + TABLE_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + TABLE_CATALOG_OID, std::vector{ColumnId::TABLE_OID}, + TABLE_CATALOG_PKEY_OID)); + + table_catalog_schema->AddConstraint(std::make_shared( + TABLE_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", + TABLE_CATALOG_OID, std::vector{ColumnId::TABLE_NAME, ColumnId::SCHEMA_NAME}, + TABLE_CATALOG_SKEY0_OID)); + return table_catalog_schema; } diff --git a/src/common/internal_types.cpp b/src/common/internal_types.cpp index 61aea8ca7e5..46ec24edbd7 100644 --- a/src/common/internal_types.cpp +++ b/src/common/internal_types.cpp @@ -2051,15 +2051,6 @@ std::string ConstraintTypeToString(ConstraintType type) { case ConstraintType::INVALID: { return ("INVALID"); } - case ConstraintType::NOT_NULL: { - return ("NOT_NULL"); - } - case ConstraintType::NOTNULL: { - return ("NOTNULL"); - } - case ConstraintType::DEFAULT: { - return ("DEFAULT"); - } case ConstraintType::CHECK: { return ("CHECK"); } @@ -2088,12 +2079,6 @@ ConstraintType StringToConstraintType(const std::string &str) { std::string upper_str = StringUtil::Upper(str); if (upper_str == "INVALID") { return ConstraintType::INVALID; - } else if (upper_str == "NOT_NULL") { - return ConstraintType::NOT_NULL; - } else if (upper_str == "NOTNULL") { - return ConstraintType::NOTNULL; - } else if (upper_str == "DEFAULT") { - return ConstraintType::DEFAULT; } else if (upper_str == "CHECK") { return ConstraintType::CHECK; } else if (upper_str == "PRIMARY") { @@ -2807,18 +2792,6 @@ ConstraintType PostgresConstraintTypeToPelotonConstraintType( ConstraintType constraintType = ConstraintType::INVALID; switch (type) { - case PostgresConstraintType::NOT_NULL: - constraintType = ConstraintType::NOT_NULL; - break; - - case PostgresConstraintType::NOTNULL: - constraintType = ConstraintType::NOTNULL; - break; - - case PostgresConstraintType::DEFAULT: - constraintType = ConstraintType::DEFAULT; - break; - case PostgresConstraintType::CHECK: constraintType = ConstraintType::CHECK; break; diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index 731ff5298ba..259ceb75e68 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -13,7 +13,6 @@ #include "executor/create_executor.h" #include "catalog/catalog.h" -#include "catalog/foreign_key.h" #include "catalog/system_catalogs.h" #include "concurrency/transaction_context.h" #include "executor/executor_context.h" @@ -125,65 +124,115 @@ bool CreateExecutor::CreateTable(const planner::CreatePlan &node) { if (current_txn->GetResult() == ResultType::SUCCESS) { LOG_TRACE("Creating table succeeded!"); + auto catalog = catalog::Catalog::GetInstance(); + auto source_table = catalog->GetTableWithName(database_name, schema_name, + table_name, current_txn); + // Add the primary key constraint + if (node.HasPrimaryKey()) { + auto pk = node.GetPrimaryKey(); + std::vector col_ids; + for (auto col_name : pk.primary_key_cols) { + oid_t col_id = source_table->GetSchema()->GetColumnID(col_name); + if (col_id == INVALID_OID) { + std::string error = StringUtil::Format( + "Invalid key column name '%s.%s' for primary key '%s'", + table_name.c_str(), col_name.c_str(), + pk.constraint_name.c_str()); + throw ExecutorException(error); + } + col_ids.push_back(col_id); + } + PELOTON_ASSERT(col_ids.size() == pk.primary_key_cols.size()); - // Add the foreign key constraint (or other multi-column constraints) - if (node.GetForeignKeys().empty() == false) { - auto catalog = catalog::Catalog::GetInstance(); - auto source_table = catalog->GetTableWithName(database_name, schema_name, - table_name, current_txn); - - for (auto fk : node.GetForeignKeys()) { - auto sink_table = catalog->GetTableWithName( - database_name, schema_name, fk.sink_table_name, current_txn); - // Source Column Offsets - std::vector source_col_ids; - for (auto col_name : fk.foreign_key_sources) { - oid_t col_id = source_table->GetSchema()->GetColumnID(col_name); - if (col_id == INVALID_OID) { - std::string error = StringUtil::Format( - "Invalid source column name '%s.%s' for foreign key '%s'", - table_name.c_str(), col_name.c_str(), - fk.constraint_name.c_str()); - throw ExecutorException(error); - } - source_col_ids.push_back(col_id); - } // FOR - PELOTON_ASSERT(source_col_ids.size() == fk.foreign_key_sources.size()); - - // Sink Column Offsets - std::vector sink_col_ids; - for (auto col_name : fk.foreign_key_sinks) { - oid_t col_id = sink_table->GetSchema()->GetColumnID(col_name); - if (col_id == INVALID_OID) { - std::string error = StringUtil::Format( - "Invalid sink column name '%s.%s' for foreign key '%s'", - sink_table->GetName().c_str(), col_name.c_str(), - fk.constraint_name.c_str()); - throw ExecutorException(error); - } - sink_col_ids.push_back(col_id); - } // FOR - PELOTON_ASSERT(sink_col_ids.size() == fk.foreign_key_sinks.size()); - - // Create the catalog object and shove it into the table - catalog->AddForeignKeyConstraint(source_table->GetDatabaseOid(), - source_table->GetOid(), source_col_ids, sink_table->GetOid(), - sink_col_ids, fk.upd_action, fk.del_action, fk.constraint_name, - current_txn); - -#ifdef LOG_DEBUG_ENABLED - std::vector source_col_names = fk.foreign_key_sources; - LOG_DEBUG("Added a FOREIGN index on in %s.\n", table_name.c_str()); - LOG_DEBUG("Foreign key column names: \n"); - for (auto c : source_col_names) { - LOG_DEBUG("FK col name: %s\n", c.c_str()); + // Create the catalog object and shove it into the table + catalog->AddPrimaryKeyConstraint(source_table->GetDatabaseOid(), + source_table->GetOid(), col_ids, pk.constraint_name, current_txn); + } + + // Add the unique constraint + for (auto unique : node.GetUniques()) { + std::vector col_ids; + for (auto col_name : unique.unique_cols) { + oid_t col_id = source_table->GetSchema()->GetColumnID(col_name); + if (col_id == INVALID_OID) { + std::string error = StringUtil::Format( + "Invalid key column name '%s.%s' for unique '%s'", + table_name.c_str(), col_name.c_str(), + unique.constraint_name.c_str()); + throw ExecutorException(error); } - for (auto c : fk.foreign_key_sinks) { - LOG_DEBUG("FK sink col name: %s\n", c.c_str()); + col_ids.push_back(col_id); + } + PELOTON_ASSERT(col_ids.size() == unique.unique_cols.size()); + + // Create the catalog object and shove it into the table + catalog->AddUniqueConstraint(source_table->GetDatabaseOid(), + source_table->GetOid(), col_ids, unique.constraint_name, current_txn); + } + + // Add the foreign key constraint + for (auto fk : node.GetForeignKeys()) { + auto sink_table = catalog->GetTableWithName( + database_name, schema_name, fk.sink_table_name, current_txn); + // Source Column Offsets + std::vector source_col_ids; + for (auto col_name : fk.foreign_key_sources) { + oid_t col_id = source_table->GetSchema()->GetColumnID(col_name); + if (col_id == INVALID_OID) { + std::string error = StringUtil::Format( + "Invalid source column name '%s.%s' for foreign key '%s'", + table_name.c_str(), col_name.c_str(), + fk.constraint_name.c_str()); + throw ExecutorException(error); + } + source_col_ids.push_back(col_id); + } // FOR + PELOTON_ASSERT(source_col_ids.size() == fk.foreign_key_sources.size()); + + // Sink Column Offsets + std::vector sink_col_ids; + for (auto col_name : fk.foreign_key_sinks) { + oid_t col_id = sink_table->GetSchema()->GetColumnID(col_name); + if (col_id == INVALID_OID) { + std::string error = StringUtil::Format( + "Invalid sink column name '%s.%s' for foreign key '%s'", + sink_table->GetName().c_str(), col_name.c_str(), + fk.constraint_name.c_str()); + throw ExecutorException(error); + } + sink_col_ids.push_back(col_id); + } // FOR + PELOTON_ASSERT(sink_col_ids.size() == fk.foreign_key_sinks.size()); + + // Create the catalog object and shove it into the table + catalog->AddForeignKeyConstraint(source_table->GetDatabaseOid(), + source_table->GetOid(), source_col_ids, sink_table->GetOid(), + sink_col_ids, fk.upd_action, fk.del_action, fk.constraint_name, + current_txn); + } + + // Add the check constraint + for (auto check : node.GetChecks()) { + std::vector col_ids; + for (auto col_name : check.check_cols) { + oid_t col_id = source_table->GetSchema()->GetColumnID(col_name); + if (col_id == INVALID_OID) { + std::string error = StringUtil::Format( + "Invalid key column name '%s.%s' for unique '%s'", + table_name.c_str(), col_name.c_str(), + check.constraint_name.c_str()); + throw ExecutorException(error); } -#endif + col_ids.push_back(col_id); } + PELOTON_ASSERT(col_ids.size() == check.check_cols.size()); + + // Create the catalog object and shove it into the table + catalog->AddCheckConstraint(source_table->GetDatabaseOid(), + source_table->GetOid(), col_ids, check.exp, check.constraint_name, + current_txn); } + } else if (current_txn->GetResult() == ResultType::FAILURE) { LOG_TRACE("Creating table failed!"); } else { diff --git a/src/executor/update_executor.cpp b/src/executor/update_executor.cpp index a67a53d4719..8577c6ce2b4 100644 --- a/src/executor/update_executor.cpp +++ b/src/executor/update_executor.cpp @@ -23,7 +23,6 @@ #include "storage/tile_group_header.h" #include "storage/tile.h" #include "storage/storage_manager.h" -#include "catalog/foreign_key.h" namespace peloton { namespace executor { @@ -119,7 +118,7 @@ bool UpdateExecutor::PerformUpdatePrimaryKey( } // Check the source table of any foreign key constraint - if (target_table_->GetForeignKeySrcCount() > 0) { + if (target_table_->GetSchema()->HasForeignKeySources()) { storage::Tuple prev_tuple(target_table_schema, true); // Get a copy of the old tuple for (oid_t column_itr = 0; column_itr < target_table_schema->GetColumnCount(); column_itr++) { diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h index ebc2e830eda..b815e0de008 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -20,7 +20,6 @@ namespace peloton { namespace catalog { -class ForeignKey; class Constraint; class Schema; class DatabaseCatalogObject; @@ -154,38 +153,40 @@ class Catalog { oid_t database_oid, oid_t table_oid, const column_map_type &column_map, concurrency::TransactionContext *txn); + //===--------------------------------------------------------------------===// - // ADD FUNCTIONS + // SET FUNCTIONS FOR COLUMN CONSTRAINT //===--------------------------------------------------------------------===// - /** - * @brief Add a new constraint for a table except for foreign key - * @param database_oid Database to which the table belongs to - * @param table_oid Table to which the constraint has to be added - * @param column_ids Columns that the constraint affects - * @param constraint The new constraint to be registered - * @param txn TransactionContext - * @return ResultType(SUCCESS or FAILURE) - * note: if add a new foreign key constraint, use AddForeignKeyConstraint - */ - ResultType AddConstraint(oid_t database_oid, oid_t table_oid, - const std::vector &column_ids, - std::shared_ptr constraint, - concurrency::TransactionContext *txn); + // Set not null constraint for a column + ResultType SetNotNullConstraint(oid_t database_oid, oid_t table_oid, + oid_t column_id, + concurrency::TransactionContext *txn); - /** - * @brief Add a new foreign key constraint for a table - * @param database_oid database to which the table belongs to - * @param src_table_oid table to which the constraint has to be added - * @param src_col_ids Columns that the constraint affects - * @param snk_table_oid sink table - * @param snk_col_ids Columns that limit the source columns - * @param upd_action foreign key constraint action when update - * @param del_action foreign key constraint action when delete - * @param constraint_name constraint name - * @param txn TransactionContext - * @return ResultType(SUCCESS or FAILURE) - */ + // Set default constraint for a column + ResultType SetDefaultConstraint(oid_t database_oid, oid_t table_oid, + oid_t column_id, + const type::Value &default_value, + concurrency::TransactionContext *txn); + + + //===--------------------------------------------------------------------===// + // ADD FUNCTIONS FOR TABLE CONSTRAINT + //===--------------------------------------------------------------------===// + + // Add a new primary constraint for a table + ResultType AddPrimaryKeyConstraint(oid_t database_oid, oid_t table_oid, + const std::vector &column_ids, + const std::string &constraint_name, + concurrency::TransactionContext *txn); + + // Add a new unique constraint for a table + ResultType AddUniqueConstraint(oid_t database_oid, oid_t table_oid, + const std::vector &column_ids, + const std::string &constraint_name, + concurrency::TransactionContext *txn); + + // Add a new foreign key constraint for a table ResultType AddForeignKeyConstraint(oid_t database_oid, oid_t src_table_oid, const std::vector &src_col_ids, oid_t sink_table_oid, @@ -195,6 +196,13 @@ class Catalog { const std::string &constraint_name, concurrency::TransactionContext *txn); + // Add a new check constraint for a table + ResultType AddCheckConstraint(oid_t database_oid, oid_t table_oid, + const std::vector &column_ids, + const std::pair &exp, + const std::string &constraint_name, + concurrency::TransactionContext *txn); + //===--------------------------------------------------------------------===// // DROP FUNCTIONS //===--------------------------------------------------------------------===// @@ -234,14 +242,17 @@ class Catalog { ResultType DropLayout(oid_t database_oid, oid_t table_oid, oid_t layout_oid, concurrency::TransactionContext *txn); - /** - * @brief Drop a new foreign key constraint for a table - * @param database_oid the database to which the table belongs to - * @param table_oid the table to which the layout belongs - * @param constraint_oid the constraint to be dropped - * @param txn TransactionContext - * @return ResultType(SUCCESS or FAILURE) - */ + // Drop not null constraint for a column + ResultType DropNotNullConstraint(oid_t database_oid, oid_t table_oid, + oid_t column_id, + concurrency::TransactionContext *txn); + + // Drop default constraint for a column + ResultType DropDefaultConstraint(oid_t database_oid, oid_t table_oid, + oid_t column_id, + concurrency::TransactionContext *txn); + + // Drop constraint for a table ResultType DropConstraint(oid_t database_oid, oid_t table_oid, oid_t constraint_oid, concurrency::TransactionContext *txn); diff --git a/src/include/catalog/catalog_defaults.h b/src/include/catalog/catalog_defaults.h index 03c17d96bc0..b5c5818fcbe 100644 --- a/src/include/catalog/catalog_defaults.h +++ b/src/include/catalog/catalog_defaults.h @@ -96,10 +96,36 @@ namespace catalog { #define LAYOUT_CATALOG_PKEY_OID (13 | INDEX_OID_MASK) #define LAYOUT_CATALOG_SKEY0_OID (14 | INDEX_OID_MASK) -// Reserve pg_layout index oid +// Reserve pg_constraint index oid #define CONSTRAINT_CATALOG_PKEY_OID (15 | INDEX_OID_MASK) #define CONSTRAINT_CATALOG_SKEY0_OID (16 | INDEX_OID_MASK) +// Reserved pg_column constraint oid +#define COLUMN_CATALOG_CON_PKEY_OID (0 | CONSTRAINT_OID_MASK) +#define COLUMN_CATALOG_CON_UNI0_OID (1 | CONSTRAINT_OID_MASK) + +// Reserved pg_index index oid +#define INDEX_CATALOG_CON_PKEY_OID (2 | CONSTRAINT_OID_MASK) +#define INDEX_CATALOG_CON_UNI0_OID (3 | CONSTRAINT_OID_MASK) + +// Reserved pg_database index oid +#define DATABASE_CATALOG_CON_PKEY_OID (4 | CONSTRAINT_OID_MASK) +#define DATABASE_CATALOG_CON_UNI0_OID (5 | CONSTRAINT_OID_MASK) + +// Reserved pg_namespace index oid +#define SCHEMA_CATALOG_CON_PKEY_OID (6 | CONSTRAINT_OID_MASK) +#define SCHEMA_CATALOG_CON_UNI0_OID (7 | CONSTRAINT_OID_MASK) + +// Reserved pg_table index oid +#define TABLE_CATALOG_CON_PKEY_OID (8 | CONSTRAINT_OID_MASK) +#define TABLE_CATALOG_CON_UNI0_OID (9 | CONSTRAINT_OID_MASK) + +// Reserve pg_layout index oid +#define LAYOUT_CATALOG_CON_PKEY_OID (10 | CONSTRAINT_OID_MASK) + +// Reserve pg_constraint index oid +#define CONSTRAINT_CATALOG_CON_PKEY_OID (11 | CONSTRAINT_OID_MASK) + // Use upper 8 bits indicating catalog type #define CATALOG_TYPE_OFFSET 24 diff --git a/src/include/catalog/column.h b/src/include/catalog/column.h index 53657cd3a70..313b76687c6 100644 --- a/src/include/catalog/column.h +++ b/src/include/catalog/column.h @@ -29,18 +29,18 @@ class Column : public Printable { friend class Constraint; public: - Column() : column_type(type::TypeId::INVALID), fixed_length(INVALID_OID) { + Column() : column_type_(type::TypeId::INVALID), fixed_length_(INVALID_OID) { // Nothing to see... } Column(type::TypeId value_type, size_t column_length, std::string column_name, bool is_inlined = false, oid_t column_offset = INVALID_OID) - : column_name(column_name), - column_type(value_type), - fixed_length(INVALID_OID), - is_inlined(is_inlined), - column_offset(column_offset) { + : column_name_(column_name), + column_type_(value_type), + fixed_length_(INVALID_OID), + is_inlined_(is_inlined), + column_offset_(column_offset) { SetInlined(); // We should not have an inline value of length 0 @@ -61,93 +61,62 @@ class Column : public Printable { // Set the appropriate column length void SetLength(size_t column_length); - oid_t GetOffset() const { return column_offset; } + inline oid_t GetOffset() const { return column_offset_; } - std::string GetName() const { return column_name; } + inline std::string GetName() const { return column_name_; } - size_t GetLength() const { - if (is_inlined) - return fixed_length; + inline size_t GetLength() const { + if (is_inlined_) + return fixed_length_; else - return variable_length; + return variable_length_; } - size_t GetFixedLength() const { return fixed_length; } + inline size_t GetFixedLength() const { return fixed_length_; } - size_t GetVariableLength() const { return variable_length; } + inline size_t GetVariableLength() const { return variable_length_; } - inline type::TypeId GetType() const { return column_type; } + inline type::TypeId GetType() const { return column_type_; } - inline bool IsInlined() const { return is_inlined; } + inline bool IsInlined() const { return is_inlined_; } // Constraint check functions for NOT NULL and DEFAULT - inline bool IsPrimary() const { return is_primary_; } - - inline bool IsUnique() const { return is_unique_; } - inline bool IsNotNull() const { return is_not_null_; } - inline bool IsDefault() const { return is_default_; } + inline bool HasDefault() const { return has_default_; } // Manage NOT NULL constraint - void SetNotNull() { is_not_null_ = true; } + inline void SetNotNull() { is_not_null_ = true; } - void ClearNotNull() { is_not_null_ = false; } + inline void ClearNotNull() { is_not_null_ = false; } // Manage DEFAULT constraint - void SetDefaultValue(std::shared_ptr value) { - default_value_ = value; - is_default_ = true; + inline void SetDefaultValue(const type::Value &value) { + if (default_value_.get() != nullptr) { + return; + } + default_value_.reset(new type::Value(value)); + has_default_ = true; } inline std::shared_ptr GetDefaultValue() const { return default_value_; } - void ClearDefaultValue() { + inline void ClearDefaultValue() { default_value_.reset(); - is_default_ = false; } - - // Add a constraint to the column - void AddConstraint(const std::shared_ptr constraint) { - if (constraint->GetType() == ConstraintType::DEFAULT) { - // Add the default constraint to the front - constraints.insert(constraints.begin(), constraint); - } else { - constraints.push_back(constraint); - } - - if (constraint->GetType() == ConstraintType::PRIMARY) { - is_primary_ = true; - } - if (constraint->GetType() == ConstraintType::UNIQUE) { - is_unique_ = true; - } - } - - // Delete a constraint from the column - bool DeleteConstraint(const oid_t constraint_oid); - - const std::vector> &GetConstraints() const { - return constraints; - } - - std::shared_ptr GetConstraint(oid_t constraint_oid) { - for (auto constraint : constraints) { - if (constraint->GetConstraintOid() == constraint_oid) - return constraint; - } - return nullptr; + has_default_ = false; } hash_t Hash() const { - hash_t hash = HashUtil::Hash(&column_type); - return HashUtil::CombineHashes(hash, HashUtil::Hash(&is_inlined)); + hash_t hash = HashUtil::Hash(&column_type_); + return HashUtil::CombineHashes(hash, HashUtil::Hash(&is_inlined_)); } // Compare two column objects bool operator==(const Column &other) const { - if (other.column_type != column_type || other.is_inlined != is_inlined) { + if (other.column_type_ != column_type_ || + other.is_inlined_ != is_inlined_) { return false; } return true; @@ -158,39 +127,39 @@ class Column : public Printable { // Get a string representation for debugging const std::string GetInfo() const; - // name of the column - std::string column_name; - //===--------------------------------------------------------------------===// // MEMBERS //===--------------------------------------------------------------------===// private: + // name of the column + std::string column_name_; + // value type of column - type::TypeId column_type; // = type::TypeId::INVALID; + type::TypeId column_type_; // = type::TypeId::INVALID; // if the column is not inlined, this is set to pointer size // else, it is set to length of the fixed length column - size_t fixed_length; // = INVALID_OID; + size_t fixed_length_; // = INVALID_OID; // if the column is inlined, this is set to 0 // else, it is set to length of the variable length column - size_t variable_length = 0; + size_t variable_length_ = 0; // is the column inlined ? - bool is_inlined = false; + bool is_inlined_ = false; // is the column allowed null bool is_not_null_ = false; - // is the column contained the default value - bool is_default_ = false; + // does the column have the default value + bool has_default_ = false; // default value std::shared_ptr default_value_; // offset of column in tuple - oid_t column_offset = INVALID_OID; + oid_t column_offset_ = INVALID_OID; }; } // namespace catalog diff --git a/src/include/catalog/column_catalog.h b/src/include/catalog/column_catalog.h index 2f4db408753..a981ed70a30 100644 --- a/src/include/catalog/column_catalog.h +++ b/src/include/catalog/column_catalog.h @@ -49,8 +49,9 @@ class ColumnCatalogObject { inline type::TypeId GetColumnType() { return column_type; } inline size_t GetColumnLength() { return column_length; } inline bool IsInlined() { return is_inlined; } - inline bool IsPrimary() { return is_primary; } inline bool IsNotNull() { return is_not_null; } + inline bool HasDefault() { return has_default; } + inline const type::Value &GetDefaultValue() { return default_value; } private: // member variables @@ -62,8 +63,8 @@ class ColumnCatalogObject { size_t column_length; bool is_inlined; bool is_not_null; - bool is_default; - std::shared_ptr default_value; + bool has_default; + type::Value default_value; }; class ColumnCatalog : public AbstractCatalog { @@ -96,6 +97,15 @@ class ColumnCatalog : public AbstractCatalog { concurrency::TransactionContext *txn); bool DeleteColumns(oid_t table_oid, concurrency::TransactionContext *txn); + bool UpdateNotNullConstraint(oid_t table_oid, const std::string &column_name, + bool is_not_null, + concurrency::TransactionContext *txn); + + bool UpdateDefaultConstraint(oid_t table_oid, const std::string &column_name, + bool has_default, + const type::Value *default_value, + concurrency::TransactionContext *txn); + private: //===--------------------------------------------------------------------===// // Read Related API(only called within table catalog object) @@ -114,11 +124,12 @@ class ColumnCatalog : public AbstractCatalog { COLUMN_LENGTH = 5, IS_INLINED = 6, IS_NOT_NULL = 7, - IS_DEFAULT = 8, - DEFAULT_VALUE = 9, + HAS_DEFAULT = 8, + DEFAULT_VALUE_SRC = 9, + DEFAULT_VALUE_BIN = 10, // Add new columns here in creation order }; - std::vector all_column_ids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::vector all_column_ids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; enum IndexId { PRIMARY_KEY = 0, diff --git a/src/include/catalog/constraint.h b/src/include/catalog/constraint.h index 20383ecbeaa..943debaae27 100644 --- a/src/include/catalog/constraint.h +++ b/src/include/catalog/constraint.h @@ -29,82 +29,108 @@ namespace catalog { class Constraint : public Printable { public: - Constraint(ConstraintType type, std::string constraint_name, - oid_t index_oid = INVALID_OID) - : constraint_type(type), constraint_name(constraint_name), - index_oid(index_oid) {} - - Constraint(ConstraintType type, std::string constraint_name, - std::string check_cmd, oid_t index_oid = INVALID_OID) - : constraint_type(type), constraint_name(constraint_name), - index_oid(index_oid), check_cmd(check_cmd) {} + // Constructor for primary key or unique + Constraint(oid_t constraint_oid, ConstraintType type, + std::string constraint_name, oid_t table_oid, + std::vector column_ids, oid_t index_oid) + : constraint_oid(constraint_oid), constraint_name(constraint_name), + constraint_type(type), table_oid(table_oid), + column_ids(column_ids), index_oid(index_oid) {} + + // Constructor for foreign key constraint + Constraint(oid_t constraint_oid, ConstraintType type, + std::string constraint_name, oid_t table_oid, + std::vector column_ids,oid_t index_oid, oid_t sink_table_oid, + std::vector sink_col_ids, FKConstrActionType update_action, + FKConstrActionType delete_action) + : constraint_oid(constraint_oid), constraint_name(constraint_name), + constraint_type(type), table_oid(table_oid), + column_ids(column_ids), index_oid(index_oid), + fk_sink_table_oid(sink_table_oid), fk_sink_col_ids(sink_col_ids), + fk_update_action(update_action), fk_delete_action(delete_action) {} + + // Constructor for check constraint + Constraint(oid_t constraint_oid, ConstraintType type, + std::string constraint_name, oid_t table_oid, + std::vector column_ids, oid_t index_oid, + std::pair exp) + : constraint_oid(constraint_oid), constraint_name(constraint_name), + constraint_type(type), table_oid(table_oid), column_ids(column_ids), + index_oid(index_oid), check_exp(exp) {} //===--------------------------------------------------------------------===// // ACCESSORS //===--------------------------------------------------------------------===// + // Set oid for catalog void SetConstraintOid(oid_t oid) { constraint_oid = oid; } - oid_t GetConstraintOid() const { return constraint_oid; } + inline oid_t GetConstraintOid() const { return constraint_oid; } + + inline ConstraintType GetType() const { return constraint_type; } + + // Get the table oid + inline oid_t GetTableOid() const { return table_oid; } - ConstraintType GetType() const { return constraint_type; } + // Get the column ids + inline const std::vector &GetColumnIds() const { return column_ids; } // Set index oid indicating the index constructing the constraint void SetIndexOid(oid_t oid) { index_oid = oid; } // Get the index oid - oid_t GetIndexOid() const { return index_oid; } + inline oid_t GetIndexOid() const { return index_oid; } - std::string GetName() const { return constraint_name; } + inline std::string GetName() const { return constraint_name; } // Get a string representation for debugging const std::string GetInfo() const; - // Todo: default union data structure, - // For default constraint - void addDefaultValue(const type::Value &value) { - if (constraint_type != ConstraintType::DEFAULT || default_value.get() != nullptr) { - return; - } + inline oid_t GetFKSinkTableOid() const { return fk_sink_table_oid; } - default_value.reset(new peloton::type::Value(value)); - } + inline const std::vector &GetFKSinkColumnIds() const { return fk_sink_col_ids; } - type::Value* getDefaultValue() const { - return default_value.get(); - } + inline FKConstrActionType GetFKUpdateAction() const { return fk_update_action; } - // Add check constrain - void AddCheck(ExpressionType op, peloton::type::Value val) { - exp = std::pair(op, val); - return; - }; + inline FKConstrActionType GetFKDeleteAction() const { return fk_delete_action; } - std::pair GetCheckExpression() const { return exp; } - - std::string GetCheckCmd() const { return check_cmd; } + inline std::pair GetCheckExpression() const { return check_exp; } private: //===--------------------------------------------------------------------===// // MEMBERS //===--------------------------------------------------------------------===// - oid_t constraint_oid = INVALID_OID; + // constraint oid created by catalog + oid_t constraint_oid; + + std::string constraint_name; // The type of constraint - ConstraintType constraint_type = ConstraintType::INVALID; + ConstraintType constraint_type; - std::string constraint_name; + // Table having this constraints + oid_t table_oid; + + // Column ids related the constraint + std::vector column_ids; - // The index constructing the constraint + // Index constructing the constraint oid_t index_oid; - std::shared_ptr default_value; + // foreign key constraint information + // The reference table (sink) + oid_t fk_sink_table_oid = INVALID_OID; + + // Column ids in the reference table (sink) + std::vector fk_sink_col_ids; + + FKConstrActionType fk_update_action = FKConstrActionType::NOACTION; - std::string check_cmd = ""; + FKConstrActionType fk_delete_action = FKConstrActionType::NOACTION; - // key string is column name - std::pair exp; + // key string is column name for check constraint + std::pair check_exp; }; } // namespace catalog diff --git a/src/include/catalog/constraint_catalog.h b/src/include/catalog/constraint_catalog.h index f0d8243354f..9f927ee0989 100644 --- a/src/include/catalog/constraint_catalog.h +++ b/src/include/catalog/constraint_catalog.h @@ -45,7 +45,6 @@ namespace peloton { namespace catalog { class Constraint; -class ForeignKey; class ConstraintCatalogObject { friend class ConstraintCatalog; @@ -63,9 +62,7 @@ class ConstraintCatalogObject { inline const std::vector &GetFKSinkColumnIds() { return fk_sink_col_ids; } inline FKConstrActionType GetFKUpdateAction() { return fk_update_action; } inline FKConstrActionType GetFKDeleteAction() { return fk_delete_action; } - inline const std::string &GetDefaultValue() { return default_value; } - inline const std::string &GetCheckCmd() { return check_cmd; } - inline const std::string &GetCheckExp() { return check_exp; } + inline const std::pair &GetCheckExp() { return check_exp; } private: // member variables @@ -79,9 +76,7 @@ class ConstraintCatalogObject { std::vector fk_sink_col_ids; FKConstrActionType fk_update_action; FKConstrActionType fk_delete_action; - std::string default_value; // original : std::shared_ptr - std::string check_cmd; - std::string check_exp; // original : std::pair + std::pair check_exp; }; class ConstraintCatalog : public AbstractCatalog { @@ -102,18 +97,10 @@ class ConstraintCatalog : public AbstractCatalog { //===--------------------------------------------------------------------===// // write Related API //===--------------------------------------------------------------------===// - // Basic insert for primary key, unique, check, default or not null constraint - bool InsertConstraint(oid_t table_oid, const std::vector &column_ids, - const std::shared_ptr constraint, + bool InsertConstraint(const std::shared_ptr constraint, type::AbstractPool *pool, concurrency::TransactionContext *txn); - // insert for foreign key constraint - bool InsertConstraint(oid_t table_oid, const std::vector &column_ids, - const std::shared_ptr constraint, - const ForeignKey &foreign_key, type::AbstractPool *pool, - concurrency::TransactionContext *txn); - bool DeleteConstraints(oid_t table_oid, concurrency::TransactionContext *txn); bool DeleteConstraint(oid_t table_oid, oid_t constraint_oid, @@ -143,12 +130,11 @@ class ConstraintCatalog : public AbstractCatalog { FK_SINK_COL_IDS = 7, FK_UPDATE_ACTION = 8, FK_DELETE_ACTION = 9, - DEFAULT_VALUE = 10, - CHECK_CMD = 11, - CHECK_EXP = 12, + CHECK_EXP_SRC = 10, + CHECK_EXP_BIN = 11, // Add new columns here in creation order }; - std::vector all_column_ids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + std::vector all_column_ids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; enum IndexId { PRIMARY_KEY = 0, diff --git a/src/include/catalog/foreign_key.h b/src/include/catalog/foreign_key.h deleted file mode 100644 index 02b28d7abf6..00000000000 --- a/src/include/catalog/foreign_key.h +++ /dev/null @@ -1,76 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Peloton -// -// foreign_key.h -// -// Identification: src/include/catalog/foreign_key.h -// -// Copyright (c) 2015-16, Carnegie Mellon University Database Group -// -//===----------------------------------------------------------------------===// - - -#pragma once - -#include -#include - -#include "common/internal_types.h" - -namespace peloton { -namespace catalog { - -//===--------------------------------------------------------------------===// -// Foreign Key Class -//===--------------------------------------------------------------------===// - -// Stores info about foreign key constraints, like the sink table id etc. -class ForeignKey { - public: - ForeignKey(oid_t source_table_id, - oid_t sink_table_id, - std::vector sink_col_ids, - std::vector source_col_ids, - FKConstrActionType update_action, - FKConstrActionType delete_action, - std::string constraint_name) - - : source_table_id(source_table_id), - sink_table_id(sink_table_id), - sink_col_ids(sink_col_ids), - source_col_ids(source_col_ids), - update_action(update_action), - delete_action(delete_action), - fk_name(constraint_name) {} - - oid_t GetSourceTableOid() const { return source_table_id; } - oid_t GetSinkTableOid() const { return sink_table_id; } - - std::vector GetSinkColumnIds() const { return sink_col_ids; } - std::vector GetSourceColumnIds() const { return source_col_ids; } - - FKConstrActionType GetUpdateAction() const { return update_action; } - FKConstrActionType GetDeleteAction() const { return delete_action; } - std::string &GetConstraintName() { return fk_name; } - - private: - oid_t source_table_id = INVALID_OID; - oid_t sink_table_id = INVALID_OID; - - // Columns in the reference table (sink) - std::vector sink_col_ids; - - // Columns in the current table (source) - // Can be a single column or multiple columns depending - // on the constraint - std::vector source_col_ids; - - FKConstrActionType update_action; - FKConstrActionType delete_action; - - std::string fk_name; -}; - -} // namespace catalog -} // namespace peloton diff --git a/src/include/catalog/multi_constraint.h b/src/include/catalog/multi_constraint.h deleted file mode 100644 index 9a5e6e13f9d..00000000000 --- a/src/include/catalog/multi_constraint.h +++ /dev/null @@ -1,70 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Peloton -// -// multi_constraint.h -// -// Identification: src/include/catalog/multi_constraint.h -// -// Copyright (c) 2015-2017, Carnegie Mellon University Database Group -// -//===----------------------------------------------------------------------===// - -#pragma once - -#include -#include -#include - -#include "common/printable.h" -#include "common/internal_types.h" -#include "type/value.h" - -namespace peloton { -namespace catalog { - -//===--------------------------------------------------------------------===// -// MultiConstraint Class -//===--------------------------------------------------------------------===// - -class MultiConstraint : public Printable { - public: - MultiConstraint(ConstraintType type, std::string constraint_name) - : constraint_type(type), constraint_name(constraint_name){}; - - MultiConstraint(ConstraintType type, std::string constraint_name, - std::vector column_ids) - : constraint_type(type), constraint_name(constraint_name) { - this->column_ids = column_ids; - }; - - //===--------------------------------------------------------------------===// - // ACCESSORS - //===--------------------------------------------------------------------===// - - ConstraintType GetType() const { return constraint_type; } - - std::string GetName() const { return constraint_name; } - - // Get a string representation for debugging - const std::string GetInfo() const; - - std::vector GetCols() const { return column_ids; } - - private: - //===--------------------------------------------------------------------===// - // MEMBERS - //===--------------------------------------------------------------------===// - - // The type of constraint - ConstraintType constraint_type = ConstraintType::INVALID; - - // constraints on column set - std::vector column_ids; - - // we do not allow duplicate constraint name in single table - std::string constraint_name; -}; - -} // namespace catalog -} // namespace peloton diff --git a/src/include/catalog/schema.h b/src/include/catalog/schema.h index a925d1cfe98..e1af0a695c3 100644 --- a/src/include/catalog/schema.h +++ b/src/include/catalog/schema.h @@ -14,7 +14,7 @@ #include #include "catalog/column.h" -#include "catalog/multi_constraint.h" +#include "catalog/constraint.h" #include "common/printable.h" #include "type/type.h" #include "boost/algorithm/string.hpp" @@ -174,62 +174,146 @@ class Schema : public Printable { return indexed_columns_; } + //===--------------------------------------------------------------------===// + // Single column constraint accessors + //===--------------------------------------------------------------------===// + // Get the nullability of the column at a given index. inline bool AllowNull(const oid_t column_id) const { - for (auto constraint : columns[column_id].GetConstraints()) { - if (constraint->GetType() == ConstraintType::NOTNULL) return false; + if (columns[column_id].IsNotNull()) { + return false; } return true; } - // For single column default - inline bool AllowDefault(const oid_t column_id) const { - for (auto constraint : columns[column_id].GetConstraints()) { - if (constraint->GetType() == ConstraintType::DEFAULT) { - return true; - } - } + // Set the not null for the column + inline void SetNotNull(const oid_t column_id) { + columns[column_id].SetNotNull(); + not_null_columns.push_back(column_id); + } + + // Drop the not null for the column + inline void DropNotNull(const oid_t column_id) { + columns[column_id].ClearNotNull(); + for (auto itr = not_null_columns.begin(); itr < not_null_columns.end(); itr++) { + if (*itr == column_id) { + not_null_columns.erase(itr); + break; + } + } + } - return false; + // Get not null column list + inline std::vector GetNotNullColumns() const { + return not_null_columns; } + // For single column default + inline bool AllowDefault(const oid_t column_id) const { + return columns[column_id].HasDefault(); + } // Get the default value for the column inline type::Value* GetDefaultValue(const oid_t column_id) const { - for (auto constraint : columns[column_id].GetConstraints()) { - if (constraint->GetType() == ConstraintType::DEFAULT) { - return constraint->getDefaultValue(); - } + if (columns[column_id].HasDefault()) { + return columns[column_id].GetDefaultValue().get(); } - return nullptr; } - // Add constraint for column by id - inline void AddConstraint(oid_t column_id, - const std::shared_ptr constraint) { - columns[column_id].AddConstraint(constraint); + // Set the default value for the column + inline void SetDefaultValue(const oid_t column_id, + const type::Value &default_value) { + if (columns[column_id].HasDefault()) { + columns[column_id].ClearDefaultValue(); + } + columns[column_id].SetDefaultValue(default_value); } - // Add constraint for column by name - inline void AddConstraint(std::string column_name, - const std::shared_ptr constraint) { - for (size_t column_itr = 0; column_itr < columns.size(); column_itr++) { - if (columns[column_itr].GetName() == column_name) { - columns[column_itr].AddConstraint(constraint); - } + // Drop the default value for the column + inline void DropDefaultValue(const oid_t column_id) { + if (columns[column_id].HasDefault()) { + columns[column_id].ClearDefaultValue(); } } - inline bool DeleteConstraint(oid_t column_id, oid_t constraint_oid) { - return columns[column_id].DeleteConstraint(constraint_oid); + //===--------------------------------------------------------------------===// + // Multi-column constraint accessors + //===--------------------------------------------------------------------===// + + // Add a constraint for the table + inline void AddConstraint(const std::shared_ptr constraint) { + constraints[constraint->GetConstraintOid()] = constraint; + + if (constraint->GetType() == ConstraintType::PRIMARY) { + has_primary_key_ = true; + } else if (constraint->GetType() == ConstraintType::UNIQUE) { + unique_constraint_count_++; + } else if (constraint->GetType() == ConstraintType::FOREIGN) { + fk_constraints_.push_back(constraint->GetConstraintOid()); + } + } + + // Delete a constraint by id from the table + inline void DropConstraint(oid_t constraint_oid) { + if (constraints[constraint_oid]->GetType() == ConstraintType::PRIMARY) { + has_primary_key_ = false; + } else if (constraints[constraint_oid]->GetType() == ConstraintType::UNIQUE) { + unique_constraint_count_--; + } else if (constraints[constraint_oid]->GetType() == ConstraintType::FOREIGN) { + for (auto itr = fk_constraints_.begin(); itr < fk_constraints_.end(); itr++) { + if (*itr == constraint_oid) { + fk_constraints_.erase(itr); + break; + } + } + } + + constraints.erase(constraint_oid); } - inline void AddMultiConstraints(const catalog::MultiConstraint &mc) { - multi_constraints.push_back(mc); + inline std::unordered_map> GetConstraints() const { + return constraints; } - inline std::vector GetMultiConstraints() { - return multi_constraints; + inline std::shared_ptr GetConstraint(oid_t constraint_oid) const { + return constraints.at(constraint_oid); + } + + // For primary key constraints + inline bool HasPrimary() { return has_primary_key_; } + + // For unique constraints + inline bool HasUniqueConstraints() const { return (unique_constraint_count_ > 0); } + + // For foreign key constraints + inline std::vector> GetForeignKeyConstraints() { + std::vector> fks; + for (auto oid : fk_constraints_) { + PELOTON_ASSERT(constraints[oid]->GetType() == ConstraintType::FOREIGN); + fks.push_back(constraints[oid]); + } + return fks; + } + + inline bool HasForeignKeys() const { return (fk_constraints_.size() > 0); } + + inline void RegisterForeignKeySource(const std::shared_ptr constraint) { + fk_sources_.push_back(constraint); + } + + inline void DeleteForeignKeySource(const oid_t constraint_oid) { + for (auto itr = fk_sources_.begin(); itr < fk_sources_.end(); itr++) { + if ((*itr)->GetConstraintOid() == constraint_oid) { + fk_sources_.erase(itr); + break; + } + } + } + + inline bool HasForeignKeySources() const { return (fk_sources_.size() > 0); } + + inline std::vector> GetForeignKeySources() { + return fk_sources_; } // Get a string representation for debugging @@ -242,15 +326,12 @@ class Schema : public Printable { // all inlined and uninlined columns in the tuple std::vector columns; - // keeps track of unlined columns - std::vector uninlined_columns; - - // keeps multi_constraints - std::vector multi_constraints; - // keep these in sync with the vectors above oid_t column_count = INVALID_OID; + // keeps track of unlined columns + std::vector uninlined_columns; + oid_t uninlined_column_count = INVALID_OID; // are all columns inlined @@ -258,6 +339,27 @@ class Schema : public Printable { // keeps track of indexed columns in original table std::vector indexed_columns_; + + // Constraint Information + // keeps constraints + std::unordered_map> constraints; + + // not null column list for fast constraint checking + std::vector not_null_columns; + + // has a primary key ? + bool has_primary_key_ = false; + + // # of unique constraints + oid_t unique_constraint_count_ = START_OID; + + // list of foreign key constraints + std::vector fk_constraints_; + + // fk constraints for which this table is the sink + // The complete information is stored so no need to lookup the table + // everytime there is a constraint check + std::vector> fk_sources_; }; } // namespace catalog diff --git a/src/include/common/internal_types.h b/src/include/common/internal_types.h index 4f8df921b86..de2fd40d67e 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -884,14 +884,11 @@ enum class PostgresConstraintType { enum class ConstraintType { INVALID = INVALID_TYPE_ID, // invalid - NOT_NULL = 1, // notnull - NOTNULL = 2, // notnull - DEFAULT = 3, // default - CHECK = 4, // check - PRIMARY = 5, // primary key - UNIQUE = 6, // unique - FOREIGN = 7, // foreign key - EXCLUSION = 8 // foreign key + CHECK = 1, // check + PRIMARY = 2, // primary key + UNIQUE = 3, // unique + FOREIGN = 4, // foreign key + EXCLUSION = 5 // foreign key }; std::string ConstraintTypeToString(ConstraintType type); ConstraintType StringToConstraintType(const std::string &str); diff --git a/src/include/planner/create_plan.h b/src/include/planner/create_plan.h index ecf6a0524fe..5f76c0f194b 100644 --- a/src/include/planner/create_plan.h +++ b/src/include/planner/create_plan.h @@ -33,11 +33,16 @@ class AbstractExpression; namespace planner { /** - * The meta-data for a foreign key reference. + * The meta-data for a constraint reference. * This is meant to be a bridge from the parser to the * catalog. It only has table names and not OIDs, whereas * the catalog only wants OIDs. */ +struct PrimaryKeyInfo { + std::vector primary_key_cols; + std::string constraint_name; +}; + struct ForeignKeyInfo { std::vector foreign_key_sources; std::vector foreign_key_sinks; @@ -47,6 +52,17 @@ struct ForeignKeyInfo { FKConstrActionType del_action; }; +struct UniqueInfo { + std::vector unique_cols; + std::string constraint_name; +}; + +struct CheckInfo { + std::vector check_cols; + std::string constraint_name; + std::pair exp; +}; + class CreatePlan : public AbstractPlan { public: CreatePlan() = delete; @@ -90,9 +106,18 @@ class CreatePlan : public AbstractPlan { std::vector GetIndexAttributes() const { return index_attrs; } + inline bool HasPrimaryKey() const { return has_primary_key; } + + inline PrimaryKeyInfo GetPrimaryKey() const { return primary_key; } + inline std::vector GetForeignKeys() const { return foreign_keys; } + + inline std::vector GetUniques() const { return con_uniques; } + + inline std::vector GetChecks() const { return con_checks; } + std::vector GetKeyAttrs() const { return key_attrs; } void SetKeyAttrs(std::vector p_key_attrs) { key_attrs = p_key_attrs; } @@ -115,11 +140,16 @@ class CreatePlan : public AbstractPlan { int16_t GetTriggerType() const { return trigger_type; } protected: - // This is a helper method for extracting foreign key information - // and storing it in an internal struct. + // These following protected function are a helper method for extracting + // Multi-column constraint information and storing it in an internal struct. void ProcessForeignKeyConstraint(const std::string &table_name, const parser::ColumnDefinition *col); + void ProcessUniqueConstraint(const parser::ColumnDefinition *col); + + void ProcessCheckConstraint(const parser::ColumnDefinition *col); + + private: // Table Name std::string table_name; @@ -150,7 +180,11 @@ class CreatePlan : public AbstractPlan { bool unique; // ColumnDefinition for multi-column constraints (including foreign key) + bool has_primary_key = false; + PrimaryKeyInfo primary_key; std::vector foreign_keys; + std::vector con_uniques; + std::vector con_checks; std::string trigger_name; std::vector trigger_funcname; std::vector trigger_args; diff --git a/src/include/storage/abstract_table.h b/src/include/storage/abstract_table.h index 6b49cf9e431..b9e5cdafa10 100644 --- a/src/include/storage/abstract_table.h +++ b/src/include/storage/abstract_table.h @@ -111,16 +111,6 @@ class AbstractTable : public Printable { // Get a string representation for debugging const std::string GetInfo() const; - //===--------------------------------------------------------------------===// - // UTILITIES - //===--------------------------------------------------------------------===// - - virtual bool HasPrimaryKey() const = 0; - - virtual bool HasUniqueConstraints() const = 0; - - virtual bool HasForeignKeys() const = 0; - //===--------------------------------------------------------------------===// // STATS //===--------------------------------------------------------------------===// diff --git a/src/include/storage/data_table.h b/src/include/storage/data_table.h index 88f70cf0d9f..c18aedd4cc4 100644 --- a/src/include/storage/data_table.h +++ b/src/include/storage/data_table.h @@ -198,6 +198,7 @@ class DataTable : public AbstractTable { const std::vector> &GetIndexColumns() const { return indexes_columns_; } + //===--------------------------------------------------------------------===// // FOREIGN KEYS //===--------------------------------------------------------------------===// @@ -208,34 +209,6 @@ class DataTable : public AbstractTable { executor::ExecutorContext *context, bool is_update); - void AddForeignKey(oid_t constraint_oid, catalog::ForeignKey *key); - - std::unordered_map GetForeignKeys() const { - return foreign_keys_; - } - - catalog::ForeignKey *GetForeignKey(oid_t constraint_oid) const { - return foreign_keys_.at(constraint_oid); - } - - size_t GetForeignKeyCount() const { return foreign_keys_.size(); } - - void DropForeignKey(oid_t constraint_oid); - - void RegisterForeignKeySource(oid_t constraint_oid, catalog::ForeignKey *key); - - size_t GetForeignKeySrcCount() const { return foreign_key_sources_.size(); } - - std::unordered_map GetForeignKeySrcs() const { - return foreign_key_sources_; - } - - catalog::ForeignKey *GetForeignKeySrc(oid_t constraint_oid) const { - return foreign_key_sources_.at(constraint_oid); - } - - void DropForeignKeySrc(oid_t constraint_oid); - //===--------------------------------------------------------------------===// // TRANSFORMERS //===--------------------------------------------------------------------===// @@ -304,12 +277,6 @@ class DataTable : public AbstractTable { // deprecated, use catalog::TableCatalog::GetInstance()->GetDatabaseOid() inline oid_t GetDatabaseOid() const { return (database_oid); } - bool HasPrimaryKey() const { return (has_primary_key_); } - - bool HasUniqueConstraints() const { return (unique_constraint_count_ > 0); } - - bool HasForeignKeys() const { return (foreign_keys_.empty() == false); } - // try to insert into all indexes. // the last argument is the index entry in primary index holding the new // tuple. @@ -439,20 +406,6 @@ class DataTable : public AbstractTable { // columns present in the indexes std::vector> indexes_columns_; - // CONSTRAINTS - // fk constraints for which this table is the source - std::unordered_map foreign_keys_; - // fk constraints for which this table is the sink - // The complete information is stored so no need to lookup the table - // everytime there is a constraint check - std::unordered_map foreign_key_sources_; - - // has a primary key ? - std::atomic has_primary_key_ = ATOMIC_VAR_INIT(false); - - // # of unique constraints - std::atomic unique_constraint_count_ = ATOMIC_VAR_INIT(START_OID); - // # of tuples. must be atomic as multiple transactions can perform insert // concurrently. std::atomic number_of_tuples_ = ATOMIC_VAR_INIT(0); diff --git a/src/include/storage/temp_table.h b/src/include/storage/temp_table.h index f6b94640750..cc45b541890 100644 --- a/src/include/storage/temp_table.h +++ b/src/include/storage/temp_table.h @@ -91,12 +91,6 @@ class TempTable : public AbstractTable { std::string GetName() const override; - inline bool HasPrimaryKey() const override { return (false); } - - inline bool HasUniqueConstraints() const override { return (false); } - - inline bool HasForeignKeys() const override { return (false); } - //===--------------------------------------------------------------------===// // STATS //===--------------------------------------------------------------------===// diff --git a/src/optimizer/stats/column_stats_collector.cpp b/src/optimizer/stats/column_stats_collector.cpp index f474504f954..45b6768b314 100644 --- a/src/optimizer/stats/column_stats_collector.cpp +++ b/src/optimizer/stats/column_stats_collector.cpp @@ -44,11 +44,12 @@ void ColumnStatsCollector::AddValue(const type::Value &value) { total_count_++; if (value.IsNull()) { null_count_++; + } else { + // Update all stats + hll_.Update(value); + hist_.Update(value); + topk_.Add(value); } - // Update all stats - hll_.Update(value); - hist_.Update(value); - topk_.Add(value); } double ColumnStatsCollector::GetFracNull() { diff --git a/src/optimizer/stats/stats_storage.cpp b/src/optimizer/stats/stats_storage.cpp index d1b2fed6b12..3f751476de4 100644 --- a/src/optimizer/stats/stats_storage.cpp +++ b/src/optimizer/stats/stats_storage.cpp @@ -282,7 +282,7 @@ ResultType StatsStorage::AnalyzeStatsForAllTables( oid_t table_count = database->GetTableCount(); for (oid_t table_offset = 0; table_offset < table_count; table_offset++) { auto table = database->GetTable(table_offset); - LOG_TRACE("Analyzing table: %s", table->GetName().c_str()); + LOG_DEBUG("Analyzing table: %s", table->GetName().c_str()); std::unique_ptr table_stats_collector( new TableStatsCollector(table)); table_stats_collector->CollectColumnStats(); diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index c05ddc717cc..74da4a0242c 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -53,50 +53,31 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { schema_name = std::string(parse_tree->GetSchemaName()); database_name = std::string(parse_tree->GetDatabaseName()); std::vector columns; - std::vector> column_constraints; + std::vector pri_cols; create_type = CreateType::TABLE; - // The parser puts the Foreign Key information into an artificial - // ColumnDefinition. - for (auto &fk : parse_tree->foreign_keys) { - this->ProcessForeignKeyConstraint(table_name, fk.get()); - } - for (auto &col : parse_tree->columns) { type::TypeId val = col->GetValueType(col->type); LOG_TRACE("Column name: %s.%s; Is primary key: %d", table_name.c_str(), col->name.c_str(), col->primary); - // Check main constraints - if (col->primary) { - std::shared_ptr constraint( - new catalog::Constraint(ConstraintType::PRIMARY, "con_primary")); - column_constraints.push_back(constraint); - LOG_TRACE("Added a primary key constraint on column \"%s.%s\"", - table_name.c_str(), col->name.c_str()); + // Create column + auto column = catalog::Column(val, type::Type::GetTypeSize(val), + std::string(col->name), false); + if (!column.IsInlined()) { + column.SetLength(col->varlen); } + // Add NOT NULL constraints to the column if (col->not_null) { - std::shared_ptr constraint( - new catalog::Constraint(ConstraintType::NOTNULL, "con_not_null")); - column_constraints.push_back(constraint); + column.SetNotNull(); LOG_TRACE("Added a not-null constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); } - if (col->unique) { - std::shared_ptr constraint( - new catalog::Constraint(ConstraintType::UNIQUE, "con_unique")); - column_constraints.push_back(constraint); - LOG_TRACE("Added a unique constraint on column \"%s.%s\"", - table_name.c_str(), col->name.c_str()); - } - - /* **************** */ - - // Add the default value + // Add DEFAULT constraints to the column if (col->default_value != nullptr) { // Referenced from insert_plan.cpp if (col->default_value->GetExpressionType() != @@ -104,54 +85,57 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { expression::ConstantValueExpression *const_expr_elem = dynamic_cast( col->default_value.get()); - - std::shared_ptr constraint( - new catalog::Constraint(ConstraintType::DEFAULT, "con_default")); - type::Value v = const_expr_elem->GetValue(); - constraint->addDefaultValue(v); - column_constraints.push_back(constraint); + column.SetDefaultValue(const_expr_elem->GetValue()); LOG_TRACE("Added a default constraint %s on column \"%s.%s\"", v.ToString().c_str(), table_name.c_str(), col->name.c_str()); } } + columns.push_back(column); + + // Collect Multi-column constraints information + // TODO: Following constraints info in ColumnDefinition should be independent + // for multi-column constraints like foreign key. + + // Primary key + if (col->primary) { + pri_cols.push_back(col->name); + } + + // Unique constraint + // Currently only supports for single column + if (col->unique) { + ProcessUniqueConstraint(col.get()); + } + // Check expression constraint // Currently only supports simple boolean forms like (a > 0) if (col->check_expression != nullptr) { - // TODO: more expression types need to be supported - if (col->check_expression->GetValueType() == type::TypeId::BOOLEAN) { - std::shared_ptr constraint( - new catalog::Constraint(ConstraintType::CHECK, "con_check")); - - const expression::ConstantValueExpression *const_expr_elem = - dynamic_cast( - col->check_expression->GetChild(1)); - - type::Value tmp_value = const_expr_elem->GetValue(); - constraint->AddCheck( - std::move(col->check_expression->GetExpressionType()), - std::move(tmp_value)); - column_constraints.push_back(constraint); - LOG_TRACE("Added a check constraint on column \"%s.%s\"", - table_name.c_str(), col->name.c_str()); - } + ProcessCheckConstraint(col.get()); } + } - auto column = catalog::Column(val, type::Type::GetTypeSize(val), - std::string(col->name), false); - if (!column.IsInlined()) { - column.SetLength(col->varlen); - } + catalog::Schema *schema = new catalog::Schema(columns); - for (auto con : column_constraints) { - column.AddConstraint(con); - } + // The parser puts the multi-column constraint information + // into an artificial ColumnDefinition. + // primary key constraint + if (pri_cols.size() > 0) { + primary_key.primary_key_cols = pri_cols; + primary_key.constraint_name = "con_primary"; + has_primary_key = true; + LOG_TRACE("Added a primary key constraint on column \"%s\"", + table_name.c_str()); + } - column_constraints.clear(); - columns.push_back(column); + // foreign key + for (auto &fk : parse_tree->foreign_keys) { + ProcessForeignKeyConstraint(table_name, fk.get()); } - catalog::Schema *schema = new catalog::Schema(columns); + + // TODO: UNIQUE and CHECK constraints + table_schema = schema; break; } @@ -243,6 +227,43 @@ void CreatePlan::ProcessForeignKeyConstraint( foreign_keys.push_back(fkey_info); } +void CreatePlan::ProcessUniqueConstraint( + const parser::ColumnDefinition *col) { + UniqueInfo unique_info; + + unique_info.unique_cols = {col->name}; + unique_info.constraint_name = "con_unique"; + + LOG_TRACE("Added a unique constraint on column \"%s.%s\"", + table_name.c_str, col->name.c_str()); + con_uniques.push_back(unique_info); +} + +void CreatePlan::ProcessCheckConstraint( + const parser::ColumnDefinition *col) { + CheckInfo check_info; + + // TODO: more expression types need to be supported + if (col->check_expression->GetValueType() == type::TypeId::BOOLEAN) { + check_info.check_cols.push_back(col->name); + + const expression::ConstantValueExpression *const_expr_elem = + dynamic_cast( + col->check_expression->GetChild(1)); + type::Value tmp_value = const_expr_elem->GetValue(); + + check_info.exp = std::make_pair( + std::move(col->check_expression->GetExpressionType()), + std::move(tmp_value)); + + check_info.constraint_name = "con_check"; + + LOG_TRACE("Added a check constraint on column \"%s\"", + table_name.c_str()); + con_checks.push_back(check_info); + } +} + expression::AbstractExpression *CreatePlan::GetTriggerWhen() const { if (trigger_when) { return trigger_when->Copy(); diff --git a/src/planner/update_plan.cpp b/src/planner/update_plan.cpp index 8b6bccc4c8a..0d1593738e3 100644 --- a/src/planner/update_plan.cpp +++ b/src/planner/update_plan.cpp @@ -23,18 +23,8 @@ UpdatePlan::UpdatePlan(storage::DataTable *table, std::unique_ptr project_info) : target_table_(table), project_info_(std::move(project_info)), - update_primary_key_(false) { + update_primary_key_(table->GetSchema()->HasPrimary()) { LOG_TRACE("Creating an Update Plan"); - - if (project_info_ != nullptr) { - for (const auto target : project_info_->GetTargetList()) { - auto col_id = target.first; - update_primary_key_ = - target_table_->GetSchema()->GetColumn(col_id).IsPrimary(); - if (update_primary_key_) - break; - } - } } void UpdatePlan::SetParameterValues(std::vector *values) { diff --git a/src/storage/data_table.cpp b/src/storage/data_table.cpp index 12206d184ea..eb9800ac73c 100644 --- a/src/storage/data_table.cpp +++ b/src/storage/data_table.cpp @@ -14,7 +14,6 @@ #include #include "catalog/catalog.h" -#include "catalog/foreign_key.h" #include "catalog/layout_catalog.h" #include "catalog/system_catalogs.h" #include "catalog/table_catalog.h" @@ -109,17 +108,6 @@ DataTable::~DataTable() { } } - // clean up foreign keys - for (auto foreign_key : foreign_keys_) { - delete foreign_key.second; - } - foreign_keys_.clear(); - - for (auto foreign_key_src : foreign_key_sources_) { - delete foreign_key_src.second; - } - foreign_key_sources_.clear(); - // drop all indirection arrays for (auto indirection_array : active_indirection_arrays_) { auto oid = indirection_array->GetOid(); @@ -145,70 +133,61 @@ bool DataTable::CheckNotNulls(const AbstractTuple *tuple, } bool DataTable::CheckConstraints(const AbstractTuple *tuple) const { - // For each column in the table, check to see whether they have - // any constraints. Then if they do, make sure that the - // given tuple does not violate them. - // - // TODO: PAVLO 2017-07-15 - // We should create a faster way of check the constraints for each - // column. Like maybe can store a list of just columns that - // even have constraints defined so that we don't have to - // look at each column individually. - oid_t column_count = schema->GetColumnCount(); - for (oid_t column_itr = 0; column_itr < column_count; column_itr++) { - auto column_cons = schema->GetColumn(column_itr).GetConstraints(); - for (auto cons : column_cons) { - ConstraintType type = cons->GetType(); - switch (type) { - case ConstraintType::NOTNULL: { - if (CheckNotNulls(tuple, column_itr) == false) { - std::string error = StringUtil::Format( - "%s constraint violated on column '%s' : %s", - ConstraintTypeToString(type).c_str(), - schema->GetColumn(column_itr).GetName().c_str(), - tuple->GetInfo().c_str()); - throw ConstraintException(error); - } - break; - } - case ConstraintType::CHECK: { - // std::pair exp = - // cons.GetCheckExpression(); - // if (CheckExp(tuple, column_itr, exp) == false) { - // LOG_TRACE("CHECK EXPRESSION constraint violated"); - // throw ConstraintException( - // "CHECK EXPRESSION constraint violated : " + - // std::string(tuple->GetInfo())); - // } - break; - } - case ConstraintType::UNIQUE: { - break; - } - case ConstraintType::DEFAULT: { - // Should not be handled here - // Handled in higher hierarchy - break; - } - case ConstraintType::PRIMARY: { - break; - } - case ConstraintType::FOREIGN: { - break; - } - case ConstraintType::EXCLUSION: { - break; - } - default: { - std::string error = - StringUtil::Format("ConstraintType '%s' is not supported", - ConstraintTypeToString(type).c_str()); - LOG_TRACE("%s", error.c_str()); - throw ConstraintException(error); - } - } // SWITCH - } // FOR (constraints) - } // FOR (columns) + // make sure that the given tuple does not violate constraints. + + // NOT NULL constraint + for (oid_t column_id : schema->GetNotNullColumns()) { + if (schema->AllowNull(column_id) == false && + CheckNotNulls(tuple, column_id) == false) { + std::string error = StringUtil::Format( + "NOT NULL constraint violated on column '%s' : %s", + schema->GetColumn(column_id).GetName().c_str(), + tuple->GetInfo().c_str()); + throw ConstraintException(error); + } + } + + // DEFAULT constraint should not be handled here + // Handled in higher hierarchy + + // multi-column constraints + for (auto cons_pair : schema->GetConstraints()) { + auto cons = cons_pair.second; + ConstraintType type = cons->GetType(); + switch (type) { + case ConstraintType::CHECK: { + // std::pair exp = + // cons.GetCheckExpression(); + // if (CheckExp(tuple, column_itr, exp) == false) { + // LOG_TRACE("CHECK EXPRESSION constraint violated"); + // throw ConstraintException( + // "CHECK EXPRESSION constraint violated : " + + // std::string(tuple->GetInfo())); + // } + break; + } + case ConstraintType::UNIQUE: { + break; + } + case ConstraintType::PRIMARY: { + break; + } + case ConstraintType::FOREIGN: { + break; + } + case ConstraintType::EXCLUSION: { + break; + } + default: { + std::string error = + StringUtil::Format("ConstraintType '%s' is not supported", + ConstraintTypeToString(type).c_str()); + LOG_TRACE("%s", error.c_str()); + throw ConstraintException(error); + } + } // SWITCH + } // FOR (constraints) + return true; } @@ -589,18 +568,14 @@ bool DataTable::CheckForeignKeySrcAndCascade( storage::Tuple *prev_tuple, storage::Tuple *new_tuple, concurrency::TransactionContext *current_txn, executor::ExecutorContext *context, bool is_update) { - size_t fk_count = GetForeignKeySrcCount(); - - if (fk_count == 0) return true; + if (!schema->HasForeignKeySources()) return true; auto &transaction_manager = concurrency::TransactionManagerFactory::GetInstance(); - for (size_t iter = 0; iter < fk_count; iter++) { - catalog::ForeignKey *fk = GetForeignKeySrc(iter); - + for (auto cons : schema->GetForeignKeySources()) { // Check if any row in the source table references the current tuple - oid_t source_table_id = fk->GetSourceTableOid(); + oid_t source_table_id = cons->GetTableOid(); storage::DataTable *src_table = nullptr; try { src_table = (storage::DataTable *)storage::StorageManager::GetInstance() @@ -616,17 +591,17 @@ bool DataTable::CheckForeignKeySrcAndCascade( if (index == nullptr) continue; // Make sure this is the right index to search in - if (index->GetMetadata()->GetName().find("_FK_") != std::string::npos && - index->GetMetadata()->GetKeyAttrs() == fk->GetSourceColumnIds()) { + if (index->GetOid() == cons->GetIndexOid() && + index->GetMetadata()->GetKeyAttrs() == cons->GetColumnIds()) { LOG_DEBUG("Searching in source tables's fk index...\n"); - std::vector key_attrs = fk->GetSourceColumnIds(); + std::vector key_attrs = cons->GetColumnIds(); std::unique_ptr fk_schema( catalog::Schema::CopySchema(src_table->GetSchema(), key_attrs)); std::unique_ptr key( new storage::Tuple(fk_schema.get(), true)); - key->SetFromTuple(prev_tuple, fk->GetSinkColumnIds(), index->GetPool()); + key->SetFromTuple(prev_tuple, cons->GetFKSinkColumnIds(), index->GetPool()); std::vector location_ptrs; index->ScanKey(key.get(), location_ptrs); @@ -644,7 +619,7 @@ bool DataTable::CheckForeignKeySrcAndCascade( if (visibility != VisibilityType::OK) continue; - switch (fk->GetUpdateAction()) { + switch (cons->GetFKUpdateAction()) { // Currently NOACTION is the same as RESTRICT case FKConstrActionType::NOACTION: case FKConstrActionType::RESTRICT: { @@ -688,7 +663,7 @@ bool DataTable::CheckForeignKeySrcAndCascade( // Set the primary key fields for (oid_t k = 0; k < key_attrs.size(); k++) { auto src_col_index = key_attrs[k]; - auto sink_col_index = fk->GetSinkColumnIds()[k]; + auto sink_col_index = cons->GetFKSinkColumnIds()[k]; src_new_tuple.SetValue(src_col_index, new_tuple->GetValue(sink_col_index), context->GetPool()); @@ -754,15 +729,14 @@ bool DataTable::CheckForeignKeySrcAndCascade( */ bool DataTable::CheckForeignKeyConstraints( const AbstractTuple *tuple, concurrency::TransactionContext *transaction) { - for (auto foreign_key_pair : foreign_keys_) { - auto foreign_key = foreign_key_pair.second; - oid_t sink_table_id = foreign_key->GetSinkTableOid(); + for (auto foreign_key : schema->GetForeignKeyConstraints()) { + oid_t sink_table_id = foreign_key->GetFKSinkTableOid(); storage::DataTable *ref_table = nullptr; try { ref_table = (storage::DataTable *)storage::StorageManager::GetInstance() ->GetTableWithOid(database_oid, sink_table_id); } catch (CatalogException &e) { - LOG_TRACE("Can't find table %d! Return false", sink_table_id); + LOG_ERROR("Can't find table %d! Return false", sink_table_id); return false; } int ref_table_index_count = ref_table->GetIndexCount(); @@ -774,12 +748,12 @@ bool DataTable::CheckForeignKeyConstraints( // The foreign key constraints only refer to the primary key if (index->GetIndexType() == IndexConstraintType::PRIMARY_KEY) { - std::vector key_attrs = foreign_key->GetSinkColumnIds(); + std::vector key_attrs = foreign_key->GetFKSinkColumnIds(); std::unique_ptr foreign_key_schema( catalog::Schema::CopySchema(ref_table->schema, key_attrs)); std::unique_ptr key( new storage::Tuple(foreign_key_schema.get(), true)); - key->SetFromTuple(tuple, foreign_key->GetSourceColumnIds(), + key->SetFromTuple(tuple, foreign_key->GetColumnIds(), index->GetPool()); LOG_TRACE("check key: %s", key->GetInfo().c_str()); @@ -1047,14 +1021,6 @@ void DataTable::AddIndex(std::shared_ptr index) { index_columns_.end()); indexes_columns_.push_back(index_columns_set); - - // Update index stats - auto index_type = index->GetIndexType(); - if (index_type == IndexConstraintType::PRIMARY_KEY) { - has_primary_key_ = true; - } else if (index_type == IndexConstraintType::UNIQUE) { - unique_constraint_count_++; - } } std::shared_ptr DataTable::GetIndexWithOid( @@ -1146,33 +1112,6 @@ oid_t DataTable::GetValidIndexCount() const { return valid_index_count; } -//===--------------------------------------------------------------------===// -// FOREIGN KEYS -//===--------------------------------------------------------------------===// - -void DataTable::AddForeignKey(oid_t constraint_oid, - catalog::ForeignKey *key) { - std::lock_guard lock(data_table_mutex_); - foreign_keys_[constraint_oid] = key; -} - -void DataTable::DropForeignKey(oid_t constraint_oid) { - std::lock_guard lock(data_table_mutex_); - foreign_keys_.erase(constraint_oid); -} - -// Adds to the list of tables for which this table's PK is the foreign key sink -void DataTable::RegisterForeignKeySource(oid_t constraint_oid, - catalog::ForeignKey *key) { - std::lock_guard lock(data_table_mutex_); - foreign_key_sources_[constraint_oid] = key; -} - -void DataTable::DropForeignKeySrc(oid_t constraint_oid) { - std::lock_guard lock(data_table_mutex_); - foreign_key_sources_.erase(constraint_oid); -} - // Get the schema for the new transformed tile group std::vector TransformTileGroupSchema( diff --git a/src/storage/database.cpp b/src/storage/database.cpp index 8d7e9ed2131..55eaccc6892 100644 --- a/src/storage/database.cpp +++ b/src/storage/database.cpp @@ -12,7 +12,6 @@ #include -#include "catalog/foreign_key.h" #include "codegen/query_cache.h" #include "common/exception.h" #include "common/logger.h" @@ -146,11 +145,11 @@ const std::string Database::GetInfo() const { } } - if (table->HasForeignKeys()) { + if (table->GetSchema()->HasForeignKeys()) { os << "foreign tables \n"; - for (auto foreign_key : table->GetForeignKeys()) { - auto sink_table_oid = foreign_key.second->GetSinkTableOid(); + for (auto foreign_key : table->GetSchema()->GetForeignKeyConstraints()) { + auto sink_table_oid = foreign_key->GetFKSinkTableOid(); auto sink_table = GetTableWithOid(sink_table_oid); os << "table name : " << sink_table->GetName() << std::endl; diff --git a/test/catalog/catalog_test.cpp b/test/catalog/catalog_test.cpp index 227fa7d3e22..37d2fa30ecc 100644 --- a/test/catalog/catalog_test.cpp +++ b/test/catalog/catalog_test.cpp @@ -15,7 +15,6 @@ #include "catalog/column_catalog.h" #include "catalog/database_catalog.h" #include "catalog/database_metrics_catalog.h" -#include "catalog/foreign_key.h" #include "catalog/index_catalog.h" #include "catalog/layout_catalog.h" #include "catalog/query_metrics_catalog.h" @@ -71,8 +70,6 @@ TEST_F(CatalogTests, CreatingTable) { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); - id_column.AddConstraint( - std::make_shared(ConstraintType::PRIMARY, "primary_key")); auto name_column = catalog::Column(type::TypeId::VARCHAR, 32, "name", true); std::unique_ptr table_schema( @@ -82,14 +79,29 @@ TEST_F(CatalogTests, CreatingTable) { std::unique_ptr table_schema_3( new catalog::Schema({id_column, name_column})); - catalog::Catalog::GetInstance()->CreateTable( - "emp_db", DEFAULT_SCHEMA_NAME, "emp_table", std::move(table_schema), txn); - catalog::Catalog::GetInstance()->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, - "department_table", - std::move(table_schema_2), txn); - catalog::Catalog::GetInstance()->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, - "salary_table", - std::move(table_schema_3), txn); + auto catalog = catalog::Catalog::GetInstance(); + catalog->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, "emp_table", + std::move(table_schema), txn); + catalog->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, "department_table", + std::move(table_schema_2), txn); + catalog->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, "salary_table", + std::move(table_schema_3), txn); + + auto emp = catalog->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, + "emp_table", txn); + auto department = catalog->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, + "department_table", txn); + auto salary = catalog->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, + "salary_table", txn); + + catalog->AddPrimaryKeyConstraint(emp->GetDatabaseOid(), emp->GetTableOid(), + {0}, "con_primary", txn); + catalog->AddPrimaryKeyConstraint(department->GetDatabaseOid(), + department->GetTableOid(), + {0}, "con_primary", txn); + catalog->AddPrimaryKeyConstraint(salary->GetDatabaseOid(), salary->GetTableOid(), + {0}, "con_primary", txn); + // insert random tuple into DATABASE_METRICS_CATALOG and check std::unique_ptr pool(new type::EphemeralPool()); catalog::DatabaseMetricsCatalog::GetInstance()->InsertDatabaseMetrics( @@ -100,26 +112,19 @@ TEST_F(CatalogTests, CreatingTable) { param.len = 1; param.buf = (unsigned char *)pool->Allocate(1); *param.buf = 'a'; - auto database_object = - catalog::Catalog::GetInstance()->GetDatabaseObject("emp_db", txn); - catalog::Catalog::GetInstance() - ->GetSystemCatalogs(database_object->GetDatabaseOid()) - ->GetQueryMetricsCatalog() - ->InsertQueryMetrics("a query", database_object->GetDatabaseOid(), 1, - param, param, param, 1, 1, 1, 1, 1, 1, 1, pool.get(), - txn); - auto param1 = catalog::Catalog::GetInstance() - ->GetSystemCatalogs(database_object->GetDatabaseOid()) - ->GetQueryMetricsCatalog() - ->GetParamTypes("a query", txn); + auto database_object = catalog->GetDatabaseObject("emp_db", txn); + catalog->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetQueryMetricsCatalog() + ->InsertQueryMetrics("a query", database_object->GetDatabaseOid(), 1, + param, param, param, 1, 1, 1, 1, 1, 1, 1, + pool.get(), txn); + auto param1 = catalog->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetQueryMetricsCatalog() + ->GetParamTypes("a query", txn); EXPECT_EQ(1, param1.len); EXPECT_EQ('a', *param1.buf); // check colum object - EXPECT_EQ("name", catalog::Catalog::GetInstance() - ->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, - "department_table", txn) - ->GetColumnObject(1) - ->GetColumnName()); + EXPECT_EQ("name", department->GetColumnObject(1)->GetColumnName()); txn_manager.CommitTransaction(txn); } @@ -168,8 +173,8 @@ TEST_F(CatalogTests, TableObject) { EXPECT_EQ(type::Type::GetTypeSize(type::TypeId::INTEGER), column_objects[0]->GetColumnLength()); EXPECT_TRUE(column_objects[0]->IsInlined()); - EXPECT_TRUE(column_objects[0]->IsPrimary()); EXPECT_FALSE(column_objects[0]->IsNotNull()); + EXPECT_FALSE(column_objects[0]->HasDefault()); EXPECT_EQ(table_object->GetTableOid(), column_objects[1]->GetTableOid()); EXPECT_EQ("name", column_objects[1]->GetColumnName()); @@ -178,8 +183,8 @@ TEST_F(CatalogTests, TableObject) { EXPECT_EQ(type::TypeId::VARCHAR, column_objects[1]->GetColumnType()); EXPECT_EQ(32, column_objects[1]->GetColumnLength()); EXPECT_TRUE(column_objects[1]->IsInlined()); - EXPECT_FALSE(column_objects[1]->IsPrimary()); EXPECT_FALSE(column_objects[1]->IsNotNull()); + EXPECT_FALSE(column_objects[1]->HasDefault()); // update pg_table SET version_oid = 1 where table_name = department_table oid_t department_table_oid = table_object->GetTableOid(); @@ -503,15 +508,13 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { // Create table for foreign key. auto sink_val0 = catalog::Column(type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "sink_val0", true); - sink_val0.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, "con_primary")); std::unique_ptr sink_table_schema( new catalog::Schema({sink_val0})); EXPECT_EQ(ResultType::SUCCESS, catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, sink_table_name, std::move(sink_table_schema), txn)); - // Create table for constraint catalog test. + // Create table for constraint catalog test, and set column constraints. auto con_val0 = catalog::Column(type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val0", true); auto con_val1 = catalog::Column(type::TypeId::INTEGER, @@ -526,23 +529,8 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val5", true); auto con_val6 = catalog::Column(type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val6", true); - con_val0.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, "con_primary")); - con_val1.AddConstraint(std::make_shared( - ConstraintType::PRIMARY, "con_primary")); - con_val2.AddConstraint(std::make_shared( - ConstraintType::NOT_NULL, "con_not_null")); - con_val3.AddConstraint(std::make_shared( - ConstraintType::UNIQUE, "con_unique")); - std::shared_ptr con_def( - new catalog::Constraint(ConstraintType::DEFAULT, "con_default")); - con_def->addDefaultValue(type::ValueFactory::GetIntegerValue(0)); - con_val4.AddConstraint(con_def); - std::shared_ptr con_chk( - new catalog::Constraint(ConstraintType::CHECK, "con_check")); - con_chk->AddCheck(ExpressionType::COMPARE_GREATERTHAN, - type::ValueFactory::GetIntegerValue(0)); - con_val5.AddConstraint(con_chk); + con_val5.SetNotNull(); + con_val6.SetDefaultValue(type::ValueFactory::GetIntegerValue(555)); std::unique_ptr con_table_schema( new catalog::Schema({con_val0, con_val1, con_val2, con_val3, con_val4, con_val5, con_val6})); @@ -565,102 +553,152 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, con_table_name, txn); auto con_table_oid = con_table_object->GetTableOid(); - LOG_DEBUG("create foreign key"); - // Add foreign key - catalog->AddForeignKeyConstraint(database_oid, con_table_oid, {6}, - sink_table_oid, {0}, FKConstrActionType::NOACTION, - FKConstrActionType::NOACTION, "con_foreign", txn); + // Add primary key constraint to sink table + EXPECT_EQ(ResultType::SUCCESS, + catalog->AddPrimaryKeyConstraint(database_oid, sink_table_oid, {0}, + "con_primary", txn)); + + // Add constraints for constraint catalog test. + EXPECT_EQ(ResultType::SUCCESS, + catalog->AddPrimaryKeyConstraint(database_oid, con_table_oid, {0, 1}, + "con_primary", txn)); + EXPECT_EQ(ResultType::SUCCESS, + catalog->AddUniqueConstraint(database_oid, con_table_oid, {2}, + "con_unique", txn)); + + EXPECT_EQ(ResultType::SUCCESS, + catalog->AddForeignKeyConstraint(database_oid, con_table_oid, {3}, + sink_table_oid, {0}, + FKConstrActionType::NOACTION, + FKConstrActionType::NOACTION, + "con_foreign", txn)); + auto exp = std::make_pair(ExpressionType::COMPARE_GREATERTHAN, + type::ValueFactory::GetIntegerValue(0)); + EXPECT_EQ(ResultType::SUCCESS, + catalog->AddCheckConstraint(database_oid, con_table_oid, {4}, + exp, "con_check", txn)); LOG_DEBUG("Success all constraint creations"); // Check constraint - std::unique_ptr pool(new type::EphemeralPool()); auto constraint_objects = sink_table_object->GetConstraintObjects(); EXPECT_EQ(1, constraint_objects.size()); for (auto constraint_object_pair : constraint_objects) { auto con_oid = constraint_object_pair.first; auto con_object = constraint_object_pair.second; auto column_ids = con_object->GetColumnIds(); - EXPECT_LE(1, column_ids.size()); - for (auto column_id : column_ids) { - auto column = sink_table->GetSchema()->GetColumn(column_id); - auto constraint = column.GetConstraint(con_oid); - EXPECT_EQ(constraint->GetName(), con_object->GetConstraintName()); - EXPECT_EQ(constraint->GetType(), con_object->GetConstraintType()); - EXPECT_EQ(sink_table_oid, con_object->GetTableOid()); - EXPECT_EQ(constraint->GetIndexOid(), con_object->GetIndexOid()); - } + EXPECT_LE(1, column_ids.size()); + auto constraint = sink_table->GetSchema()->GetConstraint(con_oid); + EXPECT_EQ(constraint->GetName(), con_object->GetConstraintName()); + EXPECT_EQ(constraint->GetType(), con_object->GetConstraintType()); + EXPECT_EQ(constraint->GetTableOid(), con_object->GetTableOid()); + EXPECT_EQ(constraint->GetIndexOid(), con_object->GetIndexOid()); + EXPECT_EQ(constraint->GetColumnIds().size(), column_ids.size()); } - LOG_DEBUG("Complete check for sink table"); + // Check foreign key as sink table + auto fk_sources = sink_table->GetSchema()->GetForeignKeySources(); + EXPECT_EQ(1, fk_sources.size()); + auto fk_source = fk_sources.at(0); + EXPECT_EQ(con_table_oid, fk_source->GetTableOid()); + EXPECT_EQ(sink_table_oid, fk_source->GetFKSinkTableOid()); - constraint_objects = con_table_object->GetConstraintObjects(); - EXPECT_EQ(6, constraint_objects.size()); - for (auto constraint_object_pair : constraint_objects) { - auto con_oid = constraint_object_pair.first; - auto con_object = constraint_object_pair.second; + LOG_DEBUG("%s", sink_table->GetSchema()->GetInfo().c_str()); + LOG_DEBUG("Complete check for sink table"); - LOG_DEBUG("Check constraint:%s (%s)", con_object->GetConstraintName().c_str(), - ConstraintTypeToString(con_object->GetConstraintType()).c_str()); + // Single column constraints + for (auto column_object_pair : con_table_object->GetColumnObjects()) { + auto column_id = column_object_pair.first; + auto column_object = column_object_pair.second; + auto column = con_table->GetSchema()->GetColumn(column_id); + + if (column_object->GetColumnName() == "con_val5") { + LOG_DEBUG("Check not null constraint in column:%s", + column_object->GetColumnName().c_str()); + EXPECT_TRUE(column_object->IsNotNull()); + EXPECT_EQ(column.IsNotNull(), column_object->IsNotNull()); + } else if (column_object->GetColumnName() == "con_val6") { + LOG_DEBUG("Check default constraint in column:%s", + column_object->GetColumnName().c_str()); + EXPECT_TRUE(column_object->HasDefault()); + EXPECT_EQ(column.HasDefault(), column_object->HasDefault()); + EXPECT_EQ(column.GetDefaultValue() + ->CompareEquals(column_object->GetDefaultValue()), + CmpBool::CmpTrue); + } + } - auto column_ids = con_object->GetColumnIds(); - for (auto column_id : column_ids) { - auto column = con_table->GetSchema()->GetColumn(column_id); - auto constraint = column.GetConstraint(con_oid); - if (constraint == nullptr) continue; - EXPECT_EQ(constraint->GetName(), con_object->GetConstraintName()); - EXPECT_EQ(constraint->GetType(), con_object->GetConstraintType()); - EXPECT_EQ(con_table_oid, con_object->GetTableOid()); - EXPECT_EQ(constraint->GetIndexOid(), con_object->GetIndexOid()); - - if (con_object->GetConstraintType() == ConstraintType::FOREIGN) { - auto fk = con_table->GetForeignKey(con_object->GetConstraintOid()); - EXPECT_EQ(fk->GetConstraintName(), con_object->GetConstraintName()); - EXPECT_EQ(fk->GetSourceColumnIds().size(), column_ids.size()); - EXPECT_EQ(fk->GetSinkTableOid(), con_object->GetFKSinkTableOid()); - EXPECT_EQ(fk->GetSinkColumnIds().size(), - con_object->GetFKSinkColumnIds().size()); - EXPECT_EQ(fk->GetUpdateAction(), con_object->GetFKUpdateAction()); - EXPECT_EQ(fk->GetDeleteAction(), con_object->GetFKDeleteAction()); - } else if (con_object->GetConstraintType() == ConstraintType::DEFAULT) { - auto dv_str = con_object->GetDefaultValue(); - auto default_value = - type::Value::DeserializeFrom(dv_str.c_str(), column.GetType(), - column.IsInlined(), pool.get()); - EXPECT_EQ(constraint->getDefaultValue()->CompareEquals(default_value), - CmpBool::CmpTrue); - } else if (con_object->GetConstraintType() == ConstraintType::CHECK) { - EXPECT_EQ(constraint->GetCheckCmd(), con_object->GetCheckCmd()); - std::stringstream exp_ss(con_object->GetCheckExp().c_str()); - std::string exp_type_str, exp_value_str; - std::getline(exp_ss, exp_type_str, ' '); - std::getline(exp_ss, exp_value_str, ' '); - auto exp_value = type::Value::DeserializeFrom(exp_value_str.c_str(), - column.GetType(), column.IsInlined(), pool.get()); - auto exp_type = StringToExpressionType(exp_type_str); - EXPECT_EQ(constraint->GetCheckExpression().first, exp_type); - EXPECT_EQ(constraint->GetCheckExpression().second.CompareEquals(exp_value), - CmpBool::CmpTrue); - } - } + // Multi-column constraints + constraint_objects = con_table_object->GetConstraintObjects(); + EXPECT_EQ(4, constraint_objects.size()); + for (auto constraint_object_pair : constraint_objects) { + auto con_oid = constraint_object_pair.first; + auto con_object = constraint_object_pair.second; + + LOG_DEBUG("Check constraint:%s (%s)", con_object->GetConstraintName().c_str(), + ConstraintTypeToString(con_object->GetConstraintType()).c_str()); + + auto constraint = con_table->GetSchema()->GetConstraint(con_oid); + EXPECT_NE(nullptr, constraint); + EXPECT_EQ(constraint->GetName(), con_object->GetConstraintName()); + EXPECT_EQ(constraint->GetType(), con_object->GetConstraintType()); + EXPECT_EQ(con_table_oid, con_object->GetTableOid()); + EXPECT_EQ(constraint->GetIndexOid(), con_object->GetIndexOid()); + EXPECT_EQ(constraint->GetColumnIds().size(), con_object->GetColumnIds().size()); + + switch (con_object->GetConstraintType()) { + case ConstraintType::PRIMARY: + case ConstraintType::UNIQUE: + break; + + case ConstraintType::FOREIGN: { + EXPECT_EQ(fk_source.get(), constraint.get()); + EXPECT_EQ(constraint->GetFKSinkTableOid(), con_object->GetFKSinkTableOid()); + EXPECT_EQ(constraint->GetFKSinkColumnIds().size(), + con_object->GetFKSinkColumnIds().size()); + EXPECT_EQ(constraint->GetFKUpdateAction(), con_object->GetFKUpdateAction()); + EXPECT_EQ(constraint->GetFKDeleteAction(), con_object->GetFKDeleteAction()); + break; + } + + case ConstraintType::CHECK: { + EXPECT_EQ(1, con_object->GetColumnIds().size()); + auto column = con_table->GetSchema()->GetColumn(con_object->GetColumnIds().at(0)); + EXPECT_EQ(constraint->GetCheckExpression().first, con_object->GetCheckExp().first); + EXPECT_EQ(constraint->GetCheckExpression().second.CompareEquals( + con_object->GetCheckExp().second), CmpBool::CmpTrue); + break; + } + default: + LOG_DEBUG("Unexpected constraint appeared: %s", + ConstraintTypeToString(con_object->GetConstraintType()).c_str()); + EXPECT_TRUE(false); + } } txn_manager.CommitTransaction(txn); + LOG_DEBUG("%s", con_table->GetSchema()->GetInfo().c_str()); LOG_DEBUG("Complete check for constraint table"); // Drop constraint txn = txn_manager.BeginTransaction(); - for (auto column : con_table->GetSchema()->GetColumns()) { - for (auto constraint : column.GetConstraints()) { - auto result = catalog->DropConstraint(database_oid, con_table_oid, - constraint->GetConstraintOid(), txn); - EXPECT_EQ(ResultType::SUCCESS, result); - } + auto con_schema = con_table->GetSchema(); + for (auto not_null_column_id : con_schema->GetNotNullColumns()) { + EXPECT_EQ(ResultType::SUCCESS, + catalog->DropNotNullConstraint(database_oid, con_table_oid, + not_null_column_id, txn)); } + EXPECT_EQ(ResultType::SUCCESS, + catalog->DropDefaultConstraint(database_oid, con_table_oid, 6, txn)); + for (auto constraint : con_schema->GetConstraints()) { + EXPECT_EQ(ResultType::SUCCESS, + catalog->DropConstraint(database_oid, con_table_oid, + constraint.second->GetConstraintOid(), txn)); + } txn_manager.CommitTransaction(txn); - LOG_DEBUG("Complete delete constraints in constraint table"); + LOG_DEBUG("Complete drop constraints in constraint table"); // Drop database txn = txn_manager.BeginTransaction(); diff --git a/test/catalog/constraints_test.cpp b/test/catalog/constraints_test.cpp index dfd8b015a81..8900d9c8143 100644 --- a/test/catalog/constraints_test.cpp +++ b/test/catalog/constraints_test.cpp @@ -16,7 +16,6 @@ #include "catalog/testing_constraints_util.h" #include "catalog/catalog.h" -#include "catalog/foreign_key.h" #include "common/internal_types.h" #include "concurrency/testing_transaction_util.h" #include "executor/executors.h" @@ -29,7 +28,8 @@ #define CONSTRAINT_NOTNULL_TEST #define CONSTRAINT_DEFAULT_TEST -//#define CONSTRAINT_CHECK_TEST +// #define CONSTRAINT_CHECK_TEST +// #define CONSTRAINT_UNIQUE_TEST namespace peloton { namespace test { @@ -52,15 +52,15 @@ TEST_F(ConstraintsTests, NOTNULLTest) { // 140 141 142 "143" // Set all of the columns to be NOT NULL - std::vector> constraints; + std::vector notnull_col_ids; for (int i = 0; i < CONSTRAINTS_NUM_COLS; i++) { - constraints.push_back( - {catalog::Constraint(ConstraintType::NOTNULL, "notnull_constraint")}); + notnull_col_ids.push_back(i); } - std::vector multi_constraints; + std::unordered_map default_values; storage::DataTable *data_table = - TestingConstraintsUtil::CreateAndPopulateTable(constraints, - multi_constraints); + TestingConstraintsUtil::CreateTable(notnull_col_ids, + default_values); + TestingConstraintsUtil::PopulateTable(data_table); // Bootstrap auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); @@ -113,29 +113,42 @@ TEST_F(ConstraintsTests, NOTNULLTest) { #ifdef CONSTRAINT_DEFAULT_TEST TEST_F(ConstraintsTests, DEFAULTTEST) { - // Set all of the columns to be NOT NULL - std::vector> constraints; + // Set default value within col_B + std::vector notnull_col_ids; + std::unordered_map default_values; for (int i = 0; i < CONSTRAINTS_NUM_COLS; i++) { + // COL_B + if (i == 1) { + default_values[i] = + type::ValueFactory::GetIntegerValue(DEFAULT_VALUE); + } + // COL_A + COL_C + COL_D + else { + // do nothing + } + } + storage::DataTable *data_table = + TestingConstraintsUtil::CreateTable(notnull_col_ids, + default_values); + // Add primary key + auto catalog = catalog::Catalog::GetInstance(); + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + for (oid_t i = 0; i < CONSTRAINTS_NUM_COLS; i++) { // COL_A if (i == 0) { - constraints.push_back( - {catalog::Constraint(ConstraintType::PRIMARY, "pkey")}); - } - // COL_B - else if (i == 1) { - catalog::Constraint default_const(ConstraintType::DEFAULT, "default"); - default_const.addDefaultValue( - type::ValueFactory::GetIntegerValue(DEFAULT_VALUE)); - constraints.push_back({}); + catalog->AddPrimaryKeyConstraint(data_table->GetDatabaseOid(), + data_table->GetOid(), {i}, "con_primary", txn); } - // COL_C + COL_D + // COL_B + COL_C + COL_D else { - constraints.push_back({}); + // do nothing } } - std::vector multi_constraints; - TestingConstraintsUtil::CreateAndPopulateTable(constraints, - multi_constraints); + txn_manager.CommitTransaction(txn); + + // populate test data + TestingConstraintsUtil::PopulateTable(data_table); // Bootstrap std::vector result; @@ -153,13 +166,14 @@ TEST_F(ConstraintsTests, DEFAULTTEST) { rows_affected, error_message); EXPECT_EQ(ResultType::SUCCESS, status); - sql = StringUtil::Format("SELECT col_d FROM %s WHERE col_a = 9999", + sql = StringUtil::Format("SELECT col_b FROM %s WHERE col_a = 9999", CONSTRAINTS_TEST_TABLE); status = TestingSQLUtil::ExecuteSQLQuery(sql, result, tuple_descriptor, rows_affected, error_message); EXPECT_EQ(ResultType::SUCCESS, status); std::string resultStr = TestingSQLUtil::GetResultValueAsString(result, 0); - LOG_INFO("OUTPUT:\n%s", resultStr.c_str()); + EXPECT_EQ(std::to_string(DEFAULT_VALUE), resultStr); + LOG_INFO("OUTPUT:%s", resultStr.c_str()); } #endif @@ -173,32 +187,38 @@ TEST_F(ConstraintsTests, CHECKTest) { // 20 21 22 "23" // ..... // 140 141 142 "143" + auto catalog = catalog::Catalog::GetInstance(); + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + catalog->CreateDatabase(DEFAULT_DB_NAME, txn); auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "A", false, 0); - auto constraints = catalog::Constraint(ConstraintType::CHECK, "check1"); - type::Value tmp_value = type::ValueFactory::GetIntegerValue(0); - constraints.AddCheck(ExpressionType::COMPARE_GREATERTHAN, tmp_value); - column1.AddConstraint(constraints); - LOG_DEBUG("%s %s", peloton::DOUBLE_STAR.c_str(), - constraints.GetInfo().c_str()); - catalog::Schema *table_schema = new catalog::Schema({column1}); + std::unique_ptr table_schema(new catalog::Schema({column1})); + std::string table_name("TEST_TABLE"); - bool own_schema = true; - bool adapt_table = false; - storage::DataTable *table = storage::TableFactory::GetDataTable( - INVALID_OID, INVALID_OID, table_schema, table_name, - TESTS_TUPLES_PER_TILEGROUP, own_schema, adapt_table); - std::unique_ptr data_table(table); + auto result = catalog->CreateTable(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + table_name, std::move(table_schema), + txn, false); + EXPECT_EQ(ResultType::SUCCESS, result); - auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto data_table = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + table_name, txn); + EXPECT_NE(nullptr, data_table); + + // add check constraint + type::Value tmp_value = type::ValueFactory::GetIntegerValue(0); + catalog->AddCheckConstraint(data_table->GetDatabaseOid(), data_table->GetOid(), + {0}, "", std::make_pair(ExpressionType::COMPARE_GREATERTHAN, tmp_value), + "con_check", txn); + txn_manager.CommitTransaction(txn); // begin this transaction - auto txn = txn_manager.BeginTransaction(); + txn = txn_manager.BeginTransaction(); // Test1: insert a tuple with column meet the constraint requirment bool hasException = false; try { TestingConstraintsUtil::ExecuteOneInsert( - txn, data_table.get(), type::ValueFactory::GetIntegerValue(10)); + txn, data_table, type::ValueFactory::GetIntegerValue(10)); } catch (ConstraintException e) { hasException = true; } @@ -208,7 +228,7 @@ TEST_F(ConstraintsTests, CHECKTest) { hasException = false; try { TestingConstraintsUtil::ExecuteOneInsert( - txn, data_table.get(), type::ValueFactory::GetIntegerValue(-1)); + txn, data_table, type::ValueFactory::GetIntegerValue(-1)); } catch (ConstraintException e) { hasException = true; } @@ -216,7 +236,12 @@ TEST_F(ConstraintsTests, CHECKTest) { // commit this transaction txn_manager.CommitTransaction(txn); - delete data_table.release(); + + + txn = txn_manager.BeginTransaction(); + auto result = catalog->DropDatabaseWithName(DEFAULT_DB_NAME, txn); + EXPECT_EQ(ResultType::SUCCESS, result); + txn_manager.CommitTransaction(txn); } #endif @@ -225,22 +250,23 @@ TEST_F(ConstraintsTests, UNIQUETest) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto catalog = catalog::Catalog::GetInstance(); auto txn = txn_manager.BeginTransaction(); - catalog->CreateDatabase(DEFAULT_DB_NAME, nullptr); + catalog->CreateDatabase(DEFAULT_DB_NAME, txn); auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "A", false, 0); auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "B", false, 1); - auto constraints = catalog::Constraint(ConstraintType::UNIQUE, "unique1"); - column1.AddConstraint(constraints); - LOG_DEBUG("%s %s", peloton::DOUBLE_STAR.c_str(), - constraints.GetInfo().c_str()); std::unique_ptr table_schema( new catalog::Schema({column1, column2})); std::string table_name("TEST_TABLE"); - catalog::Catalog::GetInstance()->CreateTable(DEFAULT_DB_NAME, - DEFAULT_SCHEMA_NAME, table_name, - std::move(table_schema), txn); - storage::DataTable *table = catalog::Catalog::GetInstance()->GetTableWithName( + auto result = catalog->CreateTable(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + table_name, std::move(table_schema), + txn, false); + EXPECT_EQ(ResultType::SUCCESS, result); + + auto table = catalog::Catalog::GetInstance()->GetTableWithName( DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, table_name, txn); + + catalog->AddUniqueConstraint(table->GetDatabaseOid(), table->GetOid(), + {0}, "con_unique", txn); txn_manager.CommitTransaction(txn); // table->AddUNIQUEIndex(); @@ -286,7 +312,7 @@ TEST_F(ConstraintsTests, UNIQUETest) { txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - catalog::Catalog::GetInstance()->DropDatabaseWithName(DEFAULT_DB_NAME, txn); + catalog->DropDatabaseWithName(DEFAULT_DB_NAME, txn); txn_manager.CommitTransaction(txn); } #endif diff --git a/test/codegen/testing_codegen_util.cpp b/test/codegen/testing_codegen_util.cpp index 55f57f835b9..acbe4422aba 100644 --- a/test/codegen/testing_codegen_util.cpp +++ b/test/codegen/testing_codegen_util.cpp @@ -81,23 +81,15 @@ catalog::Column PelotonCodeGenTest::GetTestColumn(uint32_t col_id) const { } // Create the test schema for all the tables -std::unique_ptr PelotonCodeGenTest::CreateTestSchema( - bool add_primary) const { +std::unique_ptr PelotonCodeGenTest::CreateTestSchema() const { // Create the columns std::vector cols = {GetTestColumn(0), GetTestColumn(1), GetTestColumn(2), GetTestColumn(3)}; // Add NOT NULL constraints on COL_A, COL_C, COL_D - cols[0].AddConstraint( - std::make_shared(ConstraintType::NOTNULL, "not_null")); - if (add_primary) { - cols[0].AddConstraint( - std::make_shared(ConstraintType::PRIMARY, "con_primary")); - } - cols[2].AddConstraint( - std::make_shared(ConstraintType::NOTNULL, "not_null")); - cols[3].AddConstraint( - std::make_shared(ConstraintType::NOTNULL, "not_null")); + cols[0].SetNotNull(); + cols[2].SetNotNull(); + cols[3].SetNotNull(); // Return the schema return std::unique_ptr{new catalog::Schema(cols)}; @@ -120,15 +112,15 @@ void PelotonCodeGenTest::CreateTestTables(concurrency::TransactionContext *txn, ->GetTableOid()); } for (int i = 4; i < 5; i++) { - auto table_schema = CreateTestSchema(true); + auto table_schema = CreateTestSchema(); catalog->CreateTable(test_db_name, DEFAULT_SCHEMA_NAME, test_table_names[i], std::move(table_schema), txn, false, tuples_per_tilegroup, layout_type); - test_table_oids.push_back(catalog - ->GetTableObject(test_db_name, - DEFAULT_SCHEMA_NAME, - test_table_names[i], txn) - ->GetTableOid()); + auto table_object = catalog->GetTableObject(test_db_name, DEFAULT_SCHEMA_NAME, + test_table_names[i], txn); + catalog->AddPrimaryKeyConstraint(table_object->GetDatabaseOid(), + table_object->GetTableOid(), {0}, "con_primary", txn); + test_table_oids.push_back(table_object->GetTableOid()); } } diff --git a/test/common/internal_types_test.cpp b/test/common/internal_types_test.cpp index c9782514fc6..e6a5346ee77 100644 --- a/test/common/internal_types_test.cpp +++ b/test/common/internal_types_test.cpp @@ -405,11 +405,9 @@ TEST_F(InternalTypesTests, ResultTypeTest) { TEST_F(InternalTypesTests, ConstraintTypeTest) { std::vector list = { - ConstraintType::INVALID, ConstraintType::NOT_NULL, - ConstraintType::NOTNULL, ConstraintType::DEFAULT, - ConstraintType::CHECK, ConstraintType::PRIMARY, - ConstraintType::UNIQUE, ConstraintType::FOREIGN, - ConstraintType::EXCLUSION}; + ConstraintType::INVALID, ConstraintType::CHECK, + ConstraintType::PRIMARY, ConstraintType::UNIQUE, + ConstraintType::FOREIGN, ConstraintType::EXCLUSION}; // Make sure that ToString and FromString work for (auto val : list) { diff --git a/test/concurrency/testing_transaction_util.cpp b/test/concurrency/testing_transaction_util.cpp index 5f45a0f16af..b29081b3d24 100644 --- a/test/concurrency/testing_transaction_util.cpp +++ b/test/concurrency/testing_transaction_util.cpp @@ -43,13 +43,11 @@ storage::DataTable *TestingTransactionUtil::CreateCombinedPrimaryKeyTable() { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); - id_column.AddConstraint( - std::make_shared(ConstraintType::NOTNULL, "not_null")); + id_column.SetNotNull(); auto value_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "value", true); - value_column.AddConstraint( - std::make_shared(ConstraintType::NOTNULL, "not_null")); + value_column.SetNotNull(); // Create the table catalog::Schema *table_schema = @@ -77,6 +75,12 @@ storage::DataTable *TestingTransactionUtil::CreateCombinedPrimaryKeyTable() { table->AddIndex(pkey_index); + // Create constraint on the table + std::shared_ptr constraint( + new catalog::Constraint(1000, ConstraintType::PRIMARY, + "con_primary", TEST_TABLE_OID, key_attrs, 1234)); + table->GetSchema()->AddConstraint(constraint); + // Insert tuple auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); @@ -92,8 +96,7 @@ storage::DataTable *TestingTransactionUtil::CreatePrimaryKeyUniqueKeyTable() { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); - id_column.AddConstraint( - std::make_shared(ConstraintType::NOTNULL, "not_null")); + id_column.SetNotNull(); auto value_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "value", true); @@ -124,6 +127,12 @@ storage::DataTable *TestingTransactionUtil::CreatePrimaryKeyUniqueKeyTable() { table->AddIndex(pkey_index); + // Create primary key constraint on the table + std::shared_ptr constraint( + new catalog::Constraint(1000, ConstraintType::PRIMARY, + "con_primary", TEST_TABLE_OID, key_attrs, 1234)); + table->GetSchema()->AddConstraint(constraint); + // Create unique index on the value column std::vector key_attrs2 = {1}; auto tuple_schema2 = table->GetSchema(); @@ -140,6 +149,12 @@ storage::DataTable *TestingTransactionUtil::CreatePrimaryKeyUniqueKeyTable() { table->AddIndex(ukey_index); + // Create unique constraint on the table + std::shared_ptr unique_constraint( + new catalog::Constraint(1001, ConstraintType::UNIQUE, + "con_unique", TEST_TABLE_OID, key_attrs, 1235)); + table->GetSchema()->AddConstraint(unique_constraint); + // Insert tuple auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); @@ -177,7 +192,7 @@ storage::DataTable *TestingTransactionUtil::CreateTable( key_schema->SetIndexedColumns(key_attrs); auto index_metadata = new index::IndexMetadata( - "primary_btree_index", index_oid, TEST_TABLE_OID, CATALOG_DATABASE_OID, + "primary_btree_index", index_oid, relation_id, database_id, IndexType::BWTREE, need_primary_index ? IndexConstraintType::PRIMARY_KEY : IndexConstraintType::DEFAULT, tuple_schema, key_schema, key_attrs, unique); @@ -187,6 +202,14 @@ storage::DataTable *TestingTransactionUtil::CreateTable( table->AddIndex(pkey_index); + // Create primary key constraint on the table + if (need_primary_index) { + std::shared_ptr constraint( + new catalog::Constraint(1000, ConstraintType::PRIMARY, + "con_primary", relation_id, key_attrs, index_oid)); + table->GetSchema()->AddConstraint(constraint); + } + // add this table to current database catalog::Catalog::GetInstance(); LOG_INFO("the database_id is %d", database_id); @@ -195,7 +218,7 @@ storage::DataTable *TestingTransactionUtil::CreateTable( db = storage::StorageManager::GetInstance()->GetDatabaseWithOid(database_id); } catch (CatalogException &e) { - LOG_TRACE("Can't find database %d! ", database_id); + LOG_ERROR("Can't find database %d! ", database_id); return nullptr; } PELOTON_ASSERT(db); diff --git a/test/executor/drop_test.cpp b/test/executor/drop_test.cpp index 3573cd5210f..9d57ecfd923 100644 --- a/test/executor/drop_test.cpp +++ b/test/executor/drop_test.cpp @@ -262,7 +262,7 @@ TEST_F(DropTests, DroppingIndexByName) { txn = txn_manager.BeginTransaction(); auto source_table = catalog->GetTableWithName( TEST_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table_01", txn); - oid_t col_id = source_table->GetSchema()->GetColumnID(id_column.column_name); + oid_t col_id = source_table->GetSchema()->GetColumnID(id_column.GetName()); std::vector source_col_ids; source_col_ids.push_back(col_id); std::string index_name1 = "Testing_Drop_Index_By_Name"; diff --git a/test/executor/testing_executor_util.cpp b/test/executor/testing_executor_util.cpp index fc061c78a69..95f29984a6d 100644 --- a/test/executor/testing_executor_util.cpp +++ b/test/executor/testing_executor_util.cpp @@ -80,7 +80,6 @@ void TestingExecutorUtil::DeleteDatabase(const std::string &db_name) { */ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { const bool is_inlined = true; - std::string not_null_constraint_name = "not_null"; catalog::Column dummy_column; switch (index) { @@ -89,8 +88,7 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "COL_A", is_inlined); - column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + column.SetNotNull(); return column; } break; @@ -99,8 +97,7 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "COL_B", is_inlined); - column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + column.SetNotNull(); return column; } break; @@ -109,8 +106,7 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { type::TypeId::DECIMAL, type::Type::GetTypeSize(type::TypeId::DECIMAL), "COL_C", is_inlined); - column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + column.SetNotNull(); return column; } break; @@ -119,8 +115,7 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { catalog::Column(type::TypeId::VARCHAR, 25, // Column length. "COL_D", !is_inlined); // inlined. - column.AddConstraint(std::make_shared( - ConstraintType::NOTNULL, not_null_constraint_name)); + column.SetNotNull(); return column; } break; @@ -389,7 +384,7 @@ storage::DataTable *TestingExecutorUtil::CreateTable( unique = true; index_metadata = new index::IndexMetadata( - "primary_btree_index", 123, INVALID_OID, INVALID_OID, IndexType::BWTREE, + "primary_btree_index", 123, table_oid, INVALID_OID, IndexType::BWTREE, IndexConstraintType::PRIMARY_KEY, tuple_schema, key_schema, key_attrs, unique); @@ -398,6 +393,12 @@ storage::DataTable *TestingExecutorUtil::CreateTable( table->AddIndex(pkey_index); + // Create constraint on the table + std::shared_ptr constraint( + new catalog::Constraint(1000, ConstraintType::PRIMARY, + "con_primary", table_oid, key_attrs, 123)); + table->GetSchema()->AddConstraint(constraint); + ///////////////////////////////////////////////////////////////// // Add index on table column 0 and 1 ///////////////////////////////////////////////////////////////// diff --git a/test/executor/update_test.cpp b/test/executor/update_test.cpp index 04c42162cdc..944d333fd4a 100644 --- a/test/executor/update_test.cpp +++ b/test/executor/update_test.cpp @@ -18,6 +18,7 @@ #include "binder/bind_node_visitor.h" #include "catalog/catalog.h" +#include "catalog/table_catalog.h" #include "catalog/schema.h" #include "common/internal_types.h" #include "common/logger.h" @@ -172,8 +173,6 @@ TEST_F(UpdateTests, UpdatingOld) { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "dept_id", true); - catalog::Constraint constraint(ConstraintType::PRIMARY, "con_primary"); - id_column.AddConstraint(constraint); auto manager_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "manager_id", true); @@ -182,14 +181,14 @@ TEST_F(UpdateTests, UpdatingOld) { std::unique_ptr table_schema( new catalog::Schema({id_column, manager_id_column, name_column})); - std::unique_ptr context( - new executor::ExecutorContext(txn)); - planner::CreatePlan node("department_table", DEFAULT_SCHEMA_NAME, - DEFAULT_DB_NAME, std::move(table_schema), - CreateType::TABLE); - executor::CreateExecutor create_executor(&node, context.get()); - create_executor.Init(); - create_executor.Execute(); + + catalog->CreateTable(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table", + std::move(table_schema), txn); + auto table_object = + catalog->GetTableObject(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); + catalog->AddPrimaryKeyConstraint(table_object->GetDatabaseOid(), + table_object->GetTableOid(), {0}, "con_primary", txn); LOG_INFO("Table created!"); diff --git a/test/gc/garbage_collection_test.cpp b/test/gc/garbage_collection_test.cpp index d3b24b878fc..28ffb405226 100644 --- a/test/gc/garbage_collection_test.cpp +++ b/test/gc/garbage_collection_test.cpp @@ -129,12 +129,14 @@ TEST_F(GarbageCollectionTests, UpdateTest) { oid_t db_id = database->GetOid(); EXPECT_TRUE(storage_manager->HasDatabase(db_id)); + auto prev_tc = gc_manager.GetTableCount(); + // create a table with only one key const int num_key = 1; std::unique_ptr table(TestingTransactionUtil::CreateTable( - num_key, "UPDATE_TABLE", db_id, INVALID_OID, 1234, true)); + num_key, "UPDATE_TABLE", db_id, 12345, 1234, true)); - EXPECT_TRUE(gc_manager.GetTableCount() == 1); + EXPECT_EQ(1, gc_manager.GetTableCount() - prev_tc); gc_manager.StartGC(gc_threads); @@ -222,12 +224,15 @@ TEST_F(GarbageCollectionTests, DeleteTest) { auto database = TestingExecutorUtil::InitializeDatabase("delete_db"); oid_t db_id = database->GetOid(); EXPECT_TRUE(storage_manager->HasDatabase(db_id)); + + auto prev_tc = gc_manager.GetTableCount(); + // create a table with only one key const int num_key = 1; std::unique_ptr table(TestingTransactionUtil::CreateTable( - num_key, "DELETE_TABLE", db_id, INVALID_OID, 1234, true)); + num_key, "DELETE_TABLE", db_id, 12346, 1234, true)); - EXPECT_TRUE(gc_manager.GetTableCount() == 1); + EXPECT_EQ(1, gc_manager.GetTableCount() - prev_tc); gc_manager.StartGC(gc_threads); diff --git a/test/gc/transaction_level_gc_manager_test.cpp b/test/gc/transaction_level_gc_manager_test.cpp index cef62e0cf73..70b34ef93b7 100644 --- a/test/gc/transaction_level_gc_manager_test.cpp +++ b/test/gc/transaction_level_gc_manager_test.cpp @@ -97,12 +97,14 @@ TEST_F(TransactionLevelGCManagerTests, UpdateDeleteTest) { oid_t db_id = database->GetOid(); EXPECT_TRUE(storage_manager->HasDatabase(db_id)); + auto prev_tc = gc_manager.GetTableCount(); + // create a table with only one key const int num_key = 1; std::unique_ptr table(TestingTransactionUtil::CreateTable( - num_key, "TABLE0", db_id, INVALID_OID, 1234, true)); + num_key, "TABLE0", db_id, 12345, 1234, true)); - EXPECT_TRUE(gc_manager.GetTableCount() == 1); + EXPECT_EQ(1, gc_manager.GetTableCount() - prev_tc); //=========================== // update a version here. @@ -228,12 +230,14 @@ TEST_F(TransactionLevelGCManagerTests, ReInsertTest) { oid_t db_id = database->GetOid(); EXPECT_TRUE(storage_manager->HasDatabase(db_id)); + auto prev_tc = gc_manager.GetTableCount(); + // create a table with only one key const int num_key = 1; std::unique_ptr table(TestingTransactionUtil::CreateTable( - num_key, "TABLE1", db_id, INVALID_OID, 1234, true)); + num_key, "TABLE1", db_id, 12346, 1234, true)); - EXPECT_TRUE(gc_manager.GetTableCount() == 1); + EXPECT_EQ(1, gc_manager.GetTableCount() - prev_tc); //=========================== // insert a tuple here. @@ -397,13 +401,15 @@ TEST_F(TransactionLevelGCManagerTests, ImmutabilityTest) { oid_t db_id = database->GetOid(); EXPECT_TRUE(storage_manager->HasDatabase(db_id)); + auto prev_tc = gc_manager.GetTableCount(); + // create a table with only one key const int num_key = 25; const size_t tuples_per_tilegroup = 5; std::unique_ptr table(TestingTransactionUtil::CreateTable( - num_key, "TABLE1", db_id, INVALID_OID, 1234, true, tuples_per_tilegroup)); + num_key, "TABLE1", db_id, 12347, 1234, true, tuples_per_tilegroup)); - EXPECT_TRUE(gc_manager.GetTableCount() == 1); + EXPECT_EQ(1, gc_manager.GetTableCount() - prev_tc); oid_t num_tile_groups = (table.get())->GetTileGroupCount(); EXPECT_EQ(num_tile_groups, (num_key / tuples_per_tilegroup) + 1); diff --git a/test/include/catalog/testing_constraints_util.h b/test/include/catalog/testing_constraints_util.h index 1c96b995fa9..bb8c3fb6ba7 100644 --- a/test/include/catalog/testing_constraints_util.h +++ b/test/include/catalog/testing_constraints_util.h @@ -91,26 +91,10 @@ namespace test { class TestingConstraintsUtil { public: - /** @brief Creates a basic table with allocated and populated tuples */ - static storage::DataTable *CreateAndPopulateTable( - std::vector> constraints, - std::vector multi_constraints) { - const int tuple_count = TESTS_TUPLES_PER_TILEGROUP; - storage::DataTable *table = - TestingConstraintsUtil::CreateTable(constraints, multi_constraints); - auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); - auto txn = txn_manager.BeginTransaction(); - TestingConstraintsUtil::PopulateTable( - txn, table, tuple_count * DEFAULT_TILEGROUP_COUNT); - txn_manager.CommitTransaction(txn); - - return table; - }; - /** @brief Creates a basic table with allocated but not populated tuples */ static storage::DataTable *CreateTable( - std::vector> constraints, - UNUSED_ATTRIBUTE std::vector multi_constraints, + std::vector notnull_col_ids, + std::unordered_map default_values, UNUSED_ATTRIBUTE bool indexes = true) { // Create the database auto catalog = catalog::Catalog::GetInstance(); @@ -124,13 +108,24 @@ class TestingConstraintsUtil { std::vector columns; for (int i = 0; i < CONSTRAINTS_NUM_COLS; i++) { columns.push_back( - TestingConstraintsUtil::GetColumnInfo(i, constraints[i])); + TestingConstraintsUtil::GetColumnInfo(i)); } + + // set single column constraints + for (auto col_oid : notnull_col_ids) { + PELOTON_ASSERT(col_oid < CONSTRAINTS_NUM_COLS); + columns[col_oid].SetNotNull(); + } + for (auto dv : default_values) { + PELOTON_ASSERT(dv.first < CONSTRAINTS_NUM_COLS); + columns[dv.first].SetDefaultValue(dv.second); + } + std::unique_ptr table_schema(new catalog::Schema(columns)); - std::string table_name(CONSTRAINTS_TEST_TABLE); // Create table. txn = txn_manager.BeginTransaction(); + std::string table_name(CONSTRAINTS_TEST_TABLE); auto result = catalog->CreateTable(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, table_name, std::move(table_schema), txn, false); @@ -328,6 +323,18 @@ class TestingConstraintsUtil { return executor.Execute(); }; + /** @brief Allocated and populated tuples */ + static storage::DataTable *PopulateTable(storage::DataTable *table) { + const int tuple_count = TESTS_TUPLES_PER_TILEGROUP; + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + TestingConstraintsUtil::PopulateTable( + txn, table, tuple_count * DEFAULT_TILEGROUP_COUNT); + txn_manager.CommitTransaction(txn); + + return table; + }; + static void PopulateTable(concurrency::TransactionContext *transaction, storage::DataTable *table, int num_rows) { // Ensure that the tile group is as expected. @@ -357,8 +364,7 @@ class TestingConstraintsUtil { } }; - static catalog::Column GetColumnInfo( - int index, std::vector constraints) { + static catalog::Column GetColumnInfo(int index) { catalog::Column column; switch (index) { // COL_A @@ -394,11 +400,6 @@ class TestingConstraintsUtil { std::to_string(index)); } } - - // Add any constraints that we have for this mofo - for (auto col_const : constraints) { - column.AddConstraint(col_const); - } return (column); }; diff --git a/test/include/codegen/testing_codegen_util.h b/test/include/codegen/testing_codegen_util.h index 5dc427f03b1..a9fc76e0e06 100644 --- a/test/include/codegen/testing_codegen_util.h +++ b/test/include/codegen/testing_codegen_util.h @@ -71,8 +71,7 @@ class PelotonCodeGenTest : public PelotonTest { // Create the schema (common among all tables) catalog::Column GetTestColumn(uint32_t col_id) const; - std::unique_ptr CreateTestSchema( - bool add_primary = false) const; + std::unique_ptr CreateTestSchema() const; // Create the test tables void CreateTestTables(concurrency::TransactionContext *txn, diff --git a/test/optimizer/stats_storage_test.cpp b/test/optimizer/stats_storage_test.cpp index edf42131355..131bfbdb6ac 100644 --- a/test/optimizer/stats_storage_test.cpp +++ b/test/optimizer/stats_storage_test.cpp @@ -253,4 +253,4 @@ TEST_F(StatsStorageTests, GetTableStatsTest) { } } // namespace test -} // namespace peloton \ No newline at end of file +} // namespace peloton diff --git a/test/planner/plan_util_test.cpp b/test/planner/plan_util_test.cpp index 77df6f54e88..54cc45e4fe4 100644 --- a/test/planner/plan_util_test.cpp +++ b/test/planner/plan_util_test.cpp @@ -62,7 +62,7 @@ TEST_F(PlanUtilTests, GetAffectedIndexesTest) { txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - oid_t col_id = source_table->GetSchema()->GetColumnID(id_column.column_name); + oid_t col_id = source_table->GetSchema()->GetColumnID(id_column.GetName()); std::vector source_col_ids; source_col_ids.push_back(col_id); @@ -72,7 +72,7 @@ TEST_F(PlanUtilTests, GetAffectedIndexesTest) { txn); // create index on 'id' and 'first_name' - col_id = source_table->GetSchema()->GetColumnID(fname_column.column_name); + col_id = source_table->GetSchema()->GetColumnID(fname_column.GetName()); source_col_ids.push_back(col_id); catalog->CreateIndex(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, "test_table", @@ -210,11 +210,11 @@ TEST_F(PlanUtilTests, GetIndexableColumnsTest) { oid_t table_id = source_table->GetOid(); oid_t id_col_oid = - source_table->GetSchema()->GetColumnID(id_column.column_name); + source_table->GetSchema()->GetColumnID(id_column.GetName()); oid_t fname_col_oid = - source_table->GetSchema()->GetColumnID(fname_column.column_name); + source_table->GetSchema()->GetColumnID(fname_column.GetName()); oid_t lname_col_oid = - source_table->GetSchema()->GetColumnID(lname_column.column_name); + source_table->GetSchema()->GetColumnID(lname_column.GetName()); // Insert a 'test_table_job' with 'age', 'job' and 'pid' txn = txn_manager.BeginTransaction(); @@ -238,11 +238,11 @@ TEST_F(PlanUtilTests, GetIndexableColumnsTest) { TEST_DB_COLUMNS, DEFAULT_SCHEMA_NAME, "test_table_job", txn); oid_t table_job_id = source_table_job->GetOid(); oid_t age_col_oid = - source_table_job->GetSchema()->GetColumnID(age_column.column_name); + source_table_job->GetSchema()->GetColumnID(age_column.GetName()); oid_t job_col_oid = - source_table_job->GetSchema()->GetColumnID(job_column.column_name); + source_table_job->GetSchema()->GetColumnID(job_column.GetName()); oid_t pid_col_oid = - source_table_job->GetSchema()->GetColumnID(pid_column.column_name); + source_table_job->GetSchema()->GetColumnID(pid_column.GetName()); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); diff --git a/test/planner/planner_test.cpp b/test/planner/planner_test.cpp index 5fd1709eaca..53877f37014 100644 --- a/test/planner/planner_test.cpp +++ b/test/planner/planner_test.cpp @@ -183,10 +183,10 @@ TEST_F(PlannerTest, UpdatePlanTestParameter) { ExpressionType::COMPARE_EQUAL, tuple_expr, parameter_expr); auto &schema_columns = schema->GetColumns(); - for (uint i = 0; i < schema_columns.size(); i++) { + for (oid_t i = 0; i < schema_columns.size(); i++) { bool is_in_target_list = false; for (auto col_id : column_ids) { - if (schema_columns[i].column_name == schema_columns[col_id].column_name) { + if (schema_columns[i].GetName() == schema_columns[col_id].GetName()) { is_in_target_list = true; break; } @@ -196,7 +196,7 @@ TEST_F(PlannerTest, UpdatePlanTestParameter) { } column_ids.clear(); - for (uint i = 0; i < schema_columns.size(); i++) { + for (oid_t i = 0; i < schema_columns.size(); i++) { column_ids.emplace_back(i); } diff --git a/test/sql/optimizer_sql_test.cpp b/test/sql/optimizer_sql_test.cpp index 3855c015e20..3343f09ab7f 100644 --- a/test/sql/optimizer_sql_test.cpp +++ b/test/sql/optimizer_sql_test.cpp @@ -337,7 +337,7 @@ TEST_F(OptimizerSQLTests, DDLSqlTest) { auto cols = table->GetSchema()->GetColumns(); EXPECT_EQ(3, cols.size()); EXPECT_EQ("a", cols[0].GetName()); - EXPECT_EQ(true, cols[0].IsPrimary()); + EXPECT_EQ(true, table->GetSchema()->HasPrimary()); EXPECT_EQ(type::TypeId::INTEGER, cols[0].GetType()); EXPECT_EQ("b", cols[1].GetName()); EXPECT_EQ(type::TypeId::INTEGER, cols[1].GetType()); diff --git a/test/statistics/stats_test.cpp b/test/statistics/stats_test.cpp index ef3c7da6cba..c06f4f536ae 100644 --- a/test/statistics/stats_test.cpp +++ b/test/statistics/stats_test.cpp @@ -128,8 +128,6 @@ TEST_F(StatsTests, MultiThreadStatsTest) { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "dept_id", true); - catalog::Constraint constraint(ConstraintType::PRIMARY, "con_primary"); - id_column.AddConstraint(constraint); auto name_column = catalog::Column(type::TypeId::VARCHAR, 32, "dept_name", false); @@ -146,6 +144,10 @@ TEST_F(StatsTests, MultiThreadStatsTest) { catalog->GetDatabaseWithName("emp_db", txn); storage::DataTable *table = catalog->GetTableWithName( "emp_db", DEFAULT_SCHEMA_NAME, "department_table", txn); + + catalog->AddPrimaryKeyConstraint(database->GetOid(), table->GetOid(), {0}, + "con_primary", txn); + txn_manager.CommitTransaction(txn); LaunchParallelTest(num_threads, TransactionTest, database, table); // Wait for aggregation to finish diff --git a/test/statistics/testing_stats_util.cpp b/test/statistics/testing_stats_util.cpp index dca7aca2dee..022cf8db06b 100644 --- a/test/statistics/testing_stats_util.cpp +++ b/test/statistics/testing_stats_util.cpp @@ -12,6 +12,8 @@ #include "statistics/testing_stats_util.h" +#include "catalog/catalog.h" +#include "catalog/table_catalog.h" #include "executor/delete_executor.h" #include "executor/executor_context.h" #include "executor/insert_executor.h" @@ -112,25 +114,23 @@ void TestingStatsUtil::CreateTable(bool has_primary_key) { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "dept_id", true); - if (has_primary_key) { - std::shared_ptr constraint( - new catalog::Constraint(ConstraintType::PRIMARY, "con_primary")); - id_column.AddConstraint(constraint); - } auto name_column = catalog::Column(type::TypeId::VARCHAR, 256, "dept_name", false); - std::unique_ptr table_schema( new catalog::Schema({id_column, name_column})); + + auto catalog = catalog::Catalog::GetInstance(); auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); - std::unique_ptr context( - new executor::ExecutorContext(txn)); - planner::CreatePlan node("department_table", DEFAULT_SCHEMA_NAME, "emp_db", - std::move(table_schema), CreateType::TABLE); - executor::CreateExecutor create_executor(&node, context.get()); - create_executor.Init(); - create_executor.Execute(); + catalog->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, "department_table", + std::move(table_schema), txn); + + if (has_primary_key) { + auto table_object = catalog->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, + "department_table", txn); + catalog->AddPrimaryKeyConstraint(table_object->GetDatabaseOid(), + table_object->GetTableOid(), {0}, "con_primary", txn); + } txn_manager.CommitTransaction(txn); } From 058569422ac8cc24d7e9bf257dc8b20954c3770b Mon Sep 17 00:00:00 2001 From: ksaito7 Date: Mon, 18 Jun 2018 16:13:29 -0400 Subject: [PATCH 03/10] Formatting and add constraint tests --- src/catalog/catalog.cpp | 471 ++++++++--------- src/catalog/column_catalog.cpp | 125 +++-- src/catalog/constraint_catalog.cpp | 295 +++++------ src/executor/create_executor.cpp | 109 ++-- src/include/catalog/catalog.h | 49 +- src/include/catalog/column_catalog.h | 18 +- src/include/catalog/constraint_catalog.h | 38 +- src/include/storage/data_table.h | 24 +- src/planner/create_plan.cpp | 42 +- src/storage/data_table.cpp | 138 ++--- test/catalog/catalog_test.cpp | 336 ++++++------ test/catalog/constraints_test.cpp | 618 ++++++++++------------- 12 files changed, 1113 insertions(+), 1150 deletions(-) diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 2ce3092984a..732d72d18b3 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -97,9 +97,8 @@ void Catalog::BootstrapSystemCatalogs(storage::Database *database, system_catalogs->GetIndexCatalog()->InsertIndex( COLUMN_CATALOG_PKEY_OID, COLUMN_CATALOG_NAME "_pkey", COLUMN_CATALOG_OID, CATALOG_SCHEMA_NAME, IndexType::BWTREE, IndexConstraintType::PRIMARY_KEY, - true, - {ColumnCatalog::ColumnId::TABLE_OID, - ColumnCatalog::ColumnId::COLUMN_NAME}, + true, {ColumnCatalog::ColumnId::TABLE_OID, + ColumnCatalog::ColumnId::COLUMN_NAME}, pool_.get(), txn); system_catalogs->GetIndexCatalog()->InsertIndex( COLUMN_CATALOG_SKEY0_OID, COLUMN_CATALOG_NAME "_skey0", @@ -164,22 +163,23 @@ void Catalog::BootstrapSystemCatalogs(storage::Database *database, LAYOUT_CATALOG_PKEY_OID, LAYOUT_CATALOG_NAME "_pkey", LAYOUT_CATALOG_OID, CATALOG_SCHEMA_NAME, IndexType::BWTREE, IndexConstraintType::PRIMARY_KEY, true, - {LayoutCatalog::ColumnId::TABLE_OID, LayoutCatalog::ColumnId::LAYOUT_OID}, - pool_.get(), txn); + {LayoutCatalog::ColumnId::TABLE_OID, LayoutCatalog::ColumnId::LAYOUT_OID}, + pool_.get(), txn); system_catalogs->GetIndexCatalog()->InsertIndex( - LAYOUT_CATALOG_SKEY0_OID, LAYOUT_CATALOG_NAME "_skey0", LAYOUT_CATALOG_OID, - CATALOG_SCHEMA_NAME, IndexType::BWTREE, IndexConstraintType::DEFAULT, true, - {LayoutCatalog::ColumnId::TABLE_OID}, pool_.get(), txn); + LAYOUT_CATALOG_SKEY0_OID, LAYOUT_CATALOG_NAME "_skey0", + LAYOUT_CATALOG_OID, CATALOG_SCHEMA_NAME, IndexType::BWTREE, + IndexConstraintType::DEFAULT, true, {LayoutCatalog::ColumnId::TABLE_OID}, + pool_.get(), txn); system_catalogs->GetIndexCatalog()->InsertIndex( CONSTRAINT_CATALOG_PKEY_OID, CONSTRAINT_CATALOG_NAME "_pkey", - CONSTRAINT_CATALOG_OID, CATALOG_SCHEMA_NAME, IndexType::BWTREE, - IndexConstraintType::PRIMARY_KEY, true, - {ConstraintCatalog::ColumnId::CONSTRAINT_OID}, pool_.get(), txn); + CONSTRAINT_CATALOG_OID, CATALOG_SCHEMA_NAME, IndexType::BWTREE, + IndexConstraintType::PRIMARY_KEY, true, + {ConstraintCatalog::ColumnId::CONSTRAINT_OID}, pool_.get(), txn); system_catalogs->GetIndexCatalog()->InsertIndex( - CONSTRAINT_CATALOG_SKEY0_OID, CONSTRAINT_CATALOG_NAME "_skey0", - CONSTRAINT_CATALOG_OID, CATALOG_SCHEMA_NAME, IndexType::BWTREE, - IndexConstraintType::DEFAULT, true, + CONSTRAINT_CATALOG_SKEY0_OID, CONSTRAINT_CATALOG_NAME "_skey0", + CONSTRAINT_CATALOG_OID, CATALOG_SCHEMA_NAME, IndexType::BWTREE, + IndexConstraintType::DEFAULT, true, {ConstraintCatalog::ColumnId::TABLE_OID}, pool_.get(), txn); // Insert records(default + pg_catalog namespace) into pg_namespace @@ -404,19 +404,19 @@ ResultType Catalog::CreateTable(const std::string &database_name, for (const auto &column : table->GetSchema()->GetColumns()) { pg_attribute->InsertColumn(table_oid, column.GetName(), column_id, column.GetOffset(), column.GetType(), - column.GetLength(), column.IsInlined(), - column.IsNotNull(), column.HasDefault(), - column.GetDefaultValue(), pool_.get(), txn); + column.GetLength(), column.IsInlined(), + column.IsNotNull(), column.HasDefault(), + column.GetDefaultValue(), pool_.get(), txn); column_id++; } // Create layout as default layout auto pg_layout = - catalog_map_[database_object->GetDatabaseOid()]->GetLayoutCatalog(); + catalog_map_[database_object->GetDatabaseOid()]->GetLayoutCatalog(); auto default_layout = table->GetDefaultLayout(); if (!pg_layout->InsertLayout(table_oid, default_layout, pool_.get(), txn)) - throw CatalogException("Failed to create a new layout for table " - + table_name); + throw CatalogException("Failed to create a new layout for table " + + table_name); return ResultType::SUCCESS; } @@ -462,7 +462,7 @@ ResultType Catalog::CreateIndex(const std::string &database_name, table_name + " to create index"); auto pg_index = - catalog_map_[database_object->GetDatabaseOid()]->GetIndexCatalog(); + catalog_map_[database_object->GetDatabaseOid()]->GetIndexCatalog(); oid_t index_oid = pg_index->GetNextOid(); IndexConstraintType index_constraint = unique_keys ? IndexConstraintType::UNIQUE : IndexConstraintType::DEFAULT; @@ -470,16 +470,17 @@ ResultType Catalog::CreateIndex(const std::string &database_name, ResultType success = CreateIndex( database_object->GetDatabaseOid(), table_object->GetTableOid(), key_attrs, schema_name, index_oid, index_name, index_type, index_constraint, - unique_keys, txn); + unique_keys, txn); return success; } ResultType Catalog::CreateIndex( oid_t database_oid, oid_t table_oid, const std::vector &key_attrs, - const std::string &schema_name, oid_t index_oid, const std::string &index_name, - IndexType index_type, IndexConstraintType index_constraint, - bool unique_keys, concurrency::TransactionContext *txn, bool is_catalog) { + const std::string &schema_name, oid_t index_oid, + const std::string &index_name, IndexType index_type, + IndexConstraintType index_constraint, bool unique_keys, + concurrency::TransactionContext *txn, bool is_catalog) { if (txn == nullptr) throw CatalogException("Do not have transaction to create index " + index_name); @@ -547,11 +548,11 @@ std::shared_ptr Catalog::CreateLayout( // Add the layout the pg_layout table auto pg_layout = catalog_map_[database_oid]->GetLayoutCatalog(); - if (pg_layout->GetLayoutWithOid(table_oid, new_layout->GetOid(), txn) - == nullptr && - !pg_layout->InsertLayout(table_oid, new_layout, pool_.get(), txn)) { - LOG_ERROR("Failed to create a new layout for table %u", table_oid); - return nullptr; + if (pg_layout->GetLayoutWithOid(table_oid, new_layout->GetOid(), txn) == + nullptr && + !pg_layout->InsertLayout(table_oid, new_layout, pool_.get(), txn)) { + LOG_ERROR("Failed to create a new layout for table %u", table_oid); + return nullptr; } return new_layout; } @@ -568,8 +569,8 @@ std::shared_ptr Catalog::CreateDefaultLayout( table->SetDefaultLayout(new_layout); // update table catalog - catalog_map_[database_oid]->GetTableCatalog() - ->UpdateDefaultLayoutOid(new_layout->GetOid(), table_oid, txn); + catalog_map_[database_oid]->GetTableCatalog()->UpdateDefaultLayoutOid( + new_layout->GetOid(), table_oid, txn); } return new_layout; } @@ -587,31 +588,35 @@ std::shared_ptr Catalog::CreateDefaultLayout( * @return ResultType(SUCCESS or FAILURE) */ ResultType Catalog::SetNotNullConstraint(oid_t database_oid, oid_t table_oid, - oid_t column_id, concurrency::TransactionContext *txn) { - auto table_object = catalog_map_[database_oid]->GetTableCatalog() - ->GetTableObject(table_oid, txn); + oid_t column_id, + concurrency::TransactionContext *txn) { + auto table_object = + catalog_map_[database_oid]->GetTableCatalog()->GetTableObject(table_oid, + txn); auto schema = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, table_oid) - ->GetSchema(); + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); auto column = schema->GetColumn(column_id); // Check not null if (column.IsNotNull()) { - throw CatalogException("Column " + column.GetName() + - " in table " + table_object->GetTableName() + - " is already NOT NULL."); + throw CatalogException("Column " + column.GetName() + " in table " + + table_object->GetTableName() + + " is already NOT NULL."); } - // Update pg_column to set constraint of the column auto pg_column = catalog_map_[database_oid]->GetColumnCatalog(); pg_column->UpdateNotNullConstraint(table_oid, column.GetName(), true, txn); // Set not null constraint in the schema - { - std::lock_guard lock(catalog_mutex); - schema->SetNotNull(column_id); - } + { + std::lock_guard lock(catalog_mutex); + schema->SetNotNull(column_id); + } + + LOG_TRACE("Added a NOT NULL constraint to column %s in %s.", + column.GetName().c_str(), table_object->GetTableName().c_str()); return ResultType::SUCCESS; } @@ -626,36 +631,40 @@ ResultType Catalog::SetNotNullConstraint(oid_t database_oid, oid_t table_oid, * @return ResultType(SUCCESS or FAILURE) */ ResultType Catalog::SetDefaultConstraint(oid_t database_oid, oid_t table_oid, - oid_t column_id, const type::Value &default_value, - concurrency::TransactionContext *txn) { - auto table_object = catalog_map_[database_oid]->GetTableCatalog() - ->GetTableObject(table_oid, txn); + oid_t column_id, + const type::Value &default_value, + concurrency::TransactionContext *txn) { + auto table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn); auto schema = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, table_oid) - ->GetSchema(); + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); auto column = schema->GetColumn(column_id); // Check default if (column.HasDefault()) { - throw CatalogException("Column " + column.GetName() - + " in table" + table_object->GetTableName() - + " is already set default value '" + column.GetDefaultValue()->ToString() - + "'."); + throw CatalogException("Column " + column.GetName() + " in table" + + table_object->GetTableName() + + " is already set default value '" + + column.GetDefaultValue()->ToString() + "'."); } // Update pg_column to set constraint of the column auto pg_column = catalog_map_[database_oid]->GetColumnCatalog(); - pg_column->UpdateDefaultConstraint(table_oid, column.GetName(), true, &default_value, txn); + pg_column->UpdateDefaultConstraint(table_oid, column.GetName(), true, + &default_value, txn); // Set default constraint in the schema - { - std::lock_guard lock(catalog_mutex); - schema->SetDefaultValue(column_id, default_value); - } + { + std::lock_guard lock(catalog_mutex); + schema->SetDefaultValue(column_id, default_value); + } - return ResultType::SUCCESS; -} + LOG_TRACE("Added a DEFAULT constraint to column %s in %s.", + column.GetName().c_str(), table_object->GetTableName().c_str()); + return ResultType::SUCCESS; +} //===--------------------------------------------------------------------===// // ADD FUNCTIONS FOR TABLE CONSTRAINT @@ -670,43 +679,44 @@ ResultType Catalog::SetDefaultConstraint(oid_t database_oid, oid_t table_oid, * @param txn TransactionContext * @return ResultType(SUCCESS or FAILURE) */ -ResultType Catalog::AddPrimaryKeyConstraint(oid_t database_oid, oid_t table_oid, - const std::vector &column_ids, const std::string &constraint_name, - concurrency::TransactionContext *txn) { - auto table_object = catalog_map_[database_oid]->GetTableCatalog() - ->GetTableObject(table_oid, txn); +ResultType Catalog::AddPrimaryKeyConstraint( + oid_t database_oid, oid_t table_oid, const std::vector &column_ids, + const std::string &constraint_name, concurrency::TransactionContext *txn) { + auto table_object = + catalog_map_[database_oid]->GetTableCatalog()->GetTableObject(table_oid, + txn); auto schema = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, table_oid) - ->GetSchema(); + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); // Check primary key in the table if (schema->HasPrimary()) { - throw CatalogException("Table " + table_object->GetTableName() - + " already has primary key."); + throw CatalogException("Table " + table_object->GetTableName() + + " already has primary key."); } // Create index - std::string index_name = table_object->GetTableName() + "_pkey"; - auto index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); - CreateIndex(database_oid, table_oid, column_ids, table_object->GetSchemaName(), - index_oid, index_name, IndexType::BWTREE, - IndexConstraintType::PRIMARY_KEY, true, txn); + std::string index_name = table_object->GetTableName() + "_pkey"; + auto index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); + CreateIndex(database_oid, table_oid, column_ids, + table_object->GetSchemaName(), index_oid, index_name, + IndexType::BWTREE, IndexConstraintType::PRIMARY_KEY, true, txn); // Insert constraint into pg_constraint auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); std::shared_ptr constraint( - new Constraint(pg_constraint->GetNextOid(), ConstraintType::PRIMARY, + new Constraint(pg_constraint->GetNextOid(), ConstraintType::PRIMARY, constraint_name, table_oid, column_ids, index_oid)); pg_constraint->InsertConstraint(constraint, pool_.get(), txn); // Add constraint into the schema - { - std::lock_guard lock(catalog_mutex); - schema->AddConstraint(constraint); - } + { + std::lock_guard lock(catalog_mutex); + schema->AddConstraint(constraint); + } - LOG_DEBUG("Added a PRIMARY KEY constraint in %s.", - table_object->GetTableName().c_str()); + LOG_TRACE("Added a PRIMARY KEY constraint in %s.", + table_object->GetTableName().c_str()); return ResultType::SUCCESS; } @@ -722,39 +732,40 @@ ResultType Catalog::AddPrimaryKeyConstraint(oid_t database_oid, oid_t table_oid, * note: if add a new foreign key constraint, use AddForeignKeyConstraint */ ResultType Catalog::AddUniqueConstraint(oid_t database_oid, oid_t table_oid, - const std::vector &column_ids, const std::string &constraint_name, - concurrency::TransactionContext *txn) { - auto table_object = catalog_map_[database_oid]->GetTableCatalog() - ->GetTableObject(table_oid, txn); + const std::vector &column_ids, + const std::string &constraint_name, + concurrency::TransactionContext *txn) { + auto table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn); auto schema = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, table_oid) - ->GetSchema(); + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); // Create index std::stringstream index_name(table_object->GetTableName().c_str()); for (auto column_id : column_ids) - index_name << "_" + schema->GetColumn(column_id).GetName(); + index_name << "_" + schema->GetColumn(column_id).GetName(); index_name << "_UNIQ"; auto index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); - CreateIndex(database_oid, table_oid, column_ids, table_object->GetSchemaName(), - index_oid, index_name.str(), IndexType::BWTREE, - IndexConstraintType::UNIQUE, true, txn); + CreateIndex(database_oid, table_oid, column_ids, + table_object->GetSchemaName(), index_oid, index_name.str(), + IndexType::BWTREE, IndexConstraintType::UNIQUE, true, txn); // Insert constraint into pg_constraint auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); std::shared_ptr constraint( - new Constraint(pg_constraint->GetNextOid(), ConstraintType::UNIQUE, + new Constraint(pg_constraint->GetNextOid(), ConstraintType::UNIQUE, constraint_name, table_oid, column_ids, index_oid)); pg_constraint->InsertConstraint(constraint, pool_.get(), txn); // Add constraint into the schema - { - std::lock_guard lock(catalog_mutex); - schema->AddConstraint(constraint); - } + { + std::lock_guard lock(catalog_mutex); + schema->AddConstraint(constraint); + } - LOG_DEBUG("Added a UNIQUE constraint in %s.", - table_object->GetTableName().c_str()); + LOG_TRACE("Added a UNIQUE constraint in %s.", + table_object->GetTableName().c_str()); return ResultType::SUCCESS; } @@ -772,54 +783,56 @@ ResultType Catalog::AddUniqueConstraint(oid_t database_oid, oid_t table_oid, * @param txn TransactionContext * @return ResultType(SUCCESS or FAILURE) */ -ResultType Catalog::AddForeignKeyConstraint(oid_t database_oid, - oid_t src_table_oid, const std::vector &src_col_ids, - oid_t sink_table_oid, const std::vector &sink_col_ids, - FKConstrActionType upd_action, FKConstrActionType del_action, - const std::string &constraint_name, - concurrency::TransactionContext *txn) { - +ResultType Catalog::AddForeignKeyConstraint( + oid_t database_oid, oid_t src_table_oid, + const std::vector &src_col_ids, oid_t sink_table_oid, + const std::vector &sink_col_ids, FKConstrActionType upd_action, + FKConstrActionType del_action, const std::string &constraint_name, + concurrency::TransactionContext *txn) { auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); - auto constraint_oid = pg_constraint->GetNextOid(); + auto constraint_oid = pg_constraint->GetNextOid(); auto storage_manager = storage::StorageManager::GetInstance(); auto src_table = - storage_manager->GetTableWithOid(database_oid, src_table_oid); + storage_manager->GetTableWithOid(database_oid, src_table_oid); auto sink_table = - storage_manager->GetTableWithOid(database_oid, sink_table_oid); - - // Add a non-unique index on the source table if needed - auto src_table_object = catalog_map_[database_oid]->GetTableCatalog() - ->GetTableObject(src_table_oid, txn); - auto src_schema = src_table->GetSchema(); - - std::stringstream index_name(src_table_object->GetTableName().c_str()); - for (auto col_id : src_col_ids) - index_name << "_" << src_schema->GetColumn(col_id).GetName(); - index_name << "_fkey"; + storage_manager->GetTableWithOid(database_oid, sink_table_oid); + + // Add a non-unique index on the source table if needed + auto src_table_object = + catalog_map_[database_oid]->GetTableCatalog()->GetTableObject( + src_table_oid, txn); + auto src_schema = src_table->GetSchema(); + + std::stringstream index_name(src_table_object->GetTableName().c_str()); + for (auto col_id : src_col_ids) + index_name << "_" << src_schema->GetColumn(col_id).GetName(); + index_name << "_fkey"; oid_t index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); - CreateIndex(database_oid, src_table_oid, src_col_ids, - src_table_object->GetSchemaName(), index_oid, index_name.str(), - IndexType::BWTREE, IndexConstraintType::DEFAULT, false, txn); + CreateIndex(database_oid, src_table_oid, src_col_ids, + src_table_object->GetSchemaName(), index_oid, index_name.str(), + IndexType::BWTREE, IndexConstraintType::DEFAULT, false, txn); // Insert constraint into pg_constraint std::shared_ptr constraint( - new Constraint(constraint_oid, ConstraintType::FOREIGN, constraint_name, + new Constraint(constraint_oid, ConstraintType::FOREIGN, constraint_name, src_table_oid, src_col_ids, index_oid, sink_table_oid, - sink_col_ids, upd_action, del_action)); + sink_col_ids, upd_action, del_action)); pg_constraint->InsertConstraint(constraint, pool_.get(), txn); // add constraint into schema in source table and sink table - { - std::lock_guard lock(catalog_mutex); - src_schema->AddConstraint(constraint); - sink_table->GetSchema()->RegisterForeignKeySource(constraint); - } - - LOG_DEBUG("Added a FOREIGN KEY constraint in %s to %s.", - src_table_object->GetTableName().c_str(), - catalog_map_[database_oid]->GetTableCatalog() - ->GetTableObject(sink_table_oid, txn) - ->GetTableName().c_str()); + { + std::lock_guard lock(catalog_mutex); + src_schema->AddConstraint(constraint); + sink_table->GetSchema()->RegisterForeignKeySource(constraint); + } + + LOG_TRACE("Added a FOREIGN KEY constraint in %s to %s.", + src_table_object->GetTableName().c_str(), + catalog_map_[database_oid] + ->GetTableCatalog() + ->GetTableObject(sink_table_oid, txn) + ->GetTableName() + .c_str()); return ResultType::SUCCESS; } @@ -836,33 +849,31 @@ ResultType Catalog::AddForeignKeyConstraint(oid_t database_oid, * @return ResultType(SUCCESS or FAILURE) * note: if add a new foreign key constraint, use AddForeignKeyConstraint */ -ResultType Catalog::AddCheckConstraint(oid_t database_oid, oid_t table_oid, - const std::vector &column_ids, - const std::pair &exp, - const std::string &constraint_name, - concurrency::TransactionContext *txn) { - auto table_object = catalog_map_[database_oid]->GetTableCatalog() - ->GetTableObject(table_oid, txn); +ResultType Catalog::AddCheckConstraint( + oid_t database_oid, oid_t table_oid, const std::vector &column_ids, + const std::pair &exp, + const std::string &constraint_name, concurrency::TransactionContext *txn) { + auto table_object = catalog_map_[database_oid]->GetTableCatalog() + ->GetTableObject(table_oid, txn); auto schema = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, table_oid) - ->GetSchema(); + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); // Insert constraint into pg_constraint auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); std::shared_ptr constraint( - new Constraint(pg_constraint->GetNextOid(), ConstraintType::CHECK, - constraint_name, table_oid, column_ids, INVALID_OID, - exp)); + new Constraint(pg_constraint->GetNextOid(), ConstraintType::CHECK, + constraint_name, table_oid, column_ids, INVALID_OID, exp)); pg_constraint->InsertConstraint(constraint, pool_.get(), txn); // Add constraint into the schema - { - std::lock_guard lock(catalog_mutex); - schema->AddConstraint(constraint); - } + { + std::lock_guard lock(catalog_mutex); + schema->AddConstraint(constraint); + } - LOG_DEBUG("Added a CHECK constraint in %s.", - table_object->GetTableName().c_str()); + LOG_TRACE("Added a CHECK constraint in %s.", + table_object->GetTableName().c_str()); return ResultType::SUCCESS; } @@ -1105,22 +1116,21 @@ ResultType Catalog::DropLayout(oid_t database_oid, oid_t table_oid, table->ResetDefaultLayout(); auto new_default_layout = table->GetDefaultLayout(); if (pg_layout->GetLayoutWithOid(table_oid, new_default_layout->GetOid(), - txn) == nullptr && - !pg_layout->InsertLayout(table_oid, new_default_layout, - pool_.get(), txn)) { + txn) == nullptr && + !pg_layout->InsertLayout(table_oid, new_default_layout, pool_.get(), + txn)) { LOG_DEBUG("Failed to create a new layout for table %d", table_oid); return ResultType::FAILURE; } // update table catalog - catalog_map_[database_oid]->GetTableCatalog() - ->UpdateDefaultLayoutOid(new_default_layout->GetOid(), table_oid, txn); + catalog_map_[database_oid]->GetTableCatalog()->UpdateDefaultLayoutOid( + new_default_layout->GetOid(), table_oid, txn); } return ResultType::SUCCESS; } - /** * @brief Drop not null constraint for a column * @param database_oid the database to which the table belongs to @@ -1129,21 +1139,21 @@ ResultType Catalog::DropLayout(oid_t database_oid, oid_t table_oid, * @param txn TransactionContext * @return ResultType(SUCCESS or FAILURE) */ -ResultType Catalog::DropNotNullConstraint(oid_t database_oid, - oid_t table_oid, oid_t column_id, - concurrency::TransactionContext *txn) { - auto table_object = catalog_map_[database_oid]->GetTableCatalog() - ->GetTableObject(table_oid, txn); +ResultType Catalog::DropNotNullConstraint( + oid_t database_oid, oid_t table_oid, oid_t column_id, + concurrency::TransactionContext *txn) { + auto table_object = + catalog_map_[database_oid]->GetTableCatalog()->GetTableObject(table_oid, + txn); auto schema = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, table_oid) - ->GetSchema(); + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); auto column = schema->GetColumn(column_id); // Check not null if (!column.IsNotNull()) { - throw CatalogException("Column " + column.GetName() + - " in table " + table_object->GetTableName() + - " isn't NOT NULL."); + throw CatalogException("Column " + column.GetName() + " in table " + + table_object->GetTableName() + " isn't NOT NULL."); } // Update pg_column to set constraint of the column @@ -1151,13 +1161,12 @@ ResultType Catalog::DropNotNullConstraint(oid_t database_oid, pg_column->UpdateNotNullConstraint(table_oid, column.GetName(), false, txn); // Set not null constraint in the schema - { - std::lock_guard lock(catalog_mutex); - schema->DropNotNull(column_id); - } + { + std::lock_guard lock(catalog_mutex); + schema->DropNotNull(column_id); + } return ResultType::SUCCESS; - } /** @@ -1168,34 +1177,36 @@ ResultType Catalog::DropNotNullConstraint(oid_t database_oid, * @param txn TransactionContext * @return ResultType(SUCCESS or FAILURE) */ -ResultType Catalog::DropDefaultConstraint(oid_t database_oid, - oid_t table_oid, oid_t column_id, - concurrency::TransactionContext *txn) { - auto table_object = catalog_map_[database_oid]->GetTableCatalog() - ->GetTableObject(table_oid, txn); +ResultType Catalog::DropDefaultConstraint( + oid_t database_oid, oid_t table_oid, oid_t column_id, + concurrency::TransactionContext *txn) { + auto table_object = + catalog_map_[database_oid]->GetTableCatalog()->GetTableObject(table_oid, + txn); auto schema = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, table_oid) - ->GetSchema(); + ->GetTableWithOid(database_oid, table_oid) + ->GetSchema(); auto column = schema->GetColumn(column_id); // Check default if (!column.HasDefault()) { - throw CatalogException("Column " + column.GetName() - + " in table" + table_object->GetTableName() - + " doesn't have default value."); + throw CatalogException("Column " + column.GetName() + " in table" + + table_object->GetTableName() + + " doesn't have default value."); } // Update pg_column to set constraint of the column auto pg_column = catalog_map_[database_oid]->GetColumnCatalog(); - pg_column->UpdateDefaultConstraint(table_oid, column.GetName(), false, nullptr, txn); + pg_column->UpdateDefaultConstraint(table_oid, column.GetName(), false, + nullptr, txn); // Set default constraint in the schema - { - std::lock_guard lock(catalog_mutex); - schema->DropDefaultValue(column_id); - } + { + std::lock_guard lock(catalog_mutex); + schema->DropDefaultValue(column_id); + } - return ResultType::SUCCESS; + return ResultType::SUCCESS; } /** @@ -1207,40 +1218,42 @@ ResultType Catalog::DropDefaultConstraint(oid_t database_oid, * @return ResultType(SUCCESS or FAILURE) */ ResultType Catalog::DropConstraint(oid_t database_oid, oid_t table_oid, - oid_t constraint_oid, + oid_t constraint_oid, concurrency::TransactionContext *txn) { - auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); - auto constraint_object = - pg_constraint->GetConstraintObject(table_oid, constraint_oid, txn); + auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); + auto constraint_object = + pg_constraint->GetConstraintObject(table_oid, constraint_oid, txn); // delete constraint object from pg_constraint if (!pg_constraint->DeleteConstraint(table_oid, constraint_oid, txn)) { - throw CatalogException("Failed to delete the constraint: " - + std::to_string(constraint_oid)); + throw CatalogException("Failed to delete the constraint: " + + std::to_string(constraint_oid)); } // delete index if exists if (constraint_object->GetIndexOid() != INVALID_OID) { - DropIndex(database_oid, constraint_object->GetIndexOid(), txn); + DropIndex(database_oid, constraint_object->GetIndexOid(), txn); } - // delete constraint from table + // delete constraint from table auto storage_manager = storage::StorageManager::GetInstance(); auto table = storage_manager->GetTableWithOid(database_oid, table_oid); table->GetSchema()->DropConstraint(constraint_oid); if (constraint_object->GetConstraintType() == ConstraintType::FOREIGN) { - auto sink_table = storage_manager - ->GetTableWithOid(database_oid, - constraint_object->GetFKSinkTableOid()); - sink_table->GetSchema() - ->DeleteForeignKeySource(constraint_object->GetConstraintOid()); + auto sink_table = storage_manager->GetTableWithOid( + database_oid, constraint_object->GetFKSinkTableOid()); + sink_table->GetSchema()->DeleteForeignKeySource( + constraint_object->GetConstraintOid()); } - LOG_DEBUG("Drop a %s constraint in %s.", - ConstraintTypeToString(constraint_object->GetConstraintType()).c_str(), - catalog_map_[database_oid]->GetTableCatalog() - ->GetTableObject(table_oid, txn) - ->GetTableName().c_str()); + LOG_TRACE( + "Drop a %s constraint in %s.", + ConstraintTypeToString(constraint_object->GetConstraintType()).c_str(), + catalog_map_[database_oid] + ->GetTableCatalog() + ->GetTableObject(table_oid, txn) + ->GetTableName() + .c_str()); return ResultType::SUCCESS; } @@ -1696,9 +1709,8 @@ void Catalog::InitializeFunctions() { txn); AddBuiltinFunction( "sqrt", {type::TypeId::TINYINT}, type::TypeId::DECIMAL, internal_lang, - "Sqrt", - function::BuiltInFuncType{OperatorId::Sqrt, - function::NumericFunctions::Sqrt}, + "Sqrt", function::BuiltInFuncType{OperatorId::Sqrt, + function::NumericFunctions::Sqrt}, txn); AddBuiltinFunction( "sqrt", {type::TypeId::SMALLINT}, type::TypeId::DECIMAL, @@ -1708,21 +1720,18 @@ void Catalog::InitializeFunctions() { txn); AddBuiltinFunction( "sqrt", {type::TypeId::INTEGER}, type::TypeId::DECIMAL, internal_lang, - "Sqrt", - function::BuiltInFuncType{OperatorId::Sqrt, - function::NumericFunctions::Sqrt}, + "Sqrt", function::BuiltInFuncType{OperatorId::Sqrt, + function::NumericFunctions::Sqrt}, txn); AddBuiltinFunction( "sqrt", {type::TypeId::BIGINT}, type::TypeId::DECIMAL, internal_lang, - "Sqrt", - function::BuiltInFuncType{OperatorId::Sqrt, - function::NumericFunctions::Sqrt}, + "Sqrt", function::BuiltInFuncType{OperatorId::Sqrt, + function::NumericFunctions::Sqrt}, txn); AddBuiltinFunction( "sqrt", {type::TypeId::DECIMAL}, type::TypeId::DECIMAL, internal_lang, - "Sqrt", - function::BuiltInFuncType{OperatorId::Sqrt, - function::NumericFunctions::Sqrt}, + "Sqrt", function::BuiltInFuncType{OperatorId::Sqrt, + function::NumericFunctions::Sqrt}, txn); AddBuiltinFunction( "floor", {type::TypeId::DECIMAL}, type::TypeId::DECIMAL, @@ -1791,16 +1800,14 @@ void Catalog::InitializeFunctions() { AddBuiltinFunction( "ceil", {type::TypeId::DECIMAL}, type::TypeId::DECIMAL, internal_lang, - "Ceil", - function::BuiltInFuncType{OperatorId::Ceil, - function::NumericFunctions::_Ceil}, + "Ceil", function::BuiltInFuncType{OperatorId::Ceil, + function::NumericFunctions::_Ceil}, txn); AddBuiltinFunction( "ceil", {type::TypeId::TINYINT}, type::TypeId::DECIMAL, internal_lang, - "Ceil", - function::BuiltInFuncType{OperatorId::Ceil, - function::NumericFunctions::_Ceil}, + "Ceil", function::BuiltInFuncType{OperatorId::Ceil, + function::NumericFunctions::_Ceil}, txn); AddBuiltinFunction( @@ -1812,16 +1819,14 @@ void Catalog::InitializeFunctions() { AddBuiltinFunction( "ceil", {type::TypeId::INTEGER}, type::TypeId::DECIMAL, internal_lang, - "Ceil", - function::BuiltInFuncType{OperatorId::Ceil, - function::NumericFunctions::_Ceil}, + "Ceil", function::BuiltInFuncType{OperatorId::Ceil, + function::NumericFunctions::_Ceil}, txn); AddBuiltinFunction( "ceil", {type::TypeId::BIGINT}, type::TypeId::DECIMAL, internal_lang, - "Ceil", - function::BuiltInFuncType{OperatorId::Ceil, - function::NumericFunctions::_Ceil}, + "Ceil", function::BuiltInFuncType{OperatorId::Ceil, + function::NumericFunctions::_Ceil}, txn); AddBuiltinFunction( diff --git a/src/catalog/column_catalog.cpp b/src/catalog/column_catalog.cpp index 4e08f23b356..34d51e5bed9 100644 --- a/src/catalog/column_catalog.cpp +++ b/src/catalog/column_catalog.cpp @@ -39,20 +39,21 @@ ColumnCatalogObject::ColumnCatalogObject(executor::LogicalTile *tile, tile->GetValue(tupleId, ColumnCatalog::ColumnId::COLUMN_TYPE) .ToString())), column_length( - tile->GetValue(tupleId, ColumnCatalog::ColumnId::COLUMN_LENGTH) - .GetAs()), + tile->GetValue(tupleId, ColumnCatalog::ColumnId::COLUMN_LENGTH) + .GetAs()), is_inlined(tile->GetValue(tupleId, ColumnCatalog::ColumnId::IS_INLINED) .GetAs()), is_not_null(tile->GetValue(tupleId, ColumnCatalog::ColumnId::IS_NOT_NULL) .GetAs()), has_default(tile->GetValue(tupleId, ColumnCatalog::ColumnId::HAS_DEFAULT) - .GetAs()) { - // deserialize default value if the column has default constraint - if (has_default) { - auto dv_val = tile->GetValue(tupleId, ColumnCatalog::ColumnId::DEFAULT_VALUE_BIN); - CopySerializeInput input_buffer(dv_val.GetData(), dv_val.GetLength()); - default_value = type::Value::DeserializeFrom(input_buffer, column_type); - } + .GetAs()) { + // deserialize default value if the column has default constraint + if (has_default) { + auto dv_val = + tile->GetValue(tupleId, ColumnCatalog::ColumnId::DEFAULT_VALUE_BIN); + CopySerializeInput input_buffer(dv_val.GetData(), dv_val.GetLength()); + default_value = type::Value::DeserializeFrom(input_buffer, column_type); + } } ColumnCatalog::ColumnCatalog(storage::Database *pg_catalog, @@ -64,9 +65,8 @@ ColumnCatalog::ColumnCatalog(storage::Database *pg_catalog, AddIndex({ColumnId::TABLE_OID, ColumnId::COLUMN_NAME}, COLUMN_CATALOG_PKEY_OID, COLUMN_CATALOG_NAME "_pkey", IndexConstraintType::PRIMARY_KEY); - AddIndex({ColumnId::TABLE_OID, ColumnId::COLUMN_ID}, - COLUMN_CATALOG_SKEY0_OID, COLUMN_CATALOG_NAME "_skey0", - IndexConstraintType::UNIQUE); + AddIndex({ColumnId::TABLE_OID, ColumnId::COLUMN_ID}, COLUMN_CATALOG_SKEY0_OID, + COLUMN_CATALOG_NAME "_skey0", IndexConstraintType::UNIQUE); AddIndex({ColumnId::TABLE_OID}, COLUMN_CATALOG_SKEY1_OID, COLUMN_CATALOG_NAME "_skey1", IndexConstraintType::DEFAULT); @@ -74,9 +74,9 @@ ColumnCatalog::ColumnCatalog(storage::Database *pg_catalog, uint32_t column_id = 0; for (auto column : catalog_table_->GetSchema()->GetColumns()) { InsertColumn(COLUMN_CATALOG_OID, column.GetName(), column_id, - column.GetOffset(), column.GetType(), column.GetLength(), - column.IsInlined(), column.IsNotNull(), column.HasDefault(), - column.GetDefaultValue(), pool, txn); + column.GetOffset(), column.GetType(), column.GetLength(), + column.IsInlined(), column.IsNotNull(), column.HasDefault(), + column.GetDefaultValue(), pool, txn); column_id++; } } @@ -141,31 +141,30 @@ std::unique_ptr ColumnCatalog::InitializeSchema() { std::unique_ptr column_catalog_schema(new catalog::Schema( {table_id_column, column_name_column, column_id_column, column_offset_column, column_type_column, column_length_column, - is_inlined_column, is_not_null_column, has_default_column, - default_value_src_column, default_value_bin_column})); + is_inlined_column, is_not_null_column, has_default_column, + default_value_src_column, default_value_bin_column})); column_catalog_schema->AddConstraint(std::make_shared( - COLUMN_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", - COLUMN_CATALOG_OID, std::vector{ColumnId::TABLE_OID, ColumnId::COLUMN_NAME}, - COLUMN_CATALOG_PKEY_OID)); + COLUMN_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + COLUMN_CATALOG_OID, + std::vector{ColumnId::TABLE_OID, ColumnId::COLUMN_NAME}, + COLUMN_CATALOG_PKEY_OID)); column_catalog_schema->AddConstraint(std::make_shared( - COLUMN_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", - COLUMN_CATALOG_OID, std::vector{ColumnId::TABLE_OID, ColumnId::COLUMN_ID}, - COLUMN_CATALOG_SKEY0_OID)); + COLUMN_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", + COLUMN_CATALOG_OID, + std::vector{ColumnId::TABLE_OID, ColumnId::COLUMN_ID}, + COLUMN_CATALOG_SKEY0_OID)); return column_catalog_schema; } -bool ColumnCatalog::InsertColumn(oid_t table_oid, - const std::string &column_name, - oid_t column_id, oid_t column_offset, - type::TypeId column_type, - size_t column_length, bool is_inlined, - bool is_not_null, bool is_default, - const std::shared_ptr default_value, - type::AbstractPool *pool, - concurrency::TransactionContext *txn) { +bool ColumnCatalog::InsertColumn( + oid_t table_oid, const std::string &column_name, oid_t column_id, + oid_t column_offset, type::TypeId column_type, size_t column_length, + bool is_inlined, bool is_not_null, bool is_default, + const std::shared_ptr default_value, type::AbstractPool *pool, + concurrency::TransactionContext *txn) { // Create the tuple first std::unique_ptr tuple( new storage::Tuple(catalog_table_->GetSchema(), true)); @@ -193,12 +192,13 @@ bool ColumnCatalog::InsertColumn(oid_t table_oid, // set default value if the column has default constraint if (is_default) { - auto val9 = - type::ValueFactory::GetVarcharValue(default_value->ToString(), nullptr); - CopySerializeOutput output_buffer; - default_value->SerializeTo(output_buffer); - auto val10 = type::ValueFactory::GetVarbinaryValue( - (unsigned char*)output_buffer.Data(), output_buffer.Size(), true, pool); + auto val9 = + type::ValueFactory::GetVarcharValue(default_value->ToString(), nullptr); + CopySerializeOutput output_buffer; + default_value->SerializeTo(output_buffer); + auto val10 = type::ValueFactory::GetVarbinaryValue( + (unsigned char *)output_buffer.Data(), output_buffer.Size(), true, + pool); tuple->SetValue(ColumnId::DEFAULT_VALUE_SRC, val9, pool); tuple->SetValue(ColumnId::DEFAULT_VALUE_BIN, val10, pool); @@ -250,13 +250,12 @@ bool ColumnCatalog::DeleteColumns(oid_t table_oid, return DeleteWithIndexScan(index_offset, values, txn); } - -bool ColumnCatalog::UpdateNotNullConstraint(oid_t table_oid, - const std::string &column_name, - bool is_not_null, - concurrency::TransactionContext *txn) { +bool ColumnCatalog::UpdateNotNullConstraint( + oid_t table_oid, const std::string &column_name, bool is_not_null, + concurrency::TransactionContext *txn) { std::vector update_columns({ColumnId::IS_NOT_NULL}); - oid_t index_offset = IndexId::PRIMARY_KEY; // Index of table_oid & column_name + oid_t index_offset = + IndexId::PRIMARY_KEY; // Index of table_oid & column_name // values to execute index scan std::vector scan_values; scan_values.push_back(type::ValueFactory::GetIntegerValue(table_oid).Copy()); @@ -279,15 +278,14 @@ bool ColumnCatalog::UpdateNotNullConstraint(oid_t table_oid, index_offset, txn); } -bool ColumnCatalog::UpdateDefaultConstraint(oid_t table_oid, - const std::string &column_name, - bool has_default, - const type::Value *default_value, - concurrency::TransactionContext *txn) { +bool ColumnCatalog::UpdateDefaultConstraint( + oid_t table_oid, const std::string &column_name, bool has_default, + const type::Value *default_value, concurrency::TransactionContext *txn) { std::vector update_columns({ColumnId::HAS_DEFAULT, - ColumnId::DEFAULT_VALUE_SRC, - ColumnId::DEFAULT_VALUE_BIN}); - oid_t index_offset = IndexId::PRIMARY_KEY; // Index of table_oid & column_name + ColumnId::DEFAULT_VALUE_SRC, + ColumnId::DEFAULT_VALUE_BIN}); + oid_t index_offset = + IndexId::PRIMARY_KEY; // Index of table_oid & column_name // values to execute index scan std::vector scan_values; scan_values.push_back(type::ValueFactory::GetIntegerValue(table_oid).Copy()); @@ -299,18 +297,19 @@ bool ColumnCatalog::UpdateDefaultConstraint(oid_t table_oid, update_values.push_back( type::ValueFactory::GetBooleanValue(has_default).Copy()); if (has_default) { - PELOTON_ASSERT(default_value != nullptr); - update_values.push_back( - type::ValueFactory::GetVarcharValue(default_value->ToString()).Copy()); - CopySerializeOutput output_buffer; - default_value->SerializeTo(output_buffer); - update_values.push_back(type::ValueFactory::GetVarbinaryValue( - (unsigned char*)output_buffer.Data(), output_buffer.Size(), true).Copy()); + PELOTON_ASSERT(default_value != nullptr); + update_values.push_back( + type::ValueFactory::GetVarcharValue(default_value->ToString()).Copy()); + CopySerializeOutput output_buffer; + default_value->SerializeTo(output_buffer); + update_values.push_back(type::ValueFactory::GetVarbinaryValue( + (unsigned char *)output_buffer.Data(), + output_buffer.Size(), true).Copy()); } else { - update_values.push_back( - type::ValueFactory::GetNullValueByType(type::TypeId::VARCHAR)); - update_values.push_back( - type::ValueFactory::GetNullValueByType(type::TypeId::VARBINARY)); + update_values.push_back( + type::ValueFactory::GetNullValueByType(type::TypeId::VARCHAR)); + update_values.push_back( + type::ValueFactory::GetNullValueByType(type::TypeId::VARBINARY)); } // delete column from cache diff --git a/src/catalog/constraint_catalog.cpp b/src/catalog/constraint_catalog.cpp index a45c4ba5cfb..15b47ac2864 100644 --- a/src/catalog/constraint_catalog.cpp +++ b/src/catalog/constraint_catalog.cpp @@ -2,9 +2,9 @@ // // Peloton // -// column_catalog.cpp +// constraint_catalog.cpp // -// Identification: src/catalog/column_catalog.cpp +// Identification: src/catalog/constraint_catalog.cpp // // Copyright (c) 2015-17, Carnegie Mellon University Database Group // @@ -28,78 +28,85 @@ namespace peloton { namespace catalog { ConstraintCatalogObject::ConstraintCatalogObject(executor::LogicalTile *tile, - int tupleId) - : constraint_oid(tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::CONSTRAINT_OID).GetAs()), - constraint_name(tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::CONSTRAINT_NAME).ToString()), - constraint_type(StringToConstraintType(tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::CONSTRAINT_TYPE).ToString())), - table_oid(tile->GetValue(tupleId, ConstraintCatalog::ColumnId::TABLE_OID) + int tupleId) + : constraint_oid( + tile->GetValue(tupleId, ConstraintCatalog::ColumnId::CONSTRAINT_OID) + .GetAs()), + constraint_name( + tile->GetValue(tupleId, ConstraintCatalog::ColumnId::CONSTRAINT_NAME) + .ToString()), + constraint_type(StringToConstraintType( + tile->GetValue(tupleId, ConstraintCatalog::ColumnId::CONSTRAINT_TYPE) + .ToString())), + table_oid(tile->GetValue(tupleId, ConstraintCatalog::ColumnId::TABLE_OID) .GetAs()), - index_oid(tile->GetValue(tupleId, ConstraintCatalog::ColumnId::INDEX_OID) - .GetAs()) { + index_oid(tile->GetValue(tupleId, ConstraintCatalog::ColumnId::INDEX_OID) + .GetAs()) { std::string src_column_ids_str = tile->GetValue(tupleId, ConstraintCatalog::ColumnId::COLUMN_IDS) .ToString(); std::stringstream src_ss(src_column_ids_str.c_str()); std::string src_tok; while (std::getline(src_ss, src_tok, ' ')) { - column_ids.push_back(std::stoi(src_tok)); + column_ids.push_back(std::stoi(src_tok)); } // create values by type of constraint - switch(constraint_type) { - case ConstraintType::PRIMARY: - case ConstraintType::UNIQUE: - // nothing to do more - break; - - case ConstraintType::FOREIGN: { - fk_sink_table_oid = tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::FK_SINK_TABLE_OID).GetAs(); - std::string snk_column_ids_str = tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::FK_SINK_COL_IDS).ToString(); - std::stringstream snk_ss(snk_column_ids_str.c_str()); - std::string snk_tok; - while (std::getline(snk_ss, snk_tok, ' ')) { - fk_sink_col_ids.push_back(std::stoi(snk_tok)); - } - fk_update_action = StringToFKConstrActionType(tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::FK_UPDATE_ACTION).ToString()); - fk_delete_action = StringToFKConstrActionType(tile->GetValue(tupleId, - ConstraintCatalog::ColumnId::FK_DELETE_ACTION).ToString()); - break; - } + switch (constraint_type) { + case ConstraintType::PRIMARY: + case ConstraintType::UNIQUE: + // nothing to do more + break; + + case ConstraintType::FOREIGN: { + fk_sink_table_oid = + tile->GetValue(tupleId, + ConstraintCatalog::ColumnId::FK_SINK_TABLE_OID) + .GetAs(); + std::string snk_column_ids_str = + tile->GetValue(tupleId, ConstraintCatalog::ColumnId::FK_SINK_COL_IDS) + .ToString(); + std::stringstream snk_ss(snk_column_ids_str.c_str()); + std::string snk_tok; + while (std::getline(snk_ss, snk_tok, ' ')) { + fk_sink_col_ids.push_back(std::stoi(snk_tok)); + } + fk_update_action = StringToFKConstrActionType( + tile->GetValue(tupleId, ConstraintCatalog::ColumnId::FK_UPDATE_ACTION) + .ToString()); + fk_delete_action = StringToFKConstrActionType( + tile->GetValue(tupleId, ConstraintCatalog::ColumnId::FK_DELETE_ACTION) + .ToString()); + break; + } - case ConstraintType::CHECK: { - auto dv_val = - tile->GetValue(tupleId, ConstraintCatalog::ColumnId::CHECK_EXP_BIN); - CopySerializeInput input_buffer(dv_val.GetData(), dv_val.GetLength()); - ExpressionType exp_type = (ExpressionType)input_buffer.ReadInt(); - type::TypeId value_type = (type::TypeId)input_buffer.ReadInt(); - auto exp_value = type::Value::DeserializeFrom(input_buffer, value_type); - check_exp = std::make_pair(exp_type, exp_value); - break; - } + case ConstraintType::CHECK: { + auto dv_val = + tile->GetValue(tupleId, ConstraintCatalog::ColumnId::CHECK_EXP_BIN); + CopySerializeInput input_buffer(dv_val.GetData(), dv_val.GetLength()); + ExpressionType exp_type = (ExpressionType)input_buffer.ReadInt(); + type::TypeId value_type = (type::TypeId)input_buffer.ReadInt(); + auto exp_value = type::Value::DeserializeFrom(input_buffer, value_type); + check_exp = std::make_pair(exp_type, exp_value); + break; + } - case ConstraintType::EXCLUSION: - default: - break; + case ConstraintType::EXCLUSION: + default: + break; } } -ConstraintCatalog::ConstraintCatalog(storage::Database *pg_catalog, - UNUSED_ATTRIBUTE type::AbstractPool *pool, - UNUSED_ATTRIBUTE concurrency::TransactionContext *txn) +ConstraintCatalog::ConstraintCatalog( + storage::Database *pg_catalog, UNUSED_ATTRIBUTE type::AbstractPool *pool, + UNUSED_ATTRIBUTE concurrency::TransactionContext *txn) : AbstractCatalog(CONSTRAINT_CATALOG_OID, CONSTRAINT_CATALOG_NAME, InitializeSchema().release(), pg_catalog) { // Add indexes for pg_constraint - AddIndex({ColumnId::CONSTRAINT_OID}, - CONSTRAINT_CATALOG_PKEY_OID, CONSTRAINT_CATALOG_NAME "_pkey", - IndexConstraintType::PRIMARY_KEY); + AddIndex({ColumnId::CONSTRAINT_OID}, CONSTRAINT_CATALOG_PKEY_OID, + CONSTRAINT_CATALOG_NAME "_pkey", IndexConstraintType::PRIMARY_KEY); AddIndex({ColumnId::TABLE_OID}, CONSTRAINT_CATALOG_SKEY0_OID, - CONSTRAINT_CATALOG_NAME "_skey0", IndexConstraintType::DEFAULT); + CONSTRAINT_CATALOG_NAME "_skey0", IndexConstraintType::DEFAULT); } ConstraintCatalog::~ConstraintCatalog() {} @@ -158,16 +165,18 @@ std::unique_ptr ConstraintCatalog::InitializeSchema() { type::TypeId::VARBINARY, type::Type::GetTypeSize(type::TypeId::VARBINARY), "check_exp_bin", false); - std::unique_ptr constraint_catalog_schema(new catalog::Schema( - {constraint_oid_column, constraint_name_column, constraint_type_column, - table_oid_column, column_ids_column, index_oid_column, - fk_sink_table_oid_column, fk_sink_col_ids_column, fk_update_action_column, - fk_delete_action_column, check_exp_src_column, check_exp_bin_column})); + std::unique_ptr constraint_catalog_schema( + new catalog::Schema({constraint_oid_column, constraint_name_column, + constraint_type_column, table_oid_column, + column_ids_column, index_oid_column, + fk_sink_table_oid_column, fk_sink_col_ids_column, + fk_update_action_column, fk_delete_action_column, + check_exp_src_column, check_exp_bin_column})); constraint_catalog_schema->AddConstraint(std::make_shared( - CONSTRAINT_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", - CONSTRAINT_CATALOG_OID, std::vector{ColumnId::CONSTRAINT_OID}, - CONSTRAINT_CATALOG_PKEY_OID)); + CONSTRAINT_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + CONSTRAINT_CATALOG_OID, std::vector{ColumnId::CONSTRAINT_OID}, + CONSTRAINT_CATALOG_PKEY_OID)); return constraint_catalog_schema; } @@ -181,22 +190,25 @@ std::unique_ptr ConstraintCatalog::InitializeSchema() { * @param txn TransactionContext for adding the constraint. * @return true on success. */ -bool ConstraintCatalog::InsertConstraint(const std::shared_ptr constraint, - type::AbstractPool *pool, concurrency::TransactionContext *txn) { - // Create the tuple first +bool ConstraintCatalog::InsertConstraint( + const std::shared_ptr constraint, type::AbstractPool *pool, + concurrency::TransactionContext *txn) { + // Create the tuple first std::unique_ptr tuple( new storage::Tuple(catalog_table_->GetSchema(), true)); // Common information of constraint - auto val0 = type::ValueFactory::GetIntegerValue(constraint->GetConstraintOid()); - auto val1 = type::ValueFactory::GetVarcharValue(constraint->GetName(), nullptr); - auto val2 = type::ValueFactory::GetVarcharValue( - ConstraintTypeToString(constraint->GetType()), nullptr); + auto val0 = + type::ValueFactory::GetIntegerValue(constraint->GetConstraintOid()); + auto val1 = + type::ValueFactory::GetVarcharValue(constraint->GetName(), nullptr); + auto val2 = type::ValueFactory::GetVarcharValue( + ConstraintTypeToString(constraint->GetType()), nullptr); auto val3 = type::ValueFactory::GetIntegerValue(constraint->GetTableOid()); std::stringstream ss; for (auto column_oid : constraint->GetColumnIds()) - ss << std::to_string(column_oid) << " "; - auto val4 = type::ValueFactory::GetVarcharValue(ss.str(), nullptr); + ss << std::to_string(column_oid) << " "; + auto val4 = type::ValueFactory::GetVarcharValue(ss.str(), nullptr); auto val5 = type::ValueFactory::GetIntegerValue(constraint->GetIndexOid()); tuple->SetValue(ColumnId::CONSTRAINT_OID, val0, pool); @@ -207,71 +219,73 @@ bool ConstraintCatalog::InsertConstraint(const std::shared_ptr const tuple->SetValue(ColumnId::INDEX_OID, val5, pool); // create values by type of constraint - switch(constraint->GetType()) { - case ConstraintType::PRIMARY: - case ConstraintType::UNIQUE: - // nothing to do more - // need to set a valid index oid - PELOTON_ASSERT(constraint->GetIndexOid() != INVALID_OID); - break; - - case ConstraintType::FOREIGN: { - // need to set a valid index oid - PELOTON_ASSERT(constraint->GetIndexOid() != INVALID_OID); - - auto val6 = type::ValueFactory::GetIntegerValue(constraint->GetFKSinkTableOid()); - std::stringstream snk_ss; - for (auto column_oid : constraint->GetFKSinkColumnIds()) - snk_ss << std::to_string(column_oid) << " "; - auto val7 = type::ValueFactory::GetVarcharValue(snk_ss.str(), nullptr); - auto val8 = type::ValueFactory::GetVarcharValue( - FKConstrActionTypeToString(constraint->GetFKUpdateAction()), nullptr); - auto val9 = type::ValueFactory::GetVarcharValue( - FKConstrActionTypeToString(constraint->GetFKDeleteAction()), nullptr); - - tuple->SetValue(ColumnId::FK_SINK_TABLE_OID, val6, pool); - tuple->SetValue(ColumnId::FK_SINK_COL_IDS, val7, pool); - tuple->SetValue(ColumnId::FK_UPDATE_ACTION, val8, pool); - tuple->SetValue(ColumnId::FK_DELETE_ACTION, val9, pool); - break; - } + switch (constraint->GetType()) { + case ConstraintType::PRIMARY: + case ConstraintType::UNIQUE: + // nothing to do more + // need to set a valid index oid + PELOTON_ASSERT(constraint->GetIndexOid() != INVALID_OID); + break; + + case ConstraintType::FOREIGN: { + // need to set a valid index oid + PELOTON_ASSERT(constraint->GetIndexOid() != INVALID_OID); + + auto val6 = + type::ValueFactory::GetIntegerValue(constraint->GetFKSinkTableOid()); + std::stringstream snk_ss; + for (auto column_oid : constraint->GetFKSinkColumnIds()) + snk_ss << std::to_string(column_oid) << " "; + auto val7 = type::ValueFactory::GetVarcharValue(snk_ss.str(), nullptr); + auto val8 = type::ValueFactory::GetVarcharValue( + FKConstrActionTypeToString(constraint->GetFKUpdateAction()), nullptr); + auto val9 = type::ValueFactory::GetVarcharValue( + FKConstrActionTypeToString(constraint->GetFKDeleteAction()), nullptr); + + tuple->SetValue(ColumnId::FK_SINK_TABLE_OID, val6, pool); + tuple->SetValue(ColumnId::FK_SINK_COL_IDS, val7, pool); + tuple->SetValue(ColumnId::FK_UPDATE_ACTION, val8, pool); + tuple->SetValue(ColumnId::FK_DELETE_ACTION, val9, pool); + break; + } - case ConstraintType::CHECK: { - // set value of check expression - PELOTON_ASSERT(constraint->GetColumnIds().size() == 1); - auto exp = constraint->GetCheckExpression(); - auto column = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, constraint->GetTableOid())->GetSchema() - ->GetColumn(constraint->GetColumnIds().at(0)); - - std::stringstream exp_ss; - exp_ss << column.GetName() - << " " << ExpressionTypeToString(exp.first) - << " " << exp.second.ToString(); - auto val6 = type::ValueFactory::GetVarcharValue(exp_ss.str(), nullptr); - - CopySerializeOutput output_buffer; - output_buffer.WriteInt((int)exp.first); - output_buffer.WriteInt((int)column.GetType()); - exp.second.SerializeTo(output_buffer); - auto val7 = type::ValueFactory::GetVarbinaryValue( - (unsigned char*)output_buffer.Data(), output_buffer.Size(), true, pool); - - tuple->SetValue(ColumnId::CHECK_EXP_SRC, val6, pool); - tuple->SetValue(ColumnId::CHECK_EXP_BIN, val7, pool); - break; - } + case ConstraintType::CHECK: { + // set value of check expression + PELOTON_ASSERT(constraint->GetColumnIds().size() == 1); + auto exp = constraint->GetCheckExpression(); + auto column = + storage::StorageManager::GetInstance() + ->GetTableWithOid(database_oid, constraint->GetTableOid()) + ->GetSchema() + ->GetColumn(constraint->GetColumnIds().at(0)); + + std::stringstream exp_ss; + exp_ss << column.GetName() << " " << ExpressionTypeToString(exp.first) + << " " << exp.second.ToString(); + auto val6 = type::ValueFactory::GetVarcharValue(exp_ss.str(), nullptr); + + CopySerializeOutput output_buffer; + output_buffer.WriteInt((int)exp.first); + output_buffer.WriteInt((int)column.GetType()); + exp.second.SerializeTo(output_buffer); + auto val7 = type::ValueFactory::GetVarbinaryValue( + (unsigned char *)output_buffer.Data(), output_buffer.Size(), true, + pool); + + tuple->SetValue(ColumnId::CHECK_EXP_SRC, val6, pool); + tuple->SetValue(ColumnId::CHECK_EXP_BIN, val7, pool); + break; + } - case ConstraintType::EXCLUSION: - default: - // unexpected constraint type - throw CatalogException("Unexpected constraint type '" + - ConstraintTypeToString(constraint->GetType()) + - "' appears in insertion into pg_constraint "); - return false; + case ConstraintType::EXCLUSION: + default: + // unexpected constraint type + throw CatalogException("Unexpected constraint type '" + + ConstraintTypeToString(constraint->GetType()) + + "' appears in insertion into pg_constraint "); + return false; } - // Insert the tuple return InsertTuple(std::move(tuple), txn); } @@ -282,8 +296,8 @@ bool ConstraintCatalog::InsertConstraint(const std::shared_ptr const * @param txn TransactionContext * @return a vector of table oid */ -bool ConstraintCatalog::DeleteConstraints(oid_t table_oid, - concurrency::TransactionContext *txn) { +bool ConstraintCatalog::DeleteConstraints( + oid_t table_oid, concurrency::TransactionContext *txn) { oid_t index_offset = IndexId::SKEY_TABLE_OID; // Index of table_oid std::vector values; values.push_back(type::ValueFactory::GetIntegerValue(table_oid).Copy()); @@ -304,9 +318,8 @@ bool ConstraintCatalog::DeleteConstraints(oid_t table_oid, * @param txn TransactionContext for deleting the constraint. * @return true on success. */ -bool ConstraintCatalog::DeleteConstraint(oid_t table_oid, - oid_t constraint_oid, - concurrency::TransactionContext *txn) { +bool ConstraintCatalog::DeleteConstraint(oid_t table_oid, oid_t constraint_oid, + concurrency::TransactionContext *txn) { oid_t index_offset = IndexId::PRIMARY_KEY; // Index of constraint_oid std::vector values; values.push_back(type::ValueFactory::GetIntegerValue(constraint_oid).Copy()); @@ -330,7 +343,7 @@ bool ConstraintCatalog::DeleteConstraint(oid_t table_oid, */ const std::unordered_map> ConstraintCatalog::GetConstraintObjects(oid_t table_oid, - concurrency::TransactionContext *txn) { + concurrency::TransactionContext *txn) { // try get from cache auto pg_table = Catalog::GetInstance() ->GetSystemCatalogs(database_oid) @@ -371,7 +384,7 @@ ConstraintCatalog::GetConstraintObjects(oid_t table_oid, */ const std::shared_ptr ConstraintCatalog::GetConstraintObject(oid_t table_oid, oid_t constraint_oid, - concurrency::TransactionContext *txn) { + concurrency::TransactionContext *txn) { // try get from cache auto pg_table = Catalog::GetInstance() ->GetSystemCatalogs(database_oid) @@ -380,7 +393,7 @@ ConstraintCatalog::GetConstraintObject(oid_t table_oid, oid_t constraint_oid, PELOTON_ASSERT(table_object && table_object->GetTableOid() == table_oid); auto constraint_object = - table_object->GetConstraintObject(constraint_oid, true); + table_object->GetConstraintObject(constraint_oid, true); if (constraint_object != nullptr) return constraint_object; // cache miss, get from pg_attribute diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index 259ceb75e68..15d76da10f8 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -130,107 +130,107 @@ bool CreateExecutor::CreateTable(const planner::CreatePlan &node) { // Add the primary key constraint if (node.HasPrimaryKey()) { auto pk = node.GetPrimaryKey(); - std::vector col_ids; + std::vector col_ids; for (auto col_name : pk.primary_key_cols) { oid_t col_id = source_table->GetSchema()->GetColumnID(col_name); if (col_id == INVALID_OID) { std::string error = StringUtil::Format( "Invalid key column name '%s.%s' for primary key '%s'", - table_name.c_str(), col_name.c_str(), - pk.constraint_name.c_str()); + table_name.c_str(), col_name.c_str(), pk.constraint_name.c_str()); throw ExecutorException(error); } - col_ids.push_back(col_id); + col_ids.push_back(col_id); } PELOTON_ASSERT(col_ids.size() == pk.primary_key_cols.size()); // Create the catalog object and shove it into the table catalog->AddPrimaryKeyConstraint(source_table->GetDatabaseOid(), - source_table->GetOid(), col_ids, pk.constraint_name, current_txn); + source_table->GetOid(), col_ids, + pk.constraint_name, current_txn); } // Add the unique constraint for (auto unique : node.GetUniques()) { - std::vector col_ids; + std::vector col_ids; for (auto col_name : unique.unique_cols) { oid_t col_id = source_table->GetSchema()->GetColumnID(col_name); if (col_id == INVALID_OID) { std::string error = StringUtil::Format( "Invalid key column name '%s.%s' for unique '%s'", table_name.c_str(), col_name.c_str(), - unique.constraint_name.c_str()); + unique.constraint_name.c_str()); throw ExecutorException(error); } - col_ids.push_back(col_id); + col_ids.push_back(col_id); } PELOTON_ASSERT(col_ids.size() == unique.unique_cols.size()); // Create the catalog object and shove it into the table catalog->AddUniqueConstraint(source_table->GetDatabaseOid(), - source_table->GetOid(), col_ids, unique.constraint_name, current_txn); + source_table->GetOid(), col_ids, + unique.constraint_name, current_txn); } // Add the foreign key constraint - for (auto fk : node.GetForeignKeys()) { - auto sink_table = catalog->GetTableWithName( - database_name, schema_name, fk.sink_table_name, current_txn); - // Source Column Offsets - std::vector source_col_ids; - for (auto col_name : fk.foreign_key_sources) { - oid_t col_id = source_table->GetSchema()->GetColumnID(col_name); - if (col_id == INVALID_OID) { - std::string error = StringUtil::Format( - "Invalid source column name '%s.%s' for foreign key '%s'", - table_name.c_str(), col_name.c_str(), - fk.constraint_name.c_str()); - throw ExecutorException(error); - } - source_col_ids.push_back(col_id); - } // FOR - PELOTON_ASSERT(source_col_ids.size() == fk.foreign_key_sources.size()); - - // Sink Column Offsets - std::vector sink_col_ids; - for (auto col_name : fk.foreign_key_sinks) { - oid_t col_id = sink_table->GetSchema()->GetColumnID(col_name); - if (col_id == INVALID_OID) { - std::string error = StringUtil::Format( - "Invalid sink column name '%s.%s' for foreign key '%s'", - sink_table->GetName().c_str(), col_name.c_str(), - fk.constraint_name.c_str()); - throw ExecutorException(error); - } - sink_col_ids.push_back(col_id); - } // FOR - PELOTON_ASSERT(sink_col_ids.size() == fk.foreign_key_sinks.size()); - - // Create the catalog object and shove it into the table - catalog->AddForeignKeyConstraint(source_table->GetDatabaseOid(), - source_table->GetOid(), source_col_ids, sink_table->GetOid(), - sink_col_ids, fk.upd_action, fk.del_action, fk.constraint_name, - current_txn); - } + for (auto fk : node.GetForeignKeys()) { + auto sink_table = catalog->GetTableWithName( + database_name, schema_name, fk.sink_table_name, current_txn); + // Source Column Offsets + std::vector source_col_ids; + for (auto col_name : fk.foreign_key_sources) { + oid_t col_id = source_table->GetSchema()->GetColumnID(col_name); + if (col_id == INVALID_OID) { + std::string error = StringUtil::Format( + "Invalid source column name '%s.%s' for foreign key '%s'", + table_name.c_str(), col_name.c_str(), fk.constraint_name.c_str()); + throw ExecutorException(error); + } + source_col_ids.push_back(col_id); + } // FOR + PELOTON_ASSERT(source_col_ids.size() == fk.foreign_key_sources.size()); + + // Sink Column Offsets + std::vector sink_col_ids; + for (auto col_name : fk.foreign_key_sinks) { + oid_t col_id = sink_table->GetSchema()->GetColumnID(col_name); + if (col_id == INVALID_OID) { + std::string error = StringUtil::Format( + "Invalid sink column name '%s.%s' for foreign key '%s'", + sink_table->GetName().c_str(), col_name.c_str(), + fk.constraint_name.c_str()); + throw ExecutorException(error); + } + sink_col_ids.push_back(col_id); + } // FOR + PELOTON_ASSERT(sink_col_ids.size() == fk.foreign_key_sinks.size()); + + // Create the catalog object and shove it into the table + catalog->AddForeignKeyConstraint( + source_table->GetDatabaseOid(), source_table->GetOid(), + source_col_ids, sink_table->GetOid(), sink_col_ids, fk.upd_action, + fk.del_action, fk.constraint_name, current_txn); + } // Add the check constraint for (auto check : node.GetChecks()) { - std::vector col_ids; + std::vector col_ids; for (auto col_name : check.check_cols) { oid_t col_id = source_table->GetSchema()->GetColumnID(col_name); if (col_id == INVALID_OID) { std::string error = StringUtil::Format( "Invalid key column name '%s.%s' for unique '%s'", table_name.c_str(), col_name.c_str(), - check.constraint_name.c_str()); + check.constraint_name.c_str()); throw ExecutorException(error); } - col_ids.push_back(col_id); + col_ids.push_back(col_id); } PELOTON_ASSERT(col_ids.size() == check.check_cols.size()); // Create the catalog object and shove it into the table catalog->AddCheckConstraint(source_table->GetDatabaseOid(), - source_table->GetOid(), col_ids, check.exp, check.constraint_name, - current_txn); + source_table->GetOid(), col_ids, check.exp, + check.constraint_name, current_txn); } } else if (current_txn->GetResult() == ResultType::FAILURE) { @@ -284,8 +284,7 @@ bool CreateExecutor::CreateTrigger(const planner::CreatePlan &node) { // catalog table auto time_stamp = type::ValueFactory::GetTimestampValue( std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - .count()); + std::chrono::system_clock::now().time_since_epoch()).count()); CopySerializeOutput output; newTrigger.SerializeWhen(output, table_object->GetDatabaseOid(), diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h index b815e0de008..24fe7e1f2da 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -119,9 +119,8 @@ class Catalog { ResultType CreateIndex(oid_t database_oid, oid_t table_oid, const std::vector &key_attrs, - const std::string &schema_name, - oid_t index_oid, const std::string &index_name, - IndexType index_type, + const std::string &schema_name, oid_t index_oid, + const std::string &index_name, IndexType index_type, IndexConstraintType index_constraint, bool unique_keys, concurrency::TransactionContext *txn, bool is_catalog = false); @@ -153,7 +152,6 @@ class Catalog { oid_t database_oid, oid_t table_oid, const column_map_type &column_map, concurrency::TransactionContext *txn); - //===--------------------------------------------------------------------===// // SET FUNCTIONS FOR COLUMN CONSTRAINT //===--------------------------------------------------------------------===// @@ -161,14 +159,13 @@ class Catalog { // Set not null constraint for a column ResultType SetNotNullConstraint(oid_t database_oid, oid_t table_oid, oid_t column_id, - concurrency::TransactionContext *txn); + concurrency::TransactionContext *txn); // Set default constraint for a column ResultType SetDefaultConstraint(oid_t database_oid, oid_t table_oid, oid_t column_id, - const type::Value &default_value, - concurrency::TransactionContext *txn); - + const type::Value &default_value, + concurrency::TransactionContext *txn); //===--------------------------------------------------------------------===// // ADD FUNCTIONS FOR TABLE CONSTRAINT @@ -177,31 +174,30 @@ class Catalog { // Add a new primary constraint for a table ResultType AddPrimaryKeyConstraint(oid_t database_oid, oid_t table_oid, const std::vector &column_ids, - const std::string &constraint_name, - concurrency::TransactionContext *txn); + const std::string &constraint_name, + concurrency::TransactionContext *txn); // Add a new unique constraint for a table ResultType AddUniqueConstraint(oid_t database_oid, oid_t table_oid, const std::vector &column_ids, - const std::string &constraint_name, - concurrency::TransactionContext *txn); + const std::string &constraint_name, + concurrency::TransactionContext *txn); // Add a new foreign key constraint for a table ResultType AddForeignKeyConstraint(oid_t database_oid, oid_t src_table_oid, - const std::vector &src_col_ids, - oid_t sink_table_oid, - const std::vector &sink_col_ids, - FKConstrActionType upd_action, - FKConstrActionType del_action, - const std::string &constraint_name, - concurrency::TransactionContext *txn); + const std::vector &src_col_ids, + oid_t sink_table_oid, + const std::vector &sink_col_ids, + FKConstrActionType upd_action, + FKConstrActionType del_action, + const std::string &constraint_name, + concurrency::TransactionContext *txn); // Add a new check constraint for a table - ResultType AddCheckConstraint(oid_t database_oid, oid_t table_oid, - const std::vector &column_ids, - const std::pair &exp, - const std::string &constraint_name, - concurrency::TransactionContext *txn); + ResultType AddCheckConstraint( + oid_t database_oid, oid_t table_oid, const std::vector &column_ids, + const std::pair &exp, + const std::string &constraint_name, concurrency::TransactionContext *txn); //===--------------------------------------------------------------------===// // DROP FUNCTIONS @@ -254,9 +250,8 @@ class Catalog { // Drop constraint for a table ResultType DropConstraint(oid_t database_oid, oid_t table_oid, - oid_t constraint_oid, - concurrency::TransactionContext *txn); - + oid_t constraint_oid, + concurrency::TransactionContext *txn); //===--------------------------------------------------------------------===// // GET WITH NAME - CHECK FROM CATALOG TABLES, USING TRANSACTION diff --git a/src/include/catalog/column_catalog.h b/src/include/catalog/column_catalog.h index 4a5b584fad2..26e417d4a83 100644 --- a/src/include/catalog/column_catalog.h +++ b/src/include/catalog/column_catalog.h @@ -89,9 +89,9 @@ class ColumnCatalog : public AbstractCatalog { bool InsertColumn(oid_t table_oid, const std::string &column_name, oid_t column_id, oid_t column_offset, type::TypeId column_type, size_t column_length, - bool is_inlined, bool is_not_null, bool is_default, - const std::shared_ptr default_value, - type::AbstractPool *pool, + bool is_inlined, bool is_not_null, bool is_default, + const std::shared_ptr default_value, + type::AbstractPool *pool, concurrency::TransactionContext *txn); bool DeleteColumn(oid_t table_oid, const std::string &column_name, concurrency::TransactionContext *txn); @@ -102,9 +102,9 @@ class ColumnCatalog : public AbstractCatalog { concurrency::TransactionContext *txn); bool UpdateDefaultConstraint(oid_t table_oid, const std::string &column_name, - bool has_default, - const type::Value *default_value, - concurrency::TransactionContext *txn); + bool has_default, + const type::Value *default_value, + concurrency::TransactionContext *txn); private: //===--------------------------------------------------------------------===// @@ -121,12 +121,12 @@ class ColumnCatalog : public AbstractCatalog { COLUMN_ID = 2, COLUMN_OFFSET = 3, COLUMN_TYPE = 4, - COLUMN_LENGTH = 5, + COLUMN_LENGTH = 5, IS_INLINED = 6, IS_NOT_NULL = 7, HAS_DEFAULT = 8, - DEFAULT_VALUE_SRC = 9, - DEFAULT_VALUE_BIN = 10, + DEFAULT_VALUE_SRC = 9, + DEFAULT_VALUE_BIN = 10, // Add new columns here in creation order }; std::vector all_column_ids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; diff --git a/src/include/catalog/constraint_catalog.h b/src/include/catalog/constraint_catalog.h index 9f927ee0989..7cb5e84d122 100644 --- a/src/include/catalog/constraint_catalog.h +++ b/src/include/catalog/constraint_catalog.h @@ -47,7 +47,7 @@ namespace catalog { class Constraint; class ConstraintCatalogObject { - friend class ConstraintCatalog; + friend class ConstraintCatalog; public: ConstraintCatalogObject(executor::LogicalTile *tile, int tupleId = 0); @@ -59,10 +59,14 @@ class ConstraintCatalogObject { inline const std::vector &GetColumnIds() { return column_ids; } inline oid_t GetIndexOid() { return index_oid; } inline oid_t GetFKSinkTableOid() { return fk_sink_table_oid; } - inline const std::vector &GetFKSinkColumnIds() { return fk_sink_col_ids; } + inline const std::vector &GetFKSinkColumnIds() { + return fk_sink_col_ids; + } inline FKConstrActionType GetFKUpdateAction() { return fk_update_action; } inline FKConstrActionType GetFKDeleteAction() { return fk_delete_action; } - inline const std::pair &GetCheckExp() { return check_exp; } + inline const std::pair &GetCheckExp() { + return check_exp; + } private: // member variables @@ -72,11 +76,11 @@ class ConstraintCatalogObject { oid_t table_oid; std::vector column_ids; oid_t index_oid; - oid_t fk_sink_table_oid; + oid_t fk_sink_table_oid; std::vector fk_sink_col_ids; - FKConstrActionType fk_update_action; - FKConstrActionType fk_delete_action; - std::pair check_exp; + FKConstrActionType fk_update_action; + FKConstrActionType fk_delete_action; + std::pair check_exp; }; class ConstraintCatalog : public AbstractCatalog { @@ -86,7 +90,7 @@ class ConstraintCatalog : public AbstractCatalog { public: ConstraintCatalog(storage::Database *pg_catalog, type::AbstractPool *pool, - concurrency::TransactionContext *txn); + concurrency::TransactionContext *txn); ~ConstraintCatalog(); @@ -98,13 +102,13 @@ class ConstraintCatalog : public AbstractCatalog { // write Related API //===--------------------------------------------------------------------===// bool InsertConstraint(const std::shared_ptr constraint, - type::AbstractPool *pool, + type::AbstractPool *pool, concurrency::TransactionContext *txn); bool DeleteConstraints(oid_t table_oid, concurrency::TransactionContext *txn); bool DeleteConstraint(oid_t table_oid, oid_t constraint_oid, - concurrency::TransactionContext *txn); + concurrency::TransactionContext *txn); private: //===--------------------------------------------------------------------===// @@ -113,18 +117,18 @@ class ConstraintCatalog : public AbstractCatalog { const std::unordered_map> GetConstraintObjects(oid_t table_oid, concurrency::TransactionContext *txn); - const std::shared_ptr - GetConstraintObject(oid_t table_oid, oid_t constraint_oid, - concurrency::TransactionContext *txn); + const std::shared_ptr GetConstraintObject( + oid_t table_oid, oid_t constraint_oid, + concurrency::TransactionContext *txn); std::unique_ptr InitializeSchema(); enum ColumnId { - CONSTRAINT_OID = 0, - CONSTRAINT_NAME = 1, - CONSTRAINT_TYPE = 2, + CONSTRAINT_OID = 0, + CONSTRAINT_NAME = 1, + CONSTRAINT_TYPE = 2, TABLE_OID = 3, - COLUMN_IDS = 4, + COLUMN_IDS = 4, INDEX_OID = 5, FK_SINK_TABLE_OID = 6, FK_SINK_COL_IDS = 7, diff --git a/src/include/storage/data_table.h b/src/include/storage/data_table.h index c18aedd4cc4..48708b9edb5 100644 --- a/src/include/storage/data_table.h +++ b/src/include/storage/data_table.h @@ -134,8 +134,8 @@ class DataTable : public AbstractTable { // Insert tuple with ItemPointer provided explicitly bool InsertTuple(const AbstractTuple *tuple, ItemPointer location, - concurrency::TransactionContext *transaction, ItemPointer **index_entry_ptr, - bool check_fk = true); + concurrency::TransactionContext *transaction, + ItemPointer **index_entry_ptr, bool check_fk = true); //===--------------------------------------------------------------------===// // TILE GROUP @@ -167,13 +167,12 @@ class DataTable : public AbstractTable { int GetTriggerNumber(); - trigger::Trigger* GetTriggerByIndex(int n); + trigger::Trigger *GetTriggerByIndex(int n); - trigger::TriggerList* GetTriggerList(); + trigger::TriggerList *GetTriggerList(); void UpdateTriggerListFromCatalog(concurrency::TransactionContext *txn); - //===--------------------------------------------------------------------===// // INDEX //===--------------------------------------------------------------------===// @@ -203,11 +202,10 @@ class DataTable : public AbstractTable { // FOREIGN KEYS //===--------------------------------------------------------------------===// - bool CheckForeignKeySrcAndCascade(storage::Tuple *prev_tuple, - storage::Tuple *new_tuple, - concurrency::TransactionContext *transaction, - executor::ExecutorContext *context, - bool is_update); + bool CheckForeignKeySrcAndCascade( + storage::Tuple *prev_tuple, storage::Tuple *new_tuple, + concurrency::TransactionContext *transaction, + executor::ExecutorContext *context, bool is_update); //===--------------------------------------------------------------------===// // TRANSFORMERS @@ -254,7 +252,7 @@ class DataTable : public AbstractTable { } const std::shared_ptr GetDefaultLayout() const { - return default_layout_; + return default_layout_; } //===--------------------------------------------------------------------===// @@ -316,8 +314,8 @@ class DataTable : public AbstractTable { //===--------------------------------------------------------------------===// bool CheckNotNulls(const AbstractTuple *tuple, oid_t column_idx) const; -// bool MultiCheckNotNulls(const storage::Tuple *tuple, -// std::vector cols) const; + // bool MultiCheckNotNulls(const storage::Tuple *tuple, + // std::vector cols) const; // bool CheckExp(const storage::Tuple *tuple, oid_t column_idx, // std::pair exp) const; diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index 74da4a0242c..4fdca125df2 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -95,18 +95,19 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { columns.push_back(column); // Collect Multi-column constraints information - // TODO: Following constraints info in ColumnDefinition should be independent + // TODO: Following constraints info in ColumnDefinition should be + // independent // for multi-column constraints like foreign key. // Primary key if (col->primary) { - pri_cols.push_back(col->name); + pri_cols.push_back(col->name); } // Unique constraint // Currently only supports for single column if (col->unique) { - ProcessUniqueConstraint(col.get()); + ProcessUniqueConstraint(col.get()); } // Check expression constraint @@ -122,9 +123,9 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { // into an artificial ColumnDefinition. // primary key constraint if (pri_cols.size() > 0) { - primary_key.primary_key_cols = pri_cols; - primary_key.constraint_name = "con_primary"; - has_primary_key = true; + primary_key.primary_key_cols = pri_cols; + primary_key.constraint_name = "con_primary"; + has_primary_key = true; LOG_TRACE("Added a primary key constraint on column \"%s\"", table_name.c_str()); } @@ -227,39 +228,36 @@ void CreatePlan::ProcessForeignKeyConstraint( foreign_keys.push_back(fkey_info); } -void CreatePlan::ProcessUniqueConstraint( - const parser::ColumnDefinition *col) { +void CreatePlan::ProcessUniqueConstraint(const parser::ColumnDefinition *col) { UniqueInfo unique_info; - unique_info.unique_cols = {col->name}; - unique_info.constraint_name = "con_unique"; + unique_info.unique_cols = {col->name}; + unique_info.constraint_name = "con_unique"; - LOG_TRACE("Added a unique constraint on column \"%s.%s\"", - table_name.c_str, col->name.c_str()); - con_uniques.push_back(unique_info); + LOG_TRACE("Added a unique constraint on column \"%s.%s\"", table_name.c_str, + col->name.c_str()); + con_uniques.push_back(unique_info); } -void CreatePlan::ProcessCheckConstraint( - const parser::ColumnDefinition *col) { +void CreatePlan::ProcessCheckConstraint(const parser::ColumnDefinition *col) { CheckInfo check_info; // TODO: more expression types need to be supported if (col->check_expression->GetValueType() == type::TypeId::BOOLEAN) { - check_info.check_cols.push_back(col->name); + check_info.check_cols.push_back(col->name); const expression::ConstantValueExpression *const_expr_elem = dynamic_cast( col->check_expression->GetChild(1)); type::Value tmp_value = const_expr_elem->GetValue(); - check_info.exp = std::make_pair( - std::move(col->check_expression->GetExpressionType()), - std::move(tmp_value)); + check_info.exp = + std::make_pair(std::move(col->check_expression->GetExpressionType()), + std::move(tmp_value)); - check_info.constraint_name = "con_check"; + check_info.constraint_name = "con_check"; - LOG_TRACE("Added a check constraint on column \"%s\"", - table_name.c_str()); + LOG_TRACE("Added a check constraint on column \"%s\"", table_name.c_str()); con_checks.push_back(check_info); } } diff --git a/src/storage/data_table.cpp b/src/storage/data_table.cpp index cb423657192..6ef53659627 100644 --- a/src/storage/data_table.cpp +++ b/src/storage/data_table.cpp @@ -136,58 +136,58 @@ bool DataTable::CheckNotNulls(const AbstractTuple *tuple, bool DataTable::CheckConstraints(const AbstractTuple *tuple) const { // make sure that the given tuple does not violate constraints. - // NOT NULL constraint - for (oid_t column_id : schema->GetNotNullColumns()) { - if (schema->AllowNull(column_id) == false && - CheckNotNulls(tuple, column_id) == false) { - std::string error = StringUtil::Format( - "NOT NULL constraint violated on column '%s' : %s", - schema->GetColumn(column_id).GetName().c_str(), - tuple->GetInfo().c_str()); - throw ConstraintException(error); - } + // NOT NULL constraint + for (oid_t column_id : schema->GetNotNullColumns()) { + if (schema->AllowNull(column_id) == false && + CheckNotNulls(tuple, column_id) == false) { + std::string error = + StringUtil::Format("NOT NULL constraint violated on column '%s' : %s", + schema->GetColumn(column_id).GetName().c_str(), + tuple->GetInfo().c_str()); + throw ConstraintException(error); + } } - // DEFAULT constraint should not be handled here - // Handled in higher hierarchy - - // multi-column constraints - for (auto cons_pair : schema->GetConstraints()) { - auto cons = cons_pair.second; - ConstraintType type = cons->GetType(); - switch (type) { - case ConstraintType::CHECK: { - // std::pair exp = - // cons.GetCheckExpression(); - // if (CheckExp(tuple, column_itr, exp) == false) { - // LOG_TRACE("CHECK EXPRESSION constraint violated"); - // throw ConstraintException( - // "CHECK EXPRESSION constraint violated : " + - // std::string(tuple->GetInfo())); - // } - break; - } - case ConstraintType::UNIQUE: { - break; - } - case ConstraintType::PRIMARY: { - break; - } - case ConstraintType::FOREIGN: { - break; - } - case ConstraintType::EXCLUSION: { - break; - } - default: { - std::string error = - StringUtil::Format("ConstraintType '%s' is not supported", - ConstraintTypeToString(type).c_str()); - LOG_TRACE("%s", error.c_str()); - throw ConstraintException(error); - } - } // SWITCH - } // FOR (constraints) + // DEFAULT constraint should not be handled here + // Handled in higher hierarchy + + // multi-column constraints + for (auto cons_pair : schema->GetConstraints()) { + auto cons = cons_pair.second; + ConstraintType type = cons->GetType(); + switch (type) { + case ConstraintType::CHECK: { + // std::pair exp = + // cons.GetCheckExpression(); + // if (CheckExp(tuple, column_itr, exp) == false) { + // LOG_TRACE("CHECK EXPRESSION constraint violated"); + // throw ConstraintException( + // "CHECK EXPRESSION constraint violated : " + + // std::string(tuple->GetInfo())); + // } + break; + } + case ConstraintType::UNIQUE: { + break; + } + case ConstraintType::PRIMARY: { + break; + } + case ConstraintType::FOREIGN: { + break; + } + case ConstraintType::EXCLUSION: { + break; + } + default: { + std::string error = + StringUtil::Format("ConstraintType '%s' is not supported", + ConstraintTypeToString(type).c_str()); + LOG_TRACE("%s", error.c_str()); + throw ConstraintException(error); + } + } // SWITCH + } // FOR (constraints) return true; } @@ -214,8 +214,8 @@ ItemPointer DataTable::GetEmptyTupleSlot(const storage::Tuple *tuple) { if (free_item_pointer.IsNull() == false) { // when inserting a tuple if (tuple != nullptr) { - auto tile_group = - storage::StorageManager::GetInstance()->GetTileGroup(free_item_pointer.block); + auto tile_group = storage::StorageManager::GetInstance()->GetTileGroup( + free_item_pointer.block); tile_group->CopyTuple(tuple, free_item_pointer.offset); } return free_item_pointer; @@ -364,7 +364,7 @@ bool DataTable::InsertTuple(const AbstractTuple *tuple, ItemPointer location, } PELOTON_ASSERT((*index_entry_ptr)->block == location.block && - (*index_entry_ptr)->offset == location.offset); + (*index_entry_ptr)->offset == location.offset); // Increase the table's number of tuples by 1 IncreaseTupleCount(1); @@ -569,7 +569,7 @@ bool DataTable::CheckForeignKeySrcAndCascade( storage::Tuple *prev_tuple, storage::Tuple *new_tuple, concurrency::TransactionContext *current_txn, executor::ExecutorContext *context, bool is_update) { - if (!schema->HasForeignKeySources()) return true; + if (!schema->HasForeignKeySources()) return true; auto &transaction_manager = concurrency::TransactionManagerFactory::GetInstance(); @@ -602,7 +602,8 @@ bool DataTable::CheckForeignKeySrcAndCascade( std::unique_ptr key( new storage::Tuple(fk_schema.get(), true)); - key->SetFromTuple(prev_tuple, cons->GetFKSinkColumnIds(), index->GetPool()); + key->SetFromTuple(prev_tuple, cons->GetFKSinkColumnIds(), + index->GetPool()); std::vector location_ptrs; index->ScanKey(key.get(), location_ptrs); @@ -635,11 +636,8 @@ bool DataTable::CheckForeignKeySrcAndCascade( // Read the referencing tuple, update the read timestamp so that // we can // delete it later - bool ret = - transaction_manager.PerformRead(current_txn, - *ptr, - src_tile_group_header, - true); + bool ret = transaction_manager.PerformRead( + current_txn, *ptr, src_tile_group_header, true); if (ret == false) { if (src_is_owner) { @@ -754,8 +752,7 @@ bool DataTable::CheckForeignKeyConstraints( catalog::Schema::CopySchema(ref_table->schema, key_attrs)); std::unique_ptr key( new storage::Tuple(foreign_key_schema.get(), true)); - key->SetFromTuple(tuple, foreign_key->GetColumnIds(), - index->GetPool()); + key->SetFromTuple(tuple, foreign_key->GetColumnIds(), index->GetPool()); LOG_TRACE("check key: %s", key->GetInfo().c_str()); std::vector location_ptrs; @@ -764,7 +761,7 @@ bool DataTable::CheckForeignKeyConstraints( // if this key doesn't exist in the referred column if (location_ptrs.size() == 0) { LOG_DEBUG("The key: %s does not exist in table %s\n", - key->GetInfo().c_str(), ref_table->GetInfo().c_str()); + key->GetInfo().c_str(), ref_table->GetName().c_str()); return false; } @@ -782,7 +779,7 @@ bool DataTable::CheckForeignKeyConstraints( LOG_DEBUG( "The key: %s is not yet visible in table %s, visibility " "type: %s.\n", - key->GetInfo().c_str(), ref_table->GetInfo().c_str(), + key->GetInfo().c_str(), ref_table->GetName().c_str(), VisibilityTypeToString(visibility).c_str()); return false; } @@ -849,7 +846,8 @@ void DataTable::ResetDirty() { dirty_ = false; } TileGroup *DataTable::GetTileGroupWithLayout( std::shared_ptr layout) { - oid_t tile_group_id = storage::StorageManager::GetInstance()->GetNextTileGroupId(); + oid_t tile_group_id = + storage::StorageManager::GetInstance()->GetNextTileGroupId(); return (AbstractTable::GetTileGroupWithLayout(database_oid, tile_group_id, layout, tuples_per_tilegroup_)); } @@ -889,7 +887,8 @@ oid_t DataTable::AddDefaultTileGroup(const size_t &active_tile_group_id) { tile_groups_.Append(tile_group_id); // add tile group metadata in locator - storage::StorageManager::GetInstance()->AddTileGroup(tile_group_id, tile_group); + storage::StorageManager::GetInstance()->AddTileGroup(tile_group_id, + tile_group); COMPILER_MEMORY_FENCE; @@ -935,7 +934,8 @@ void DataTable::AddTileGroupWithOidForRecovery(const oid_t &tile_group_id) { LOG_TRACE("Added a tile group "); // add tile group metadata in locator - storage::StorageManager::GetInstance()->AddTileGroup(tile_group_id, tile_group); + storage::StorageManager::GetInstance()->AddTileGroup(tile_group_id, + tile_group); // we must guarantee that the compiler always add tile group before adding // tile_group_count_. @@ -958,7 +958,8 @@ void DataTable::AddTileGroup(const std::shared_ptr &tile_group) { tile_groups_.Append(tile_group_id); // add tile group in catalog - storage::StorageManager::GetInstance()->AddTileGroup(tile_group_id, tile_group); + storage::StorageManager::GetInstance()->AddTileGroup(tile_group_id, + tile_group); // we must guarantee that the compiler always add tile group before adding // tile_group_count_. @@ -1113,7 +1114,6 @@ oid_t DataTable::GetValidIndexCount() const { return valid_index_count; } - // Get the schema for the new transformed tile group std::vector TransformTileGroupSchema( storage::TileGroup *tile_group, const Layout &layout) { diff --git a/test/catalog/catalog_test.cpp b/test/catalog/catalog_test.cpp index bd2c6dd9345..15db7cac655 100644 --- a/test/catalog/catalog_test.cpp +++ b/test/catalog/catalog_test.cpp @@ -83,24 +83,24 @@ TEST_F(CatalogTests, CreatingTable) { catalog->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, "emp_table", std::move(table_schema), txn); catalog->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, "department_table", - std::move(table_schema_2), txn); + std::move(table_schema_2), txn); catalog->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, "salary_table", - std::move(table_schema_3), txn); + std::move(table_schema_3), txn); - auto emp = catalog->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, - "emp_table", txn); + auto emp = + catalog->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, "emp_table", txn); auto department = catalog->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, - "department_table", txn); + "department_table", txn); auto salary = catalog->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, - "salary_table", txn); + "salary_table", txn); catalog->AddPrimaryKeyConstraint(emp->GetDatabaseOid(), emp->GetTableOid(), - {0}, "con_primary", txn); + {0}, "con_primary", txn); catalog->AddPrimaryKeyConstraint(department->GetDatabaseOid(), - department->GetTableOid(), - {0}, "con_primary", txn); - catalog->AddPrimaryKeyConstraint(salary->GetDatabaseOid(), salary->GetTableOid(), - {0}, "con_primary", txn); + department->GetTableOid(), {0}, + "con_primary", txn); + catalog->AddPrimaryKeyConstraint( + salary->GetDatabaseOid(), salary->GetTableOid(), {0}, "con_primary", txn); // insert random tuple into DATABASE_METRICS_CATALOG and check std::unique_ptr pool(new type::EphemeralPool()); @@ -114,13 +114,13 @@ TEST_F(CatalogTests, CreatingTable) { *param.buf = 'a'; auto database_object = catalog->GetDatabaseObject("emp_db", txn); catalog->GetSystemCatalogs(database_object->GetDatabaseOid()) - ->GetQueryMetricsCatalog() - ->InsertQueryMetrics("a query", database_object->GetDatabaseOid(), 1, - param, param, param, 1, 1, 1, 1, 1, 1, 1, - pool.get(), txn); + ->GetQueryMetricsCatalog() + ->InsertQueryMetrics("a query", database_object->GetDatabaseOid(), 1, + param, param, param, 1, 1, 1, 1, 1, 1, 1, pool.get(), + txn); auto param1 = catalog->GetSystemCatalogs(database_object->GetDatabaseOid()) - ->GetQueryMetricsCatalog() - ->GetParamTypes("a query", txn); + ->GetQueryMetricsCatalog() + ->GetParamTypes("a query", txn); EXPECT_EQ(1, param1.len); EXPECT_EQ('a', *param1.buf); // check colum object @@ -133,20 +133,23 @@ TEST_F(CatalogTests, TestingCatalogCache) { auto txn = txn_manager.BeginTransaction(); auto catalog = catalog::Catalog::GetInstance(); - auto catalog_db_object = catalog->GetDatabaseObject(CATALOG_DATABASE_OID, txn); + auto catalog_db_object = + catalog->GetDatabaseObject(CATALOG_DATABASE_OID, txn); auto catalog_table_objects = catalog_db_object->GetTableObjects(); EXPECT_NE(0, catalog_table_objects.size()); auto user_db_object = catalog->GetDatabaseObject("emp_db", txn); - auto user_database = storage::StorageManager::GetInstance() - ->GetDatabaseWithOid(user_db_object->GetDatabaseOid()); + auto user_database = + storage::StorageManager::GetInstance()->GetDatabaseWithOid( + user_db_object->GetDatabaseOid()); // check expected table object is acquired - for (oid_t table_idx = 0; table_idx < user_database->GetTableCount(); table_idx++) { - auto table = user_database->GetTable(table_idx); - auto user_table_object = user_db_object->GetTableObject(table->GetOid()); - EXPECT_EQ(user_db_object->GetDatabaseOid(), - user_table_object->GetDatabaseOid()); + for (oid_t table_idx = 0; table_idx < user_database->GetTableCount(); + table_idx++) { + auto table = user_database->GetTable(table_idx); + auto user_table_object = user_db_object->GetTableObject(table->GetOid()); + EXPECT_EQ(user_db_object->GetDatabaseOid(), + user_table_object->GetDatabaseOid()); } txn_manager.CommitTransaction(txn); @@ -171,7 +174,7 @@ TEST_F(CatalogTests, TableObject) { EXPECT_EQ(0, column_objects[0]->GetColumnOffset()); EXPECT_EQ(type::TypeId::INTEGER, column_objects[0]->GetColumnType()); EXPECT_EQ(type::Type::GetTypeSize(type::TypeId::INTEGER), - column_objects[0]->GetColumnLength()); + column_objects[0]->GetColumnLength()); EXPECT_TRUE(column_objects[0]->IsInlined()); EXPECT_FALSE(column_objects[0]->IsNotNull()); EXPECT_FALSE(column_objects[0]->HasDefault()); @@ -181,7 +184,7 @@ TEST_F(CatalogTests, TableObject) { EXPECT_EQ(1, column_objects[1]->GetColumnId()); EXPECT_EQ(4, column_objects[1]->GetColumnOffset()); EXPECT_EQ(type::TypeId::VARCHAR, column_objects[1]->GetColumnType()); - EXPECT_EQ(32, column_objects[1]->GetColumnLength()); + EXPECT_EQ(32, column_objects[1]->GetColumnLength()); EXPECT_TRUE(column_objects[1]->IsInlined()); EXPECT_FALSE(column_objects[1]->IsNotNull()); EXPECT_FALSE(column_objects[1]->HasDefault()); @@ -405,7 +408,8 @@ TEST_F(CatalogTests, LayoutCatalogTest) { *(first_default_layout.get()), *(pg_layout->GetLayoutWithOid(table_oid, first_layout_oid, txn).get())); EXPECT_EQ(first_layout_oid, - catalog->GetTableObject(database_oid, table_oid, txn)->GetDefaultLayoutOid()); + catalog->GetTableObject(database_oid, table_oid, txn) + ->GetDefaultLayoutOid()); txn_manager.CommitTransaction(txn); // Change default layout. @@ -434,7 +438,8 @@ TEST_F(CatalogTests, LayoutCatalogTest) { *(default_layout.get()), *(pg_layout->GetLayoutWithOid(table_oid, default_layout_oid, txn).get())); EXPECT_EQ(default_layout_oid, - catalog->GetTableObject(database_oid, table_oid, txn)->GetDefaultLayoutOid()); + catalog->GetTableObject(database_oid, table_oid, txn) + ->GetDefaultLayoutOid()); txn_manager.CommitTransaction(txn); // Create additional layout. @@ -448,7 +453,7 @@ TEST_F(CatalogTests, LayoutCatalogTest) { auto other_layout = catalog->CreateLayout(database_oid, table_oid, non_default_map, txn); EXPECT_NE(nullptr, other_layout); - txn_manager.CommitTransaction(txn); + txn_manager.CommitTransaction(txn); // Check the created layout EXPECT_FALSE(other_layout->IsColumnStore()); @@ -465,7 +470,8 @@ TEST_F(CatalogTests, LayoutCatalogTest) { // Check that the default layout is still the same. EXPECT_NE(other_layout, table->GetDefaultLayout()); EXPECT_NE(other_layout_oid, - catalog->GetTableObject(database_oid, table_oid, txn)->GetDefaultLayoutOid()); + catalog->GetTableObject(database_oid, table_oid, txn) + ->GetDefaultLayoutOid()); txn_manager.CommitTransaction(txn); // Drop the default layout. @@ -486,7 +492,8 @@ TEST_F(CatalogTests, LayoutCatalogTest) { EXPECT_EQ(nullptr, pg_layout->GetLayoutWithOid(table_oid, default_layout_oid, txn)); EXPECT_EQ(ROW_STORE_LAYOUT_OID, - catalog->GetTableObject(database_oid, table_oid, txn)->GetDefaultLayoutOid()); + catalog->GetTableObject(database_oid, table_oid, txn) + ->GetDefaultLayoutOid()); // The additional layout must be present in pg_layout EXPECT_EQ( @@ -500,7 +507,6 @@ TEST_F(CatalogTests, LayoutCatalogTest) { txn_manager.CommitTransaction(txn); } - TEST_F(CatalogTests, ConstraintCatalogTest) { auto db_name = "con_db"; auto sink_table_name = "sink_table"; @@ -512,8 +518,9 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { EXPECT_EQ(ResultType::SUCCESS, catalog->CreateDatabase(db_name, txn)); // Create table for foreign key. - auto sink_val0 = catalog::Column(type::TypeId::INTEGER, - type::Type::GetTypeSize(type::TypeId::INTEGER), "sink_val0", true); + auto sink_val0 = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "sink_val0", true); std::unique_ptr sink_table_schema( new catalog::Schema({sink_val0})); EXPECT_EQ(ResultType::SUCCESS, @@ -521,25 +528,31 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { std::move(sink_table_schema), txn)); // Create table for constraint catalog test, and set column constraints. - auto con_val0 = catalog::Column(type::TypeId::INTEGER, - type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val0", true); - auto con_val1 = catalog::Column(type::TypeId::INTEGER, - type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val1", true); - auto con_val2 = catalog::Column(type::TypeId::INTEGER, - type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val2", true); - auto con_val3 = catalog::Column(type::TypeId::INTEGER, - type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val3", true); - auto con_val4 = catalog::Column(type::TypeId::INTEGER, - type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val4", true); - auto con_val5 = catalog::Column(type::TypeId::INTEGER, - type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val5", true); - auto con_val6 = catalog::Column(type::TypeId::INTEGER, - type::Type::GetTypeSize(type::TypeId::INTEGER), "con_val6", true); + auto con_val0 = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "con_val0", true); + auto con_val1 = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "con_val1", true); + auto con_val2 = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "con_val2", true); + auto con_val3 = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "con_val3", true); + auto con_val4 = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "con_val4", true); + auto con_val5 = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "con_val5", true); + auto con_val6 = catalog::Column( + type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), + "con_val6", true); con_val5.SetNotNull(); con_val6.SetDefaultValue(type::ValueFactory::GetIntegerValue(555)); - std::unique_ptr con_table_schema( - new catalog::Schema({con_val0, con_val1, con_val2, con_val3, con_val4, - con_val5, con_val6})); + std::unique_ptr con_table_schema(new catalog::Schema( + {con_val0, con_val1, con_val2, con_val3, con_val4, con_val5, con_val6})); EXPECT_EQ(ResultType::SUCCESS, catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, con_table_name, std::move(con_table_schema), txn)); @@ -548,42 +561,40 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { auto database_oid = catalog->GetDatabaseObject(db_name, txn)->GetDatabaseOid(); - auto sink_table_object = - catalog->GetTableObject(db_name, DEFAULT_SCHEMA_NAME, sink_table_name, txn); - auto sink_table = - catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, sink_table_name, txn); + auto sink_table_object = catalog->GetTableObject(db_name, DEFAULT_SCHEMA_NAME, + sink_table_name, txn); + auto sink_table = catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, + sink_table_name, txn); auto sink_table_oid = sink_table_object->GetTableOid(); - auto con_table_object = - catalog->GetTableObject(db_name, DEFAULT_SCHEMA_NAME, con_table_name, txn); - auto con_table = - catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, con_table_name, txn); + auto con_table_object = catalog->GetTableObject(db_name, DEFAULT_SCHEMA_NAME, + con_table_name, txn); + auto con_table = catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, + con_table_name, txn); auto con_table_oid = con_table_object->GetTableOid(); - // Add primary key constraint to sink table EXPECT_EQ(ResultType::SUCCESS, - catalog->AddPrimaryKeyConstraint(database_oid, sink_table_oid, {0}, - "con_primary", txn)); + catalog->AddPrimaryKeyConstraint(database_oid, sink_table_oid, {0}, + "con_primary", txn)); // Add constraints for constraint catalog test. EXPECT_EQ(ResultType::SUCCESS, - catalog->AddPrimaryKeyConstraint(database_oid, con_table_oid, {0, 1}, - "con_primary", txn)); + catalog->AddPrimaryKeyConstraint(database_oid, con_table_oid, + {0, 1}, "con_primary", txn)); EXPECT_EQ(ResultType::SUCCESS, - catalog->AddUniqueConstraint(database_oid, con_table_oid, {2}, - "con_unique", txn)); + catalog->AddUniqueConstraint(database_oid, con_table_oid, {2}, + "con_unique", txn)); EXPECT_EQ(ResultType::SUCCESS, - catalog->AddForeignKeyConstraint(database_oid, con_table_oid, {3}, - sink_table_oid, {0}, - FKConstrActionType::NOACTION, - FKConstrActionType::NOACTION, - "con_foreign", txn)); + catalog->AddForeignKeyConstraint( + database_oid, con_table_oid, {3}, sink_table_oid, {0}, + FKConstrActionType::NOACTION, FKConstrActionType::NOACTION, + "con_foreign", txn)); auto exp = std::make_pair(ExpressionType::COMPARE_GREATERTHAN, type::ValueFactory::GetIntegerValue(0)); EXPECT_EQ(ResultType::SUCCESS, - catalog->AddCheckConstraint(database_oid, con_table_oid, {4}, - exp, "con_check", txn)); + catalog->AddCheckConstraint(database_oid, con_table_oid, {4}, exp, + "con_check", txn)); LOG_DEBUG("Success all constraint creations"); @@ -591,16 +602,16 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { auto constraint_objects = sink_table_object->GetConstraintObjects(); EXPECT_EQ(1, constraint_objects.size()); for (auto constraint_object_pair : constraint_objects) { - auto con_oid = constraint_object_pair.first; - auto con_object = constraint_object_pair.second; - auto column_ids = con_object->GetColumnIds(); + auto con_oid = constraint_object_pair.first; + auto con_object = constraint_object_pair.second; + auto column_ids = con_object->GetColumnIds(); EXPECT_LE(1, column_ids.size()); - auto constraint = sink_table->GetSchema()->GetConstraint(con_oid); - EXPECT_EQ(constraint->GetName(), con_object->GetConstraintName()); - EXPECT_EQ(constraint->GetType(), con_object->GetConstraintType()); - EXPECT_EQ(constraint->GetTableOid(), con_object->GetTableOid()); - EXPECT_EQ(constraint->GetIndexOid(), con_object->GetIndexOid()); - EXPECT_EQ(constraint->GetColumnIds().size(), column_ids.size()); + auto constraint = sink_table->GetSchema()->GetConstraint(con_oid); + EXPECT_EQ(constraint->GetName(), con_object->GetConstraintName()); + EXPECT_EQ(constraint->GetType(), con_object->GetConstraintType()); + EXPECT_EQ(constraint->GetTableOid(), con_object->GetTableOid()); + EXPECT_EQ(constraint->GetIndexOid(), con_object->GetIndexOid()); + EXPECT_EQ(constraint->GetColumnIds().size(), column_ids.size()); } // Check foreign key as sink table @@ -610,98 +621,108 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { EXPECT_EQ(con_table_oid, fk_source->GetTableOid()); EXPECT_EQ(sink_table_oid, fk_source->GetFKSinkTableOid()); - LOG_DEBUG("%s", sink_table->GetSchema()->GetInfo().c_str()); + LOG_DEBUG("%s", sink_table->GetSchema()->GetInfo().c_str()); LOG_DEBUG("Complete check for sink table"); // Single column constraints for (auto column_object_pair : con_table_object->GetColumnObjects()) { - auto column_id = column_object_pair.first; - auto column_object = column_object_pair.second; - auto column = con_table->GetSchema()->GetColumn(column_id); - - if (column_object->GetColumnName() == "con_val5") { - LOG_DEBUG("Check not null constraint in column:%s", - column_object->GetColumnName().c_str()); - EXPECT_TRUE(column_object->IsNotNull()); - EXPECT_EQ(column.IsNotNull(), column_object->IsNotNull()); - } else if (column_object->GetColumnName() == "con_val6") { - LOG_DEBUG("Check default constraint in column:%s", - column_object->GetColumnName().c_str()); - EXPECT_TRUE(column_object->HasDefault()); - EXPECT_EQ(column.HasDefault(), column_object->HasDefault()); - EXPECT_EQ(column.GetDefaultValue() - ->CompareEquals(column_object->GetDefaultValue()), - CmpBool::CmpTrue); - } + auto column_id = column_object_pair.first; + auto column_object = column_object_pair.second; + auto column = con_table->GetSchema()->GetColumn(column_id); + + if (column_object->GetColumnName() == "con_val5") { + LOG_DEBUG("Check not null constraint in column:%s", + column_object->GetColumnName().c_str()); + EXPECT_TRUE(column_object->IsNotNull()); + EXPECT_EQ(column.IsNotNull(), column_object->IsNotNull()); + } else if (column_object->GetColumnName() == "con_val6") { + LOG_DEBUG("Check default constraint in column:%s", + column_object->GetColumnName().c_str()); + EXPECT_TRUE(column_object->HasDefault()); + EXPECT_EQ(column.HasDefault(), column_object->HasDefault()); + EXPECT_EQ(column.GetDefaultValue()->CompareEquals( + column_object->GetDefaultValue()), + CmpBool::CmpTrue); + } } - // Multi-column constraints + // Multi-column constraints constraint_objects = con_table_object->GetConstraintObjects(); EXPECT_EQ(4, constraint_objects.size()); - for (auto constraint_object_pair : constraint_objects) { - auto con_oid = constraint_object_pair.first; - auto con_object = constraint_object_pair.second; - - LOG_DEBUG("Check constraint:%s (%s)", con_object->GetConstraintName().c_str(), - ConstraintTypeToString(con_object->GetConstraintType()).c_str()); - - auto constraint = con_table->GetSchema()->GetConstraint(con_oid); - EXPECT_NE(nullptr, constraint); - EXPECT_EQ(constraint->GetName(), con_object->GetConstraintName()); - EXPECT_EQ(constraint->GetType(), con_object->GetConstraintType()); - EXPECT_EQ(con_table_oid, con_object->GetTableOid()); - EXPECT_EQ(constraint->GetIndexOid(), con_object->GetIndexOid()); - EXPECT_EQ(constraint->GetColumnIds().size(), con_object->GetColumnIds().size()); - - switch (con_object->GetConstraintType()) { - case ConstraintType::PRIMARY: - case ConstraintType::UNIQUE: - break; - - case ConstraintType::FOREIGN: { - EXPECT_EQ(fk_source.get(), constraint.get()); - EXPECT_EQ(constraint->GetFKSinkTableOid(), con_object->GetFKSinkTableOid()); - EXPECT_EQ(constraint->GetFKSinkColumnIds().size(), - con_object->GetFKSinkColumnIds().size()); - EXPECT_EQ(constraint->GetFKUpdateAction(), con_object->GetFKUpdateAction()); - EXPECT_EQ(constraint->GetFKDeleteAction(), con_object->GetFKDeleteAction()); - break; - } - - case ConstraintType::CHECK: { - EXPECT_EQ(1, con_object->GetColumnIds().size()); - auto column = con_table->GetSchema()->GetColumn(con_object->GetColumnIds().at(0)); - EXPECT_EQ(constraint->GetCheckExpression().first, con_object->GetCheckExp().first); - EXPECT_EQ(constraint->GetCheckExpression().second.CompareEquals( - con_object->GetCheckExp().second), CmpBool::CmpTrue); - break; - } - default: - LOG_DEBUG("Unexpected constraint appeared: %s", - ConstraintTypeToString(con_object->GetConstraintType()).c_str()); - EXPECT_TRUE(false); - } + for (auto constraint_object_pair : constraint_objects) { + auto con_oid = constraint_object_pair.first; + auto con_object = constraint_object_pair.second; + + LOG_DEBUG("Check constraint:%s (%s)", + con_object->GetConstraintName().c_str(), + ConstraintTypeToString(con_object->GetConstraintType()).c_str()); + + auto constraint = con_table->GetSchema()->GetConstraint(con_oid); + EXPECT_NE(nullptr, constraint); + EXPECT_EQ(constraint->GetName(), con_object->GetConstraintName()); + EXPECT_EQ(constraint->GetType(), con_object->GetConstraintType()); + EXPECT_EQ(con_table_oid, con_object->GetTableOid()); + EXPECT_EQ(constraint->GetIndexOid(), con_object->GetIndexOid()); + EXPECT_EQ(constraint->GetColumnIds().size(), + con_object->GetColumnIds().size()); + + switch (con_object->GetConstraintType()) { + case ConstraintType::PRIMARY: + case ConstraintType::UNIQUE: + break; + + case ConstraintType::FOREIGN: { + EXPECT_EQ(fk_source.get(), constraint.get()); + EXPECT_EQ(constraint->GetFKSinkTableOid(), + con_object->GetFKSinkTableOid()); + EXPECT_EQ(constraint->GetFKSinkColumnIds().size(), + con_object->GetFKSinkColumnIds().size()); + EXPECT_EQ(constraint->GetFKUpdateAction(), + con_object->GetFKUpdateAction()); + EXPECT_EQ(constraint->GetFKDeleteAction(), + con_object->GetFKDeleteAction()); + break; + } + + case ConstraintType::CHECK: { + EXPECT_EQ(1, con_object->GetColumnIds().size()); + auto column = + con_table->GetSchema()->GetColumn(con_object->GetColumnIds().at(0)); + EXPECT_EQ(constraint->GetCheckExpression().first, + con_object->GetCheckExp().first); + EXPECT_EQ(constraint->GetCheckExpression().second.CompareEquals( + con_object->GetCheckExp().second), + CmpBool::CmpTrue); + break; + } + default: + LOG_DEBUG( + "Unexpected constraint appeared: %s", + ConstraintTypeToString(con_object->GetConstraintType()).c_str()); + EXPECT_TRUE(false); + } } txn_manager.CommitTransaction(txn); - LOG_DEBUG("%s", con_table->GetSchema()->GetInfo().c_str()); + LOG_DEBUG("%s", con_table->GetSchema()->GetInfo().c_str()); LOG_DEBUG("Complete check for constraint table"); // Drop constraint txn = txn_manager.BeginTransaction(); auto con_schema = con_table->GetSchema(); for (auto not_null_column_id : con_schema->GetNotNullColumns()) { - EXPECT_EQ(ResultType::SUCCESS, - catalog->DropNotNullConstraint(database_oid, con_table_oid, - not_null_column_id, txn)); + EXPECT_EQ(ResultType::SUCCESS, + catalog->DropNotNullConstraint(database_oid, con_table_oid, + not_null_column_id, txn)); + } + EXPECT_EQ(ResultType::SUCCESS, catalog->DropDefaultConstraint( + database_oid, con_table_oid, 6, txn)); + for (auto constraint : con_schema->GetConstraints()) { + EXPECT_EQ( + ResultType::SUCCESS, + catalog->DropConstraint(database_oid, con_table_oid, + constraint.second->GetConstraintOid(), txn)); } - EXPECT_EQ(ResultType::SUCCESS, - catalog->DropDefaultConstraint(database_oid, con_table_oid, 6, txn)); - for (auto constraint : con_schema->GetConstraints()) { - EXPECT_EQ(ResultType::SUCCESS, - catalog->DropConstraint(database_oid, con_table_oid, - constraint.second->GetConstraintOid(), txn)); - } txn_manager.CommitTransaction(txn); LOG_DEBUG("Complete drop constraints in constraint table"); @@ -712,6 +733,5 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { txn_manager.CommitTransaction(txn); } - } // namespace test } // namespace peloton diff --git a/test/catalog/constraints_test.cpp b/test/catalog/constraints_test.cpp index 8900d9c8143..0ac992dc5e8 100644 --- a/test/catalog/constraints_test.cpp +++ b/test/catalog/constraints_test.cpp @@ -29,7 +29,8 @@ #define CONSTRAINT_NOTNULL_TEST #define CONSTRAINT_DEFAULT_TEST // #define CONSTRAINT_CHECK_TEST -// #define CONSTRAINT_UNIQUE_TEST +#define CONSTRAINT_UNIQUE_TEST +#define CONSTRAINT_FOREIGN_KEY_TEST namespace peloton { namespace test { @@ -54,12 +55,11 @@ TEST_F(ConstraintsTests, NOTNULLTest) { // Set all of the columns to be NOT NULL std::vector notnull_col_ids; for (int i = 0; i < CONSTRAINTS_NUM_COLS; i++) { - notnull_col_ids.push_back(i); + notnull_col_ids.push_back(i); } std::unordered_map default_values; storage::DataTable *data_table = - TestingConstraintsUtil::CreateTable(notnull_col_ids, - default_values); + TestingConstraintsUtil::CreateTable(notnull_col_ids, default_values); TestingConstraintsUtil::PopulateTable(data_table); // Bootstrap @@ -113,14 +113,13 @@ TEST_F(ConstraintsTests, NOTNULLTest) { #ifdef CONSTRAINT_DEFAULT_TEST TEST_F(ConstraintsTests, DEFAULTTEST) { - // Set default value within col_B + // Set default value within col_B std::vector notnull_col_ids; std::unordered_map default_values; for (int i = 0; i < CONSTRAINTS_NUM_COLS; i++) { // COL_B if (i == 1) { - default_values[i] = - type::ValueFactory::GetIntegerValue(DEFAULT_VALUE); + default_values[i] = type::ValueFactory::GetIntegerValue(DEFAULT_VALUE); } // COL_A + COL_C + COL_D else { @@ -128,8 +127,7 @@ TEST_F(ConstraintsTests, DEFAULTTEST) { } } storage::DataTable *data_table = - TestingConstraintsUtil::CreateTable(notnull_col_ids, - default_values); + TestingConstraintsUtil::CreateTable(notnull_col_ids, default_values); // Add primary key auto catalog = catalog::Catalog::GetInstance(); auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); @@ -138,7 +136,8 @@ TEST_F(ConstraintsTests, DEFAULTTEST) { // COL_A if (i == 0) { catalog->AddPrimaryKeyConstraint(data_table->GetDatabaseOid(), - data_table->GetOid(), {i}, "con_primary", txn); + data_table->GetOid(), {i}, "con_primary", + txn); } // COL_B + COL_C + COL_D else { @@ -196,20 +195,21 @@ TEST_F(ConstraintsTests, CHECKTest) { std::unique_ptr table_schema(new catalog::Schema({column1})); std::string table_name("TEST_TABLE"); - auto result = catalog->CreateTable(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, - table_name, std::move(table_schema), - txn, false); + auto result = + catalog->CreateTable(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, table_name, + std::move(table_schema), txn, false); EXPECT_EQ(ResultType::SUCCESS, result); - auto data_table = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, - table_name, txn); + auto data_table = catalog->GetTableWithName( + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, table_name, txn); EXPECT_NE(nullptr, data_table); // add check constraint type::Value tmp_value = type::ValueFactory::GetIntegerValue(0); - catalog->AddCheckConstraint(data_table->GetDatabaseOid(), data_table->GetOid(), - {0}, "", std::make_pair(ExpressionType::COMPARE_GREATERTHAN, tmp_value), - "con_check", txn); + catalog->AddCheckConstraint( + data_table->GetDatabaseOid(), data_table->GetOid(), {0}, "", + std::make_pair(ExpressionType::COMPARE_GREATERTHAN, tmp_value), + "con_check", txn); txn_manager.CommitTransaction(txn); // begin this transaction @@ -237,7 +237,6 @@ TEST_F(ConstraintsTests, CHECKTest) { // commit this transaction txn_manager.CommitTransaction(txn); - txn = txn_manager.BeginTransaction(); auto result = catalog->DropDatabaseWithName(DEFAULT_DB_NAME, txn); EXPECT_EQ(ResultType::SUCCESS, result); @@ -250,354 +249,287 @@ TEST_F(ConstraintsTests, UNIQUETest) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto catalog = catalog::Catalog::GetInstance(); auto txn = txn_manager.BeginTransaction(); - catalog->CreateDatabase(DEFAULT_DB_NAME, txn); - auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "A", false, 0); - auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "B", false, 1); + std::string db_name = "db1"; + catalog->CreateDatabase(db_name, txn); + auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "A", false); + auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "B", false); std::unique_ptr table_schema( new catalog::Schema({column1, column2})); std::string table_name("TEST_TABLE"); - auto result = catalog->CreateTable(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, - table_name, std::move(table_schema), - txn, false); - EXPECT_EQ(ResultType::SUCCESS, result); + catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, table_name, + std::move(table_schema), txn, false); auto table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, table_name, txn); - - catalog->AddUniqueConstraint(table->GetDatabaseOid(), table->GetOid(), - {0}, "con_unique", txn); + db_name, DEFAULT_SCHEMA_NAME, table_name, txn); + catalog->AddUniqueConstraint(table->GetDatabaseOid(), table->GetOid(), {0}, + "con_unique", txn); txn_manager.CommitTransaction(txn); - // table->AddUNIQUEIndex(); - txn = txn_manager.BeginTransaction(); // begin this transaction - // Test1: insert a tuple with column meet the unique requirment - bool hasException = false; - try { - // bool result = true; - // result = - TestingConstraintsUtil::ExecuteOneInsert( - txn, table, type::ValueFactory::GetIntegerValue(10)); - // if (result == false) hasException = true; - } catch (ConstraintException e) { - hasException = true; - } - EXPECT_FALSE(hasException); + // Test1: insert a tuple with column meet the unique requirement + bool result = TestingConstraintsUtil::ExecuteOneInsert( + txn, table, type::ValueFactory::GetIntegerValue(10)); + EXPECT_TRUE(result); // Test2: insert not a valid column violate the constraint - hasException = false; - try { - // bool result = true; - // result = - TestingConstraintsUtil::ExecuteOneInsert( + result = TestingConstraintsUtil::ExecuteOneInsert( txn, table, type::ValueFactory::GetIntegerValue(10)); - // if (result == false) hasException = true; - } catch (ConstraintException e) { - hasException = true; - } - EXPECT_TRUE(hasException); + EXPECT_FALSE(result); - hasException = false; - try { - TestingConstraintsUtil::ExecuteOneInsert( + result = TestingConstraintsUtil::ExecuteOneInsert( txn, table, type::ValueFactory::GetIntegerValue(20)); - } catch (ConstraintException e) { - hasException = true; - } - EXPECT_FALSE(hasException); + EXPECT_TRUE(result); // commit this transaction txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - catalog->DropDatabaseWithName(DEFAULT_DB_NAME, txn); + catalog->DropDatabaseWithName(db_name, txn); + txn_manager.CommitTransaction(txn); +} + + TEST_F(ConstraintsTests, MULTIUNIQUETest) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto catalog = catalog::Catalog::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + std::string db_name = "db1"; + catalog->CreateDatabase(db_name, txn); + auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "A", false); + auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "B", false); + auto column3 = catalog::Column(type::TypeId::INTEGER, 25, "C", false); + std::vector cols; + cols.push_back(0); + cols.push_back(1); + std::vector columns; + columns.push_back(column1); + columns.push_back(column2); + columns.push_back(column3); + std::unique_ptr table_schema(new catalog::Schema(columns)); + std::string table_name("TEST_TABLE_1"); + catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, table_name, + std::move(table_schema), txn, false); + + // Add multi-unique constraint + auto table = catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, + table_name, txn); + catalog->AddUniqueConstraint(table->GetDatabaseOid(), table->GetOid(), cols, + "con_unique", txn); + txn_manager.CommitTransaction(txn); + + txn = txn_manager.BeginTransaction(); + // begin this transaction + // Test1: insert a tuple with column meet the unique requirment + std::vector ccs; + ccs.push_back(type::ValueFactory::GetIntegerValue(10)); + ccs.push_back(type::ValueFactory::GetIntegerValue(11)); + bool result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); + EXPECT_TRUE(result); + + // Test2: insert not a valid column violate the constraint + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(10)); + ccs.push_back(type::ValueFactory::GetIntegerValue(11)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); + EXPECT_FALSE(result); + + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(10)); + ccs.push_back(type::ValueFactory::GetIntegerValue(12)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); + EXPECT_TRUE(result); + + // commit this transaction + txn_manager.CommitTransaction(txn); + txn = txn_manager.BeginTransaction(); + catalog::Catalog::GetInstance()->DropDatabaseWithName(db_name, txn); txn_manager.CommitTransaction(txn); } #endif -// TEST_F(ConstraintsTests, MULTIUNIQUETest) { -// auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); -// auto catalog = catalog::Catalog::GetInstance(); -// auto txn = txn_manager.BeginTransaction(); -// std::string db_name = "db1"; -// catalog->CreateDatabase(db_name, nullptr); -// auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "A", false, 0); -// auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "B", false, 1); -// auto column3 = catalog::Column(type::TypeId::INTEGER, 25, "C", false, 2); -// std::vector cols; -// cols.push_back(0); -// cols.push_back(1); -// std::vector columns; -// columns.push_back(column1); -// columns.push_back(column2); -// columns.push_back(column3); -// auto mc = catalog::MultiConstraint(ConstraintType::UNIQUE, "c1", cols); -// LOG_DEBUG("%s MULTI CONSTRAINTS %s %s", peloton::DOUBLE_STAR.c_str(), -// peloton::DOUBLE_STAR.c_str(), mc.GetInfo().c_str()); -// -// std::unique_ptr table_schema(new catalog::Schema(columns)); -// table_schema->AddMultiConstraints(mc); -// std::string table_name("TEST_TABLE_1"); -// catalog->CreateTable(db_name, table_name, std::move(table_schema), txn); -// txn_manager.CommitTransaction(txn); -// storage::Database *database = catalog->GetDatabaseWithName(db_name); -// storage::DataTable *table = database->GetTableWithName(table_name); -// -// // table->AddUNIQUEIndex(); -// -// txn = txn_manager.BeginTransaction(); -// // begin this transaction -// // Test1: insert a tuple with column meet the unique requirment -// bool hasException = false; -// try { -// std::vector ccs; -// ccs.push_back(type::ValueFactory::GetIntegerValue(10)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(11)); -// // bool result = true; -// // result = -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); -// // if (result == false) hasException = true; -// } catch (ConstraintException e) { -// hasException = true; -// } -// EXPECT_FALSE(hasException); -// -// // Test2: insert not a valid column violate the constraint -// hasException = false; -// try { -// std::vector ccs; -// ccs.push_back(type::ValueFactory::GetIntegerValue(10)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(11)); -// // bool result = true; -// // result = -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); -// // if (result == false) hasException = true; -// } catch (ConstraintException e) { -// hasException = true; -// } -// EXPECT_TRUE(hasException); -// -// hasException = false; -// try { -// std::vector ccs; -// ccs.push_back(type::ValueFactory::GetIntegerValue(10)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(12)); -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); -// } catch (ConstraintException e) { -// hasException = true; -// } -// EXPECT_FALSE(hasException); -// -// // commit this transaction -// txn_manager.CommitTransaction(txn); -// txn = txn_manager.BeginTransaction(); -// catalog::Catalog::GetInstance()->DropDatabaseWithName(db_name, txn); -// txn_manager.CommitTransaction(txn); -//} - -// TEST_F(ConstraintsTests, ForeignKeySingleInsertTest) { -// // First, initial 2 tables like following -// // TABLE A -- src table TABLE B -- sink table -// // a int(primary, ref B) b int b int(primary) c int -// // 0 0 0 0 -// // 1 0 1 0 -// // 2 0 2 0 -// // ..... -// // 9 0 -// -// // create new db -// auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); -// auto txn = txn_manager.BeginTransaction(); -// auto catalog = catalog::Catalog::GetInstance(); -// std::string db_name = "db2"; -// std::string table_a_name = "tableA"; -// std::string table_b_name = "tableB"; -// catalog::Catalog::GetInstance()->CreateDatabase(db_name, nullptr); -// // txn_manager.CommitTransaction(txn); -// -// auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "a", false, 0); -// auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "b", false, 1); -// -// auto constraints = catalog::Constraint(ConstraintType::PRIMARY, "primary1"); -// column1.AddConstraint(constraints); -// LOG_DEBUG("%s %s", peloton::DOUBLE_STAR.c_str(), -// constraints.GetInfo().c_str()); std::unique_ptr -// tableA_schema( -// new catalog::Schema({column1, column2})); -// -// catalog->CreateTable(db_name, table_a_name, std::move(tableA_schema), txn); -// txn_manager.CommitTransaction(txn); -// -// txn = txn_manager.BeginTransaction(); -// auto column3 = catalog::Column(type::TypeId::INTEGER, 25, "b", false, 0); -// column3.AddConstraint(constraints); -// auto column4 = catalog::Column(type::TypeId::INTEGER, 25, "c", false, 1); -// std::unique_ptr tableB_schema( -// new catalog::Schema({column3, column4})); -// -// catalog->CreateTable(db_name, table_b_name, std::move(tableB_schema), txn); -// -// auto table_a = catalog->GetTableWithName(db_name, table_a_name); -// auto table_b = catalog->GetTableWithName(db_name, table_b_name); -// -// oid_t sink_table_id = table_b->GetOid(); -// std::vector sink_col_ids = { table_b->GetSchema()->GetColumnID("b") -// }; std::vector source_col_ids = { -// table_a->GetSchema()->GetColumnID("a") }; catalog::ForeignKey *foreign_key = -// new catalog::ForeignKey( -// sink_table_id, sink_col_ids, source_col_ids, -// FKConstrActionType::NOACTION, -// FKConstrActionType::NOACTION, -// "foreign_constraint1"); -// table_a->AddForeignKey(foreign_key); -// -// txn = txn_manager.BeginTransaction(); -// // begin this transaction -// // Test1: insert a tuple with column meet the unique requirment -// bool hasException = false; -// try { -// std::vector ccs; -// ccs.push_back(type::ValueFactory::GetIntegerValue(1)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(2)); -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); -// ccs.clear(); -// ccs.push_back(type::ValueFactory::GetIntegerValue(1)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(2)); -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); -// } catch (ConstraintException e) { -// hasException = true; -// } -// EXPECT_FALSE(hasException); -// -// hasException = true; -// try { -// std::vector ccs; -// ccs.push_back(type::ValueFactory::GetIntegerValue(3)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(4)); -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); -// ccs.clear(); -// ccs.push_back(type::ValueFactory::GetIntegerValue(2)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(5)); -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); -// } catch (ConstraintException e) { -// hasException = true; -// } -// EXPECT_TRUE(hasException); -// -// // commit this transaction -// txn_manager.CommitTransaction(txn); -// txn = txn_manager.BeginTransaction(); -// catalog::Catalog::GetInstance()->DropDatabaseWithName(db_name, txn); -// txn_manager.CommitTransaction(txn); -// delete foreign_key; -//} - -// TEST_F(ConstraintsTests, ForeignKeyMultiInsertTest) { -// // First, initial 2 tables like following -// // TABLE A -- src table TABLE B -- sink table -// // a int(primary, ref B) b int b int(primary) c int -// // 0 0 0 0 -// // 1 0 1 0 -// // 2 0 2 0 -// // ..... -// // 9 0 -// -// // create new db -// auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); -// auto txn = txn_manager.BeginTransaction(); -// auto catalog = catalog::Catalog::GetInstance(); -// std::string db_name = "db2"; -// std::string table_a_name = "tableA"; -// std::string table_b_name = "tableB"; -// catalog->CreateDatabase(db_name, txn); -// -// // TABLE A -// auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "a", false, 0); -// auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "b", false, 1); -// std::unique_ptr tableA_schema( -// new catalog::Schema({column1, column2})); -// catalog->CreateTable(db_name, table_a_name, std::move(tableA_schema), txn); -// txn_manager.CommitTransaction(txn); -// auto table_A = catalog->GetTableWithName(db_name, table_a_name); -// -// txn = txn_manager.BeginTransaction(); -// auto column3 = catalog::Column(type::TypeId::INTEGER, 25, "b", false, 0); -// auto column4 = catalog::Column(type::TypeId::INTEGER, 25, "c", false, 1); -// std::vector cols; -// cols.push_back(0); -// cols.push_back(1); -// auto mc = -// catalog::MultiConstraint(ConstraintType::PRIMARY, "multiprimary1", -// cols); -// LOG_DEBUG("%s MULTI CONSTRAINTS %s %s", peloton::DOUBLE_STAR.c_str(), -// peloton::DOUBLE_STAR.c_str(), mc.GetInfo().c_str()); -// -// // TABLE B -// catalog::Schema *table_schema = new catalog::Schema({column3, column4}); -// table_schema->AddMultiConstraints(mc); -// std::unique_ptr tableB_schema(table_schema); -// -// catalog->CreateTable(db_name, table_b_name, std::move(tableB_schema), txn); -// auto table_a = catalog->GetTableWithName(db_name, table_a_name); -// auto table_b = catalog->GetTableWithName(db_name, table_b_name); -// txn_manager.CommitTransaction(txn); -// -// // Create foreign key tableA.B -> tableB.B -// oid_t sink_table_id = table_b->GetOid(); -// std::vector sink_col_ids = { table_b->GetSchema()->GetColumnID("b") -// }; std::vector source_col_ids = { -// table_a->GetSchema()->GetColumnID("b") }; catalog::ForeignKey *foreign_key = -// new catalog::ForeignKey( -// sink_table_id, sink_col_ids, source_col_ids, -// FKConstrActionType::RESTRICT, -// FKConstrActionType::CASCADE, -// "foreign_constraint1"); -// table_A->AddForeignKey(foreign_key); -// -// // Test1: insert a tuple with column meet the constraint requirment -// -// txn = txn_manager.BeginTransaction(); -// // begin this transaction -// // Test1: insert a tuple with column meet the unique requirment -// bool hasException = false; -// try { -// std::vector ccs; -// ccs.push_back(type::ValueFactory::GetIntegerValue(1)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(2)); -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); -// ccs.clear(); -// ccs.push_back(type::ValueFactory::GetIntegerValue(2)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(1)); -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); -// } catch (ConstraintException e) { -// hasException = true; -// } -// EXPECT_FALSE(hasException); -// -// hasException = true; -// try { -// std::vector ccs; -// ccs.push_back(type::ValueFactory::GetIntegerValue(3)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(4)); -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); -// ccs.clear(); -// ccs.push_back(type::ValueFactory::GetIntegerValue(2)); -// ccs.push_back(type::ValueFactory::GetIntegerValue(5)); -// TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); -// } catch (ConstraintException e) { -// hasException = true; -// } -// EXPECT_TRUE(hasException); -// -// // commit this transaction -// txn_manager.CommitTransaction(txn); -// txn = txn_manager.BeginTransaction(); -// catalog::Catalog::GetInstance()->DropDatabaseWithName(db_name, txn); -// txn_manager.CommitTransaction(txn); -// delete foreign_key; -//} +#ifdef CONSTRAINT_FOREIGN_KEY_TEST + TEST_F(ConstraintsTests, ForeignKeySingleInsertTest) { + // First, initial 2 tables like following + // TABLE A -- src table TABLE B -- sink table + // a int(primary) b int(ref B) b int(primary) c int + // 0 0 0 0 + // 1 1 1 0 + // 2 2 2 0 + // ..... + // 9 0 + + // create new db + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + auto catalog = catalog::Catalog::GetInstance(); + std::string db_name = "db2"; + std::string table_a_name = "tableA"; + std::string table_b_name = "tableB"; + catalog::Catalog::GetInstance()->CreateDatabase(db_name, txn); + + // Table A + auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "a", false); + auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "b", false); + std::unique_ptr tableA_schema( + new catalog::Schema({column1, column2})); + catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, table_a_name, + std::move(tableA_schema), txn); + + auto table_a = catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, + table_a_name, txn); + catalog->AddPrimaryKeyConstraint(table_a->GetDatabaseOid(), table_a->GetOid(), + {0}, "con_primary", txn); + txn_manager.CommitTransaction(txn); + + // Table B + txn = txn_manager.BeginTransaction(); + auto column3 = catalog::Column(type::TypeId::INTEGER, 25, "b", false); + auto column4 = catalog::Column(type::TypeId::INTEGER, 25, "c", false); + std::unique_ptr tableB_schema( + new catalog::Schema({column3, column4})); + + catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, table_b_name, + std::move(tableB_schema), txn); + + auto table_b = catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, + table_b_name, txn); + catalog->AddPrimaryKeyConstraint(table_b->GetDatabaseOid(), table_b->GetOid(), + {0}, "con_primary", txn); + + oid_t sink_table_id = table_b->GetOid(); + std::vector sink_col_ids = { table_b->GetSchema()->GetColumnID("b") }; + std::vector source_col_ids = { table_a->GetSchema()->GetColumnID("b") }; + catalog->AddForeignKeyConstraint(table_a->GetDatabaseOid(), table_a->GetOid(), + source_col_ids, sink_table_id, sink_col_ids, FKConstrActionType::NOACTION, + FKConstrActionType::NOACTION, "con_foreign", txn); + txn_manager.CommitTransaction(txn); + + txn = txn_manager.BeginTransaction(); + // begin this transaction + // Test1: insert a tuple with column meet the constraint requirement + std::vector ccs; + ccs.push_back(type::ValueFactory::GetIntegerValue(1)); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + bool result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); + EXPECT_TRUE(result); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + ccs.push_back(type::ValueFactory::GetIntegerValue(1)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); + EXPECT_TRUE(result); + + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(3)); + ccs.push_back(type::ValueFactory::GetIntegerValue(4)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); + EXPECT_TRUE(result); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + ccs.push_back(type::ValueFactory::GetIntegerValue(5)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); + EXPECT_FALSE(result); + + // commit this transaction + txn_manager.CommitTransaction(txn); + txn = txn_manager.BeginTransaction(); + catalog::Catalog::GetInstance()->DropDatabaseWithName(db_name, txn); + txn_manager.CommitTransaction(txn); +} + + TEST_F(ConstraintsTests, ForeignKeyMultiInsertTest) { + // First, initial 2 tables like following + // TABLE A -- src table TABLE B -- sink table + // a int(ref B) b int(ref B) a int(primary) b int(primary) + // 0 0 0 0 + // 1 0 1 0 + // 2 0 2 0 + // ..... + // 9 0 + + // create new db + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + auto catalog = catalog::Catalog::GetInstance(); + std::string db_name = "db2"; + std::string table_a_name = "tableA"; + std::string table_b_name = "tableB"; + catalog->CreateDatabase(db_name, txn); + + // TABLE A + auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "a", false); + auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "b", false); + std::unique_ptr tableA_schema( + new catalog::Schema({column1, column2})); + catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, table_a_name, + std::move(tableA_schema), txn); + + auto table_a = catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, + table_a_name, txn); + txn_manager.CommitTransaction(txn); + + // TABLE B + txn = txn_manager.BeginTransaction(); + auto column3 = catalog::Column(type::TypeId::INTEGER, 25, "a", false); + auto column4 = catalog::Column(type::TypeId::INTEGER, 25, "b", false); + catalog::Schema *table_schema = new catalog::Schema({column3, column4}); + std::unique_ptr tableB_schema(table_schema); + + catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, table_b_name, + std::move(tableB_schema), txn); + + std::vector cols; + cols.push_back(0); + cols.push_back(1); + auto table_b = catalog->GetTableWithName(db_name, DEFAULT_SCHEMA_NAME, + table_b_name, txn); + catalog->AddPrimaryKeyConstraint(table_b->GetDatabaseOid(), table_b->GetOid(), + cols, "con_primary", txn); + + // Create foreign key tableA.B -> tableB.B + oid_t sink_table_id = table_b->GetOid(); + std::vector sink_col_ids = { table_b->GetSchema()->GetColumnID("a"), + table_b->GetSchema()->GetColumnID("b") }; + std::vector source_col_ids = { table_a->GetSchema()->GetColumnID("a"), + table_a->GetSchema()->GetColumnID("b") }; + catalog->AddForeignKeyConstraint(table_a->GetDatabaseOid(), table_a->GetOid(), + source_col_ids, sink_table_id, sink_col_ids, FKConstrActionType::RESTRICT, + FKConstrActionType::CASCADE, "con_foreign", txn); + txn_manager.CommitTransaction(txn); + + + txn = txn_manager.BeginTransaction(); + // begin this transaction + // Test1: insert a tuple with column meet the constraint requirement + std::vector ccs; + ccs.push_back(type::ValueFactory::GetIntegerValue(1)); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + bool result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); + EXPECT_TRUE(result); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(1)); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); + EXPECT_TRUE(result); + + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(3)); + ccs.push_back(type::ValueFactory::GetIntegerValue(4)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); + EXPECT_TRUE(result); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + ccs.push_back(type::ValueFactory::GetIntegerValue(5)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); + EXPECT_FALSE(result); + + // commit this transaction + txn_manager.CommitTransaction(txn); + txn = txn_manager.BeginTransaction(); + catalog::Catalog::GetInstance()->DropDatabaseWithName(db_name, txn); + txn_manager.CommitTransaction(txn); +} +#endif // ======================================================== From 85b6c91594a7169c7b035b661929a4fcc5f3f3c2 Mon Sep 17 00:00:00 2001 From: ksaito7 Date: Tue, 19 Jun 2018 09:59:02 -0400 Subject: [PATCH 04/10] Fix bugs in LOG_TRACE --- src/planner/create_plan.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index 4fdca125df2..47b415175b7 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -87,8 +87,8 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { col->default_value.get()); column.SetDefaultValue(const_expr_elem->GetValue()); LOG_TRACE("Added a default constraint %s on column \"%s.%s\"", - v.ToString().c_str(), table_name.c_str(), - col->name.c_str()); + const_expr_elem->GetValue().ToString().c_str(), + table_name.c_str(), col->name.c_str()); } } @@ -234,7 +234,7 @@ void CreatePlan::ProcessUniqueConstraint(const parser::ColumnDefinition *col) { unique_info.unique_cols = {col->name}; unique_info.constraint_name = "con_unique"; - LOG_TRACE("Added a unique constraint on column \"%s.%s\"", table_name.c_str, + LOG_TRACE("Added a unique constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); con_uniques.push_back(unique_info); } From f5893617fb1313f7f68d8492adee8b9bdc5cbfab Mon Sep 17 00:00:00 2001 From: ksaito7 Date: Tue, 19 Jun 2018 14:37:52 -0400 Subject: [PATCH 05/10] Replace tab with spaces --- src/catalog/database_catalog.cpp | 14 +-- src/catalog/index_catalog.cpp | 12 +-- src/catalog/layout_catalog.cpp | 8 +- src/catalog/schema.cpp | 12 +-- src/catalog/schema_catalog.cpp | 12 +-- src/common/internal_types.cpp | 42 ++++---- src/include/catalog/catalog_defaults.h | 2 +- src/include/catalog/schema.h | 86 ++++++++--------- .../stats/column_stats_collector.cpp | 8 +- test/catalog/constraints_test.cpp | 96 +++++++++---------- test/common/internal_types_test.cpp | 4 +- test/concurrency/testing_transaction_util.cpp | 20 ++-- test/executor/testing_executor_util.cpp | 4 +- test/executor/update_test.cpp | 6 +- .../catalog/testing_constraints_util.h | 12 +-- test/statistics/stats_test.cpp | 2 +- test/statistics/testing_stats_util.cpp | 4 +- 17 files changed, 172 insertions(+), 172 deletions(-) diff --git a/src/catalog/database_catalog.cpp b/src/catalog/database_catalog.cpp index 32b0a7af461..4634b1c04a6 100644 --- a/src/catalog/database_catalog.cpp +++ b/src/catalog/database_catalog.cpp @@ -269,7 +269,7 @@ DatabaseCatalog::~DatabaseCatalog() {} * @return unqiue pointer to schema */ std::unique_ptr DatabaseCatalog::InitializeSchema() { - auto database_id_column = catalog::Column( + auto database_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "database_oid", true); database_id_column.SetNotNull(); @@ -282,14 +282,14 @@ std::unique_ptr DatabaseCatalog::InitializeSchema() { new catalog::Schema({database_id_column, database_name_column})); database_catalog_schema->AddConstraint(std::make_shared( - DATABASE_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", - DATABASE_CATALOG_OID, std::vector{ColumnId::DATABASE_OID}, - DATABASE_CATALOG_PKEY_OID)); + DATABASE_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + DATABASE_CATALOG_OID, std::vector{ColumnId::DATABASE_OID}, + DATABASE_CATALOG_PKEY_OID)); database_catalog_schema->AddConstraint(std::make_shared( - DATABASE_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", - DATABASE_CATALOG_OID, std::vector{ColumnId::DATABASE_NAME}, - DATABASE_CATALOG_SKEY0_OID)); + DATABASE_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", + DATABASE_CATALOG_OID, std::vector{ColumnId::DATABASE_NAME}, + DATABASE_CATALOG_SKEY0_OID)); return database_catalog_schema; } diff --git a/src/catalog/index_catalog.cpp b/src/catalog/index_catalog.cpp index 16597e13039..2abac99dd4f 100644 --- a/src/catalog/index_catalog.cpp +++ b/src/catalog/index_catalog.cpp @@ -117,14 +117,14 @@ std::unique_ptr IndexCatalog::InitializeSchema() { indexed_attributes_column})); index_schema->AddConstraint(std::make_shared( - INDEX_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", - INDEX_CATALOG_OID, std::vector{ColumnId::INDEX_OID}, - INDEX_CATALOG_PKEY_OID)); + INDEX_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + INDEX_CATALOG_OID, std::vector{ColumnId::INDEX_OID}, + INDEX_CATALOG_PKEY_OID)); index_schema->AddConstraint(std::make_shared( - INDEX_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", - INDEX_CATALOG_OID, std::vector{ColumnId::INDEX_NAME, ColumnId::SCHEMA_NAME}, - INDEX_CATALOG_SKEY0_OID)); + INDEX_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", + INDEX_CATALOG_OID, std::vector{ColumnId::INDEX_NAME, ColumnId::SCHEMA_NAME}, + INDEX_CATALOG_SKEY0_OID)); return index_schema; } diff --git a/src/catalog/layout_catalog.cpp b/src/catalog/layout_catalog.cpp index 97c33259a6e..4ca0527ae03 100644 --- a/src/catalog/layout_catalog.cpp +++ b/src/catalog/layout_catalog.cpp @@ -44,7 +44,7 @@ LayoutCatalog::~LayoutCatalog() {} * @return unique_ptr of the schema for pg_layout. */ std::unique_ptr LayoutCatalog::InitializeSchema() { - auto table_id_column = catalog::Column( + auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); table_id_column.SetNotNull(); @@ -69,9 +69,9 @@ std::unique_ptr LayoutCatalog::InitializeSchema() { num_columns_column, column_map_column})); layout_catalog_schema->AddConstraint(std::make_shared( - LAYOUT_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", - LAYOUT_CATALOG_OID, std::vector{ColumnId::TABLE_OID, ColumnId::LAYOUT_OID}, - LAYOUT_CATALOG_PKEY_OID)); + LAYOUT_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + LAYOUT_CATALOG_OID, std::vector{ColumnId::TABLE_OID, ColumnId::LAYOUT_OID}, + LAYOUT_CATALOG_PKEY_OID)); return layout_catalog_schema; } diff --git a/src/catalog/schema.cpp b/src/catalog/schema.cpp index feb946d95b0..618899e5310 100644 --- a/src/catalog/schema.cpp +++ b/src/catalog/schema.cpp @@ -78,12 +78,12 @@ Schema::Schema(const std::vector &columns) // Set constraints for (oid_t column_itr = 0; column_itr < column_count; column_itr++) { - if (columns[column_itr].IsNotNull()) { - SetNotNull(column_itr); - } - if (columns[column_itr].HasDefault()) { - SetDefaultValue(column_itr, *(columns[column_itr].GetDefaultValue())); - } + if (columns[column_itr].IsNotNull()) { + SetNotNull(column_itr); + } + if (columns[column_itr].HasDefault()) { + SetDefaultValue(column_itr, *(columns[column_itr].GetDefaultValue())); + } } } diff --git a/src/catalog/schema_catalog.cpp b/src/catalog/schema_catalog.cpp index f34ddbd3146..57e6143e225 100644 --- a/src/catalog/schema_catalog.cpp +++ b/src/catalog/schema_catalog.cpp @@ -63,14 +63,14 @@ std::unique_ptr SchemaCatalog::InitializeSchema() { new catalog::Schema({schema_id_column, schema_name_column})); schema->AddConstraint(std::make_shared( - SCHEMA_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", - SCHEMA_CATALOG_OID, std::vector{ColumnId::SCHEMA_OID}, - SCHEMA_CATALOG_PKEY_OID)); + SCHEMA_CATALOG_CON_PKEY_OID, ConstraintType::PRIMARY, "con_primary", + SCHEMA_CATALOG_OID, std::vector{ColumnId::SCHEMA_OID}, + SCHEMA_CATALOG_PKEY_OID)); schema->AddConstraint(std::make_shared( - SCHEMA_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", - SCHEMA_CATALOG_OID, std::vector{ColumnId::SCHEMA_NAME}, - SCHEMA_CATALOG_SKEY0_OID)); + SCHEMA_CATALOG_CON_UNI0_OID, ConstraintType::UNIQUE, "con_unique", + SCHEMA_CATALOG_OID, std::vector{ColumnId::SCHEMA_NAME}, + SCHEMA_CATALOG_SKEY0_OID)); return schema; } diff --git a/src/common/internal_types.cpp b/src/common/internal_types.cpp index dda5dac8938..8ccea6515f2 100644 --- a/src/common/internal_types.cpp +++ b/src/common/internal_types.cpp @@ -2138,26 +2138,26 @@ std::ostream &operator<<(std::ostream &os, const ConstraintType &type) { std::string FKConstrActionTypeToString(FKConstrActionType type) { switch (type) { - case FKConstrActionType::NOACTION: { - return ("NOACTION"); - } - case FKConstrActionType::RESTRICT: { - return ("RESTRICT"); - } - case FKConstrActionType::CASCADE: { - return ("CASCADE"); - } - case FKConstrActionType::SETNULL: { - return ("SETNULL"); - } - case FKConstrActionType::SETDEFAULT: { - return ("SETDEFAULT"); - } - default: { - throw ConversionException(StringUtil::Format( - "No string conversion for FKConstrActionType value '%d'", - static_cast(type))); - } + case FKConstrActionType::NOACTION: { + return ("NOACTION"); + } + case FKConstrActionType::RESTRICT: { + return ("RESTRICT"); + } + case FKConstrActionType::CASCADE: { + return ("CASCADE"); + } + case FKConstrActionType::SETNULL: { + return ("SETNULL"); + } + case FKConstrActionType::SETDEFAULT: { + return ("SETDEFAULT"); + } + default: { + throw ConversionException(StringUtil::Format( + "No string conversion for FKConstrActionType value '%d'", + static_cast(type))); + } } return "INVALID"; } @@ -2177,7 +2177,7 @@ FKConstrActionType StringToFKConstrActionType(const std::string &str){ } else { throw ConversionException(StringUtil::Format( "No FKConstrActionType conversion from string '%s'", - upper_str.c_str())); + upper_str.c_str())); } return FKConstrActionType::NOACTION; } diff --git a/src/include/catalog/catalog_defaults.h b/src/include/catalog/catalog_defaults.h index fc40def8a49..4a3a5bcd1b2 100644 --- a/src/include/catalog/catalog_defaults.h +++ b/src/include/catalog/catalog_defaults.h @@ -143,7 +143,7 @@ enum class CatalogType : uint32_t { TRIGGER = 6 << CATALOG_TYPE_OFFSET, LANGUAGE = 7 << CATALOG_TYPE_OFFSET, PROC = 8 << CATALOG_TYPE_OFFSET, - CONSTRAINT = 9 << CATALOG_TYPE_OFFSET, + CONSTRAINT = 9 << CATALOG_TYPE_OFFSET, // To be added }; diff --git a/src/include/catalog/schema.h b/src/include/catalog/schema.h index 127105cd2ab..758bfbc6096 100644 --- a/src/include/catalog/schema.h +++ b/src/include/catalog/schema.h @@ -188,24 +188,24 @@ class Schema : public Printable { // Set the not null for the column inline void SetNotNull(const oid_t column_id) { - columns[column_id].SetNotNull(); - not_null_columns.push_back(column_id); + columns[column_id].SetNotNull(); + not_null_columns.push_back(column_id); } // Drop the not null for the column inline void DropNotNull(const oid_t column_id) { - columns[column_id].ClearNotNull(); - for (auto itr = not_null_columns.begin(); itr < not_null_columns.end(); itr++) { - if (*itr == column_id) { - not_null_columns.erase(itr); - break; - } - } + columns[column_id].ClearNotNull(); + for (auto itr = not_null_columns.begin(); itr < not_null_columns.end(); itr++) { + if (*itr == column_id) { + not_null_columns.erase(itr); + break; + } + } } // Get not null column list inline std::vector GetNotNullColumns() const { - return not_null_columns; + return not_null_columns; } // For single column default @@ -215,24 +215,24 @@ class Schema : public Printable { // Get the default value for the column inline type::Value* GetDefaultValue(const oid_t column_id) const { if (columns[column_id].HasDefault()) { - return columns[column_id].GetDefaultValue().get(); + return columns[column_id].GetDefaultValue().get(); } return nullptr; } // Set the default value for the column inline void SetDefaultValue(const oid_t column_id, - const type::Value &default_value) { + const type::Value &default_value) { if (columns[column_id].HasDefault()) { - columns[column_id].ClearDefaultValue(); + columns[column_id].ClearDefaultValue(); } - columns[column_id].SetDefaultValue(default_value); + columns[column_id].SetDefaultValue(default_value); } // Drop the default value for the column inline void DropDefaultValue(const oid_t column_id) { if (columns[column_id].HasDefault()) { - columns[column_id].ClearDefaultValue(); + columns[column_id].ClearDefaultValue(); } } @@ -245,38 +245,38 @@ class Schema : public Printable { constraints[constraint->GetConstraintOid()] = constraint; if (constraint->GetType() == ConstraintType::PRIMARY) { - has_primary_key_ = true; + has_primary_key_ = true; } else if (constraint->GetType() == ConstraintType::UNIQUE) { - unique_constraint_count_++; + unique_constraint_count_++; } else if (constraint->GetType() == ConstraintType::FOREIGN) { - fk_constraints_.push_back(constraint->GetConstraintOid()); + fk_constraints_.push_back(constraint->GetConstraintOid()); } } // Delete a constraint by id from the table inline void DropConstraint(oid_t constraint_oid) { if (constraints[constraint_oid]->GetType() == ConstraintType::PRIMARY) { - has_primary_key_ = false; + has_primary_key_ = false; } else if (constraints[constraint_oid]->GetType() == ConstraintType::UNIQUE) { - unique_constraint_count_--; + unique_constraint_count_--; } else if (constraints[constraint_oid]->GetType() == ConstraintType::FOREIGN) { - for (auto itr = fk_constraints_.begin(); itr < fk_constraints_.end(); itr++) { - if (*itr == constraint_oid) { - fk_constraints_.erase(itr); - break; - } - } + for (auto itr = fk_constraints_.begin(); itr < fk_constraints_.end(); itr++) { + if (*itr == constraint_oid) { + fk_constraints_.erase(itr); + break; + } + } } - constraints.erase(constraint_oid); + constraints.erase(constraint_oid); } inline std::unordered_map> GetConstraints() const { - return constraints; + return constraints; } inline std::shared_ptr GetConstraint(oid_t constraint_oid) const { - return constraints.at(constraint_oid); + return constraints.at(constraint_oid); } // For primary key constraints @@ -287,33 +287,33 @@ class Schema : public Printable { // For foreign key constraints inline std::vector> GetForeignKeyConstraints() { - std::vector> fks; - for (auto oid : fk_constraints_) { - PELOTON_ASSERT(constraints[oid]->GetType() == ConstraintType::FOREIGN); - fks.push_back(constraints[oid]); - } - return fks; + std::vector> fks; + for (auto oid : fk_constraints_) { + PELOTON_ASSERT(constraints[oid]->GetType() == ConstraintType::FOREIGN); + fks.push_back(constraints[oid]); + } + return fks; } inline bool HasForeignKeys() const { return (fk_constraints_.size() > 0); } inline void RegisterForeignKeySource(const std::shared_ptr constraint) { - fk_sources_.push_back(constraint); + fk_sources_.push_back(constraint); } inline void DeleteForeignKeySource(const oid_t constraint_oid) { - for (auto itr = fk_sources_.begin(); itr < fk_sources_.end(); itr++) { - if ((*itr)->GetConstraintOid() == constraint_oid) { - fk_sources_.erase(itr); - break; - } - } + for (auto itr = fk_sources_.begin(); itr < fk_sources_.end(); itr++) { + if ((*itr)->GetConstraintOid() == constraint_oid) { + fk_sources_.erase(itr); + break; + } + } } inline bool HasForeignKeySources() const { return (fk_sources_.size() > 0); } inline std::vector> GetForeignKeySources() { - return fk_sources_; + return fk_sources_; } // Get a string representation for debugging diff --git a/src/optimizer/stats/column_stats_collector.cpp b/src/optimizer/stats/column_stats_collector.cpp index 45b6768b314..f805258538d 100644 --- a/src/optimizer/stats/column_stats_collector.cpp +++ b/src/optimizer/stats/column_stats_collector.cpp @@ -45,10 +45,10 @@ void ColumnStatsCollector::AddValue(const type::Value &value) { if (value.IsNull()) { null_count_++; } else { - // Update all stats - hll_.Update(value); - hist_.Update(value); - topk_.Add(value); + // Update all stats + hll_.Update(value); + hist_.Update(value); + topk_.Add(value); } } diff --git a/test/catalog/constraints_test.cpp b/test/catalog/constraints_test.cpp index 0ac992dc5e8..c88249ea1d3 100644 --- a/test/catalog/constraints_test.cpp +++ b/test/catalog/constraints_test.cpp @@ -261,7 +261,7 @@ TEST_F(ConstraintsTests, UNIQUETest) { std::move(table_schema), txn, false); auto table = catalog::Catalog::GetInstance()->GetTableWithName( - db_name, DEFAULT_SCHEMA_NAME, table_name, txn); + db_name, DEFAULT_SCHEMA_NAME, table_name, txn); catalog->AddUniqueConstraint(table->GetDatabaseOid(), table->GetOid(), {0}, "con_unique", txn); txn_manager.CommitTransaction(txn); @@ -270,7 +270,7 @@ TEST_F(ConstraintsTests, UNIQUETest) { // begin this transaction // Test1: insert a tuple with column meet the unique requirement bool result = TestingConstraintsUtil::ExecuteOneInsert( - txn, table, type::ValueFactory::GetIntegerValue(10)); + txn, table, type::ValueFactory::GetIntegerValue(10)); EXPECT_TRUE(result); // Test2: insert not a valid column violate the constraint @@ -321,20 +321,20 @@ TEST_F(ConstraintsTests, UNIQUETest) { txn = txn_manager.BeginTransaction(); // begin this transaction // Test1: insert a tuple with column meet the unique requirment - std::vector ccs; - ccs.push_back(type::ValueFactory::GetIntegerValue(10)); - ccs.push_back(type::ValueFactory::GetIntegerValue(11)); - bool result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); + std::vector ccs; + ccs.push_back(type::ValueFactory::GetIntegerValue(10)); + ccs.push_back(type::ValueFactory::GetIntegerValue(11)); + bool result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); EXPECT_TRUE(result); // Test2: insert not a valid column violate the constraint - ccs.clear(); - ccs.push_back(type::ValueFactory::GetIntegerValue(10)); - ccs.push_back(type::ValueFactory::GetIntegerValue(11)); - result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(10)); + ccs.push_back(type::ValueFactory::GetIntegerValue(11)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); EXPECT_FALSE(result); - ccs.clear(); + ccs.clear(); ccs.push_back(type::ValueFactory::GetIntegerValue(10)); ccs.push_back(type::ValueFactory::GetIntegerValue(12)); result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table, ccs); @@ -372,7 +372,7 @@ TEST_F(ConstraintsTests, UNIQUETest) { auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "a", false); auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "b", false); std::unique_ptr tableA_schema( - new catalog::Schema({column1, column2})); + new catalog::Schema({column1, column2})); catalog->CreateTable(db_name, DEFAULT_SCHEMA_NAME, table_a_name, std::move(tableA_schema), txn); @@ -401,33 +401,33 @@ TEST_F(ConstraintsTests, UNIQUETest) { std::vector sink_col_ids = { table_b->GetSchema()->GetColumnID("b") }; std::vector source_col_ids = { table_a->GetSchema()->GetColumnID("b") }; catalog->AddForeignKeyConstraint(table_a->GetDatabaseOid(), table_a->GetOid(), - source_col_ids, sink_table_id, sink_col_ids, FKConstrActionType::NOACTION, - FKConstrActionType::NOACTION, "con_foreign", txn); + source_col_ids, sink_table_id, sink_col_ids, FKConstrActionType::NOACTION, + FKConstrActionType::NOACTION, "con_foreign", txn); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); // begin this transaction // Test1: insert a tuple with column meet the constraint requirement - std::vector ccs; - ccs.push_back(type::ValueFactory::GetIntegerValue(1)); - ccs.push_back(type::ValueFactory::GetIntegerValue(2)); - bool result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); + std::vector ccs; + ccs.push_back(type::ValueFactory::GetIntegerValue(1)); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + bool result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); EXPECT_TRUE(result); - ccs.clear(); - ccs.push_back(type::ValueFactory::GetIntegerValue(2)); - ccs.push_back(type::ValueFactory::GetIntegerValue(1)); - result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + ccs.push_back(type::ValueFactory::GetIntegerValue(1)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); EXPECT_TRUE(result); - ccs.clear(); - ccs.push_back(type::ValueFactory::GetIntegerValue(3)); - ccs.push_back(type::ValueFactory::GetIntegerValue(4)); - result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(3)); + ccs.push_back(type::ValueFactory::GetIntegerValue(4)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); EXPECT_TRUE(result); - ccs.clear(); - ccs.push_back(type::ValueFactory::GetIntegerValue(2)); - ccs.push_back(type::ValueFactory::GetIntegerValue(5)); - result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + ccs.push_back(type::ValueFactory::GetIntegerValue(5)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); EXPECT_FALSE(result); // commit this transaction @@ -493,34 +493,34 @@ TEST_F(ConstraintsTests, UNIQUETest) { std::vector source_col_ids = { table_a->GetSchema()->GetColumnID("a"), table_a->GetSchema()->GetColumnID("b") }; catalog->AddForeignKeyConstraint(table_a->GetDatabaseOid(), table_a->GetOid(), - source_col_ids, sink_table_id, sink_col_ids, FKConstrActionType::RESTRICT, - FKConstrActionType::CASCADE, "con_foreign", txn); + source_col_ids, sink_table_id, sink_col_ids, FKConstrActionType::RESTRICT, + FKConstrActionType::CASCADE, "con_foreign", txn); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); // begin this transaction // Test1: insert a tuple with column meet the constraint requirement - std::vector ccs; - ccs.push_back(type::ValueFactory::GetIntegerValue(1)); - ccs.push_back(type::ValueFactory::GetIntegerValue(2)); - bool result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); + std::vector ccs; + ccs.push_back(type::ValueFactory::GetIntegerValue(1)); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + bool result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); EXPECT_TRUE(result); - ccs.clear(); - ccs.push_back(type::ValueFactory::GetIntegerValue(1)); - ccs.push_back(type::ValueFactory::GetIntegerValue(2)); - result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(1)); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); EXPECT_TRUE(result); - ccs.clear(); - ccs.push_back(type::ValueFactory::GetIntegerValue(3)); - ccs.push_back(type::ValueFactory::GetIntegerValue(4)); - result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(3)); + ccs.push_back(type::ValueFactory::GetIntegerValue(4)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_b, ccs); EXPECT_TRUE(result); - ccs.clear(); - ccs.push_back(type::ValueFactory::GetIntegerValue(2)); - ccs.push_back(type::ValueFactory::GetIntegerValue(5)); - result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); + ccs.clear(); + ccs.push_back(type::ValueFactory::GetIntegerValue(2)); + ccs.push_back(type::ValueFactory::GetIntegerValue(5)); + result = TestingConstraintsUtil::ExecuteMultiInsert(txn, table_a, ccs); EXPECT_FALSE(result); // commit this transaction diff --git a/test/common/internal_types_test.cpp b/test/common/internal_types_test.cpp index 9c673b04284..a8ff6b0881c 100644 --- a/test/common/internal_types_test.cpp +++ b/test/common/internal_types_test.cpp @@ -406,8 +406,8 @@ TEST_F(InternalTypesTests, ResultTypeTest) { TEST_F(InternalTypesTests, ConstraintTypeTest) { std::vector list = { ConstraintType::INVALID, ConstraintType::CHECK, - ConstraintType::PRIMARY, ConstraintType::UNIQUE, - ConstraintType::FOREIGN, ConstraintType::EXCLUSION}; + ConstraintType::PRIMARY, ConstraintType::UNIQUE, + ConstraintType::FOREIGN, ConstraintType::EXCLUSION}; // Make sure that ToString and FromString work for (auto val : list) { diff --git a/test/concurrency/testing_transaction_util.cpp b/test/concurrency/testing_transaction_util.cpp index b29081b3d24..6366c87597c 100644 --- a/test/concurrency/testing_transaction_util.cpp +++ b/test/concurrency/testing_transaction_util.cpp @@ -77,8 +77,8 @@ storage::DataTable *TestingTransactionUtil::CreateCombinedPrimaryKeyTable() { // Create constraint on the table std::shared_ptr constraint( - new catalog::Constraint(1000, ConstraintType::PRIMARY, - "con_primary", TEST_TABLE_OID, key_attrs, 1234)); + new catalog::Constraint(1000, ConstraintType::PRIMARY, + "con_primary", TEST_TABLE_OID, key_attrs, 1234)); table->GetSchema()->AddConstraint(constraint); // Insert tuple @@ -129,8 +129,8 @@ storage::DataTable *TestingTransactionUtil::CreatePrimaryKeyUniqueKeyTable() { // Create primary key constraint on the table std::shared_ptr constraint( - new catalog::Constraint(1000, ConstraintType::PRIMARY, - "con_primary", TEST_TABLE_OID, key_attrs, 1234)); + new catalog::Constraint(1000, ConstraintType::PRIMARY, + "con_primary", TEST_TABLE_OID, key_attrs, 1234)); table->GetSchema()->AddConstraint(constraint); // Create unique index on the value column @@ -151,8 +151,8 @@ storage::DataTable *TestingTransactionUtil::CreatePrimaryKeyUniqueKeyTable() { // Create unique constraint on the table std::shared_ptr unique_constraint( - new catalog::Constraint(1001, ConstraintType::UNIQUE, - "con_unique", TEST_TABLE_OID, key_attrs, 1235)); + new catalog::Constraint(1001, ConstraintType::UNIQUE, + "con_unique", TEST_TABLE_OID, key_attrs, 1235)); table->GetSchema()->AddConstraint(unique_constraint); // Insert tuple @@ -204,10 +204,10 @@ storage::DataTable *TestingTransactionUtil::CreateTable( // Create primary key constraint on the table if (need_primary_index) { - std::shared_ptr constraint( - new catalog::Constraint(1000, ConstraintType::PRIMARY, - "con_primary", relation_id, key_attrs, index_oid)); - table->GetSchema()->AddConstraint(constraint); + std::shared_ptr constraint( + new catalog::Constraint(1000, ConstraintType::PRIMARY, + "con_primary", relation_id, key_attrs, index_oid)); + table->GetSchema()->AddConstraint(constraint); } // add this table to current database diff --git a/test/executor/testing_executor_util.cpp b/test/executor/testing_executor_util.cpp index 80b78427da6..3218e583a4a 100644 --- a/test/executor/testing_executor_util.cpp +++ b/test/executor/testing_executor_util.cpp @@ -396,8 +396,8 @@ storage::DataTable *TestingExecutorUtil::CreateTable( // Create constraint on the table std::shared_ptr constraint( - new catalog::Constraint(1000, ConstraintType::PRIMARY, - "con_primary", table_oid, key_attrs, 123)); + new catalog::Constraint(1000, ConstraintType::PRIMARY, + "con_primary", table_oid, key_attrs, 123)); table->GetSchema()->AddConstraint(constraint); ///////////////////////////////////////////////////////////////// diff --git a/test/executor/update_test.cpp b/test/executor/update_test.cpp index e354162c986..0c1cf2d91d4 100644 --- a/test/executor/update_test.cpp +++ b/test/executor/update_test.cpp @@ -185,10 +185,10 @@ TEST_F(UpdateTests, UpdatingOld) { catalog->CreateTable(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table", std::move(table_schema), txn); auto table_object = - catalog->GetTableObject(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, - "department_table", txn); + catalog->GetTableObject(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); catalog->AddPrimaryKeyConstraint(table_object->GetDatabaseOid(), - table_object->GetTableOid(), {0}, "con_primary", txn); + table_object->GetTableOid(), {0}, "con_primary", txn); LOG_INFO("Table created!"); diff --git a/test/include/catalog/testing_constraints_util.h b/test/include/catalog/testing_constraints_util.h index bb8c3fb6ba7..0425a1d0538 100644 --- a/test/include/catalog/testing_constraints_util.h +++ b/test/include/catalog/testing_constraints_util.h @@ -93,8 +93,8 @@ class TestingConstraintsUtil { public: /** @brief Creates a basic table with allocated but not populated tuples */ static storage::DataTable *CreateTable( - std::vector notnull_col_ids, - std::unordered_map default_values, + std::vector notnull_col_ids, + std::unordered_map default_values, UNUSED_ATTRIBUTE bool indexes = true) { // Create the database auto catalog = catalog::Catalog::GetInstance(); @@ -113,12 +113,12 @@ class TestingConstraintsUtil { // set single column constraints for (auto col_oid : notnull_col_ids) { - PELOTON_ASSERT(col_oid < CONSTRAINTS_NUM_COLS); - columns[col_oid].SetNotNull(); + PELOTON_ASSERT(col_oid < CONSTRAINTS_NUM_COLS); + columns[col_oid].SetNotNull(); } for (auto dv : default_values) { - PELOTON_ASSERT(dv.first < CONSTRAINTS_NUM_COLS); - columns[dv.first].SetDefaultValue(dv.second); + PELOTON_ASSERT(dv.first < CONSTRAINTS_NUM_COLS); + columns[dv.first].SetDefaultValue(dv.second); } std::unique_ptr table_schema(new catalog::Schema(columns)); diff --git a/test/statistics/stats_test.cpp b/test/statistics/stats_test.cpp index c06f4f536ae..77fa65e97d8 100644 --- a/test/statistics/stats_test.cpp +++ b/test/statistics/stats_test.cpp @@ -146,7 +146,7 @@ TEST_F(StatsTests, MultiThreadStatsTest) { "emp_db", DEFAULT_SCHEMA_NAME, "department_table", txn); catalog->AddPrimaryKeyConstraint(database->GetOid(), table->GetOid(), {0}, - "con_primary", txn); + "con_primary", txn); txn_manager.CommitTransaction(txn); LaunchParallelTest(num_threads, TransactionTest, database, table); diff --git a/test/statistics/testing_stats_util.cpp b/test/statistics/testing_stats_util.cpp index 022cf8db06b..1b708994723 100644 --- a/test/statistics/testing_stats_util.cpp +++ b/test/statistics/testing_stats_util.cpp @@ -127,9 +127,9 @@ void TestingStatsUtil::CreateTable(bool has_primary_key) { if (has_primary_key) { auto table_object = catalog->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, - "department_table", txn); + "department_table", txn); catalog->AddPrimaryKeyConstraint(table_object->GetDatabaseOid(), - table_object->GetTableOid(), {0}, "con_primary", txn); + table_object->GetTableOid(), {0}, "con_primary", txn); } txn_manager.CommitTransaction(txn); } From e752d4b7fe9a26155c06f10e0037556b79784eb6 Mon Sep 17 00:00:00 2001 From: ksaito7 Date: Wed, 20 Jun 2018 15:18:10 -0400 Subject: [PATCH 06/10] Fix a problem that the order of query results changes --- test/brain/query_logger_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/brain/query_logger_test.cpp b/test/brain/query_logger_test.cpp index c3affa7fd40..301e3408dbd 100644 --- a/test/brain/query_logger_test.cpp +++ b/test/brain/query_logger_test.cpp @@ -53,7 +53,7 @@ class QueryLoggerTests : public PelotonTest { sleep(wait_time_); TestingSQLUtil::ExecuteSQLQueryAndCheckResult(select_query_.c_str(), - expected_result, true); + expected_result); // the select query we used will also be logged for next time expected_result.push_back(select_query_ + "|" + select_query_fingerprint_); @@ -88,7 +88,7 @@ class QueryLoggerTests : public PelotonTest { temporary_expected_result.end()); temporary_expected_result.clear(); TestingSQLUtil::ExecuteSQLQueryAndCheckResult(select_query_.c_str(), - expected_result, true); + expected_result); // the select query we used will also be logged for next time expected_result.push_back(select_query_ + "|" + @@ -97,7 +97,7 @@ class QueryLoggerTests : public PelotonTest { } else { // verify that the logging does not happen before the txn commit TestingSQLUtil::ExecuteSQLQueryAndCheckResult(select_query_.c_str(), - expected_result, true); + expected_result); // the select query we used will also be logged for next time temporary_expected_result.push_back(select_query_ + "|" + select_query_fingerprint_); From f78931966a365536dd697161caf7075cb813e0cf Mon Sep 17 00:00:00 2001 From: ksaito7 Date: Wed, 27 Jun 2018 13:06:18 -0400 Subject: [PATCH 07/10] Rename ConstraintCatalogObject to ConstraintCatalogEntry --- src/catalog/catalog.cpp | 2 +- src/catalog/constraint_catalog.cpp | 30 ++++++++--------- src/catalog/table_catalog.cpp | 42 ++++++++++++------------ src/include/catalog/constraint_catalog.h | 17 +++++----- src/include/catalog/table_catalog.h | 22 ++++++------- test/catalog/catalog_test.cpp | 4 +-- 6 files changed, 59 insertions(+), 58 deletions(-) diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 6ea8b1515f7..9461d01827b 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -1223,7 +1223,7 @@ ResultType Catalog::DropConstraint(oid_t database_oid, oid_t table_oid, concurrency::TransactionContext *txn) { auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); auto constraint_object = - pg_constraint->GetConstraintObject(table_oid, constraint_oid, txn); + pg_constraint->GetConstraintCatalogEntry(table_oid, constraint_oid, txn); // delete constraint object from pg_constraint if (!pg_constraint->DeleteConstraint(table_oid, constraint_oid, txn)) { diff --git a/src/catalog/constraint_catalog.cpp b/src/catalog/constraint_catalog.cpp index 15b47ac2864..aabcce79fd0 100644 --- a/src/catalog/constraint_catalog.cpp +++ b/src/catalog/constraint_catalog.cpp @@ -27,7 +27,7 @@ namespace peloton { namespace catalog { -ConstraintCatalogObject::ConstraintCatalogObject(executor::LogicalTile *tile, +ConstraintCatalogEntry::ConstraintCatalogEntry(executor::LogicalTile *tile, int tupleId) : constraint_oid( tile->GetValue(tupleId, ConstraintCatalog::ColumnId::CONSTRAINT_OID) @@ -307,7 +307,7 @@ bool ConstraintCatalog::DeleteConstraints( ->GetSystemCatalogs(database_oid) ->GetTableCatalog(); auto table_object = pg_table->GetTableObject(table_oid, txn); - table_object->EvictAllConstraintObjects(); + table_object->EvictAllConstraintCatalogEntries(); return DeleteWithIndexScan(index_offset, values, txn); } @@ -329,7 +329,7 @@ bool ConstraintCatalog::DeleteConstraint(oid_t table_oid, oid_t constraint_oid, ->GetSystemCatalogs(database_oid) ->GetTableCatalog(); auto table_object = pg_table->GetTableObject(table_oid, txn); - table_object->EvictConstraintObject(constraint_oid); + table_object->EvictConstraintCatalogEntry(constraint_oid); return DeleteWithIndexScan(index_offset, values, txn); } @@ -341,8 +341,8 @@ bool ConstraintCatalog::DeleteConstraint(oid_t table_oid, oid_t constraint_oid, * @return unordered_map containing a constraint_oid -> * constraint object mapping. */ -const std::unordered_map> -ConstraintCatalog::GetConstraintObjects(oid_t table_oid, +const std::unordered_map> +ConstraintCatalog::GetConstraintCatalogEntries(oid_t table_oid, concurrency::TransactionContext *txn) { // try get from cache auto pg_table = Catalog::GetInstance() @@ -351,7 +351,7 @@ ConstraintCatalog::GetConstraintObjects(oid_t table_oid, auto table_object = pg_table->GetTableObject(table_oid, txn); PELOTON_ASSERT(table_object && table_object->GetTableOid() == table_oid); - auto constraint_objects = table_object->GetConstraintObjects(true); + auto constraint_objects = table_object->GetConstraintCatalogEntries(true); if (constraint_objects.size() != 0) return constraint_objects; // cache miss, get from pg_attribute @@ -366,12 +366,12 @@ ConstraintCatalog::GetConstraintObjects(oid_t table_oid, for (auto &tile : (*result_tiles)) { for (auto tuple_id : *tile) { auto constraint_object = - std::make_shared(tile.get(), tuple_id); - table_object->InsertConstraintObject(constraint_object); + std::make_shared(tile.get(), tuple_id); + table_object->InsertConstraintCatalogEntry(constraint_object); } } - return table_object->GetConstraintObjects(); + return table_object->GetConstraintCatalogEntries(); } /** @brief Get the constraint object by constraint_oid from @@ -382,9 +382,9 @@ ConstraintCatalog::GetConstraintObjects(oid_t table_oid, * @return shared_ptr constraint object to the constraint_oid if found. * nullptr otherwise. */ -const std::shared_ptr -ConstraintCatalog::GetConstraintObject(oid_t table_oid, oid_t constraint_oid, - concurrency::TransactionContext *txn) { +const std::shared_ptr +ConstraintCatalog::GetConstraintCatalogEntry(oid_t table_oid, + oid_t constraint_oid, concurrency::TransactionContext *txn) { // try get from cache auto pg_table = Catalog::GetInstance() ->GetSystemCatalogs(database_oid) @@ -393,7 +393,7 @@ ConstraintCatalog::GetConstraintObject(oid_t table_oid, oid_t constraint_oid, PELOTON_ASSERT(table_object && table_object->GetTableOid() == table_oid); auto constraint_object = - table_object->GetConstraintObject(constraint_oid, true); + table_object->GetConstraintCatalogEntry(constraint_oid, true); if (constraint_object != nullptr) return constraint_object; // cache miss, get from pg_attribute @@ -407,8 +407,8 @@ ConstraintCatalog::GetConstraintObject(oid_t table_oid, oid_t constraint_oid, if (result_tiles->size() == 1 && (*result_tiles)[0]->GetTupleCount() == 1) { auto constraint_object = - std::make_shared((*result_tiles)[0].get()); - table_object->InsertConstraintObject(constraint_object); + std::make_shared((*result_tiles)[0].get()); + table_object->InsertConstraintCatalogEntry(constraint_object); return constraint_object; } diff --git a/src/catalog/table_catalog.cpp b/src/catalog/table_catalog.cpp index 221dfb59b03..c245057e460 100644 --- a/src/catalog/table_catalog.cpp +++ b/src/catalog/table_catalog.cpp @@ -419,12 +419,12 @@ bool TableCatalogObject::EvictLayout(oid_t layout_id) { } -/** @brief Insert constraint object into the cache. - * @param constraint_object Constraint object to be inserted - * @return false if the constraint object already exists in cache +/** @brief Insert a constraint catalog entry into the cache. + * @param constraint_object Constraint to be inserted + * @return false if the constraint already exists in cache */ -bool TableCatalogObject::InsertConstraintObject( - std::shared_ptr constraint_object) { +bool TableCatalogObject::InsertConstraintCatalogEntry( + std::shared_ptr constraint_object) { // Invalid object if (!constraint_object || (constraint_object->GetConstraintOid() == INVALID_OID)) { @@ -443,14 +443,14 @@ bool TableCatalogObject::InsertConstraintObject( } -/** @brief Evict constraint object from the cache. - * @param constraint_oid Id of the constraint to be deleted. +/** @brief Evict a constraint catalog entry from the cache. + * @param constraint_oid Id of the constraint to be deleted. * @return true if constraint_oid is found and evicted; false if not found. */ -bool TableCatalogObject::EvictConstraintObject(oid_t constraint_oid) { +bool TableCatalogObject::EvictConstraintCatalogEntry(oid_t constraint_oid) { if (!valid_constraint_objects_) return false; - // find the constraint object from the cache + // find the constraint catalog entry from the cache auto it = constraint_objects_.find(constraint_oid); if (it == constraint_objects_.end()) { return false; // constraint_oid not found in cache @@ -462,37 +462,37 @@ bool TableCatalogObject::EvictConstraintObject(oid_t constraint_oid) { return true; } -/** @brief evict all constraint objects from cache. */ -void TableCatalogObject::EvictAllConstraintObjects() { +/** @brief evict all constraint catalog entries from cache. */ +void TableCatalogObject::EvictAllConstraintCatalogEntries() { constraint_objects_.clear(); valid_constraint_objects_ = false; } -/** @brief Get all constraint objects of this table. +/** @brief Get all constraint catalog entries of this table. * Add it to the cache if necessary. - * @param cached_only If set to true, don't fetch the constraint objects. + * @param cached_only If set to true, don't fetch the constraints. * @return Map from constraint_oid to cached constraint object. */ -std::unordered_map> -TableCatalogObject::GetConstraintObjects(bool cached_only) { +std::unordered_map> +TableCatalogObject::GetConstraintCatalogEntries(bool cached_only) { if (!valid_constraint_objects_ && !cached_only) { // get constraint catalog objects from pg_constraint auto pg_constraint = Catalog::GetInstance() ->GetSystemCatalogs(database_oid) ->GetConstraintCatalog(); - pg_constraint->GetConstraintObjects(table_oid, txn); + pg_constraint->GetConstraintCatalogEntries(table_oid, txn); valid_constraint_objects_ = true; } return constraint_objects_; } -/** @brief Get the constraint catalog object of the given constraint_oid. +/** @brief Get a constraint catalog entry of the given constraint_oid. * @param constraint_oid The id of the constraint to be fetched. - * @param cached_only If set to true, don't fetch the constraint objects. + * @param cached_only If set to true, don't fetch the constraint. * @return Constraint catalog object of corresponding to the oid if present. */ -std::shared_ptr -TableCatalogObject::GetConstraintObject(oid_t constraint_oid, bool cached_only){ +std::shared_ptr +TableCatalogObject::GetConstraintCatalogEntry(oid_t constraint_oid, bool cached_only){ auto it = constraint_objects_.find(constraint_oid); if (it != constraint_objects_.end()) return it->second; @@ -504,7 +504,7 @@ TableCatalogObject::GetConstraintObject(oid_t constraint_oid, bool cached_only){ auto pg_constraint = Catalog::GetInstance() ->GetSystemCatalogs(database_oid) ->GetConstraintCatalog(); - return pg_constraint->GetConstraintObject(table_oid, constraint_oid, txn); + return pg_constraint->GetConstraintCatalogEntry(table_oid, constraint_oid, txn); } } diff --git a/src/include/catalog/constraint_catalog.h b/src/include/catalog/constraint_catalog.h index 7cb5e84d122..2095597660b 100644 --- a/src/include/catalog/constraint_catalog.h +++ b/src/include/catalog/constraint_catalog.h @@ -46,11 +46,11 @@ namespace catalog { class Constraint; -class ConstraintCatalogObject { +class ConstraintCatalogEntry { friend class ConstraintCatalog; public: - ConstraintCatalogObject(executor::LogicalTile *tile, int tupleId = 0); + ConstraintCatalogEntry(executor::LogicalTile *tile, int tupleId = 0); inline oid_t GetConstraintOid() { return constraint_oid; } inline const std::string &GetConstraintName() { return constraint_name; } @@ -84,7 +84,7 @@ class ConstraintCatalogObject { }; class ConstraintCatalog : public AbstractCatalog { - friend class ConstraintCatalogObject; + friend class ConstraintCatalogEntry; friend class TableCatalogObject; friend class Catalog; @@ -114,12 +114,13 @@ class ConstraintCatalog : public AbstractCatalog { //===--------------------------------------------------------------------===// // Read Related API(only called within table catalog object) //===--------------------------------------------------------------------===// - const std::unordered_map> - GetConstraintObjects(oid_t table_oid, concurrency::TransactionContext *txn); + const std::unordered_map> + GetConstraintCatalogEntries(oid_t table_oid, + concurrency::TransactionContext *txn); - const std::shared_ptr GetConstraintObject( - oid_t table_oid, oid_t constraint_oid, - concurrency::TransactionContext *txn); + const std::shared_ptr + GetConstraintCatalogEntry(oid_t table_oid, oid_t constraint_oid, + concurrency::TransactionContext *txn); std::unique_ptr InitializeSchema(); diff --git a/src/include/catalog/table_catalog.h b/src/include/catalog/table_catalog.h index 25e4bf3f823..4a01d7e2ca8 100644 --- a/src/include/catalog/table_catalog.h +++ b/src/include/catalog/table_catalog.h @@ -45,7 +45,7 @@ namespace catalog { class IndexCatalogObject; class ColumnCatalogObject; -class ConstraintCatalogObject; +class ConstraintCatalogEntry; class TableCatalogObject { friend class TableCatalog; @@ -90,14 +90,14 @@ class TableCatalogObject { std::shared_ptr GetLayout(oid_t layout_id, bool cached_entry = false); - // Evict all layouts from the cache - void EvictAllConstraintObjects(); + // Evict all constraints from the cache + void EvictAllConstraintCatalogEntries(); // Get constraints - std::unordered_map> - GetConstraintObjects(bool cached_only = false); - std::shared_ptr - GetConstraintObject(oid_t constraint_oid, bool cached_entry = false); + std::unordered_map> + GetConstraintCatalogEntries(bool cached_only = false); + std::shared_ptr + GetConstraintCatalogEntry(oid_t constraint_oid, bool cached_entry = false); inline oid_t GetTableOid() { return table_oid; } inline const std::string &GetTableName() { return table_name; } @@ -131,10 +131,10 @@ class TableCatalogObject { bool EvictLayout(oid_t layout_id); // Insert constraint object table object - bool InsertConstraintObject( - std::shared_ptr constraint_object); + bool InsertConstraintCatalogEntry( + std::shared_ptr constraint_object); // Evict constraint_oid from the table object - bool EvictConstraintObject(oid_t constraint_oid); + bool EvictConstraintCatalogEntry(oid_t constraint_oid); // cache for *all* index catalog objects in this table std::unordered_map> index_objects; @@ -155,7 +155,7 @@ class TableCatalogObject { bool valid_layout_objects_; // cache for *all* layout objects in the table - std::unordered_map> + std::unordered_map> constraint_objects_; bool valid_constraint_objects_; diff --git a/test/catalog/catalog_test.cpp b/test/catalog/catalog_test.cpp index 15db7cac655..d4cd47f1c5e 100644 --- a/test/catalog/catalog_test.cpp +++ b/test/catalog/catalog_test.cpp @@ -599,7 +599,7 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { LOG_DEBUG("Success all constraint creations"); // Check constraint - auto constraint_objects = sink_table_object->GetConstraintObjects(); + auto constraint_objects = sink_table_object->GetConstraintCatalogEntries(); EXPECT_EQ(1, constraint_objects.size()); for (auto constraint_object_pair : constraint_objects) { auto con_oid = constraint_object_pair.first; @@ -647,7 +647,7 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { } // Multi-column constraints - constraint_objects = con_table_object->GetConstraintObjects(); + constraint_objects = con_table_object->GetConstraintCatalogEntries(); EXPECT_EQ(4, constraint_objects.size()); for (auto constraint_object_pair : constraint_objects) { auto con_oid = constraint_object_pair.first; From bb11eb9bf6e23c78b2c6ada624a44d69a590c506 Mon Sep 17 00:00:00 2001 From: ksaito7 Date: Thu, 28 Jun 2018 18:10:32 -0400 Subject: [PATCH 08/10] Fix constraints stuff --- src/catalog/catalog.cpp | 6 +-- src/catalog/constraint_catalog.cpp | 13 +++--- src/catalog/table_catalog.cpp | 27 +++++------ src/common/internal_types.cpp | 9 +++- src/include/catalog/table_catalog.h | 25 ++++++----- src/include/common/internal_types.h | 11 ++--- test/catalog/catalog_test.cpp | 45 ++++++++++++++++--- test/concurrency/testing_transaction_util.cpp | 6 +-- .../concurrency/testing_transaction_util.h | 2 +- 9 files changed, 91 insertions(+), 53 deletions(-) diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index aee82f02cae..ea73e0552fe 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -544,8 +544,6 @@ ResultType Catalog::CreateTable(concurrency::TransactionContext *txn, // Insert column info into each catalog oid_t column_id = 0; - std::vector pkey_attrs, unique_attrs; - std::shared_ptr pkey_constraint, unique_constraint; for (const auto &column : table->GetSchema()->GetColumns()) { pg_attribute->InsertColumn(txn, table_oid, @@ -960,7 +958,7 @@ ResultType Catalog::AddUniqueConstraint(concurrency::TransactionContext *txn, ->GetSchema(); // Create index - std::stringstream index_name(table_object->GetTableName().c_str()); + std::stringstream index_name(table_object->GetTableName()); for (auto column_id : column_ids) index_name << "_" + schema->GetColumn(column_id).GetName(); index_name << "_UNIQ"; @@ -1035,7 +1033,7 @@ ResultType Catalog::AddForeignKeyConstraint(concurrency::TransactionContext *txn ->GetTableCatalogEntry(txn, src_table_oid); auto src_schema = src_table->GetSchema(); - std::stringstream index_name(src_table_object->GetTableName().c_str()); + std::stringstream index_name(src_table_object->GetTableName()); for (auto col_id : src_col_ids) index_name << "_" << src_schema->GetColumn(col_id).GetName(); index_name << "_fkey"; diff --git a/src/catalog/constraint_catalog.cpp b/src/catalog/constraint_catalog.cpp index f89e23eae32..f780333e700 100644 --- a/src/catalog/constraint_catalog.cpp +++ b/src/catalog/constraint_catalog.cpp @@ -93,6 +93,8 @@ ConstraintCatalogEntry::ConstraintCatalogEntry(executor::LogicalTile *tile, case ConstraintType::EXCLUSION: default: + LOG_ERROR("Invalid Constraint type from pg_constraint: %s", + ConstraintTypeToString(constraint_type_).c_str()); break; } } @@ -190,8 +192,6 @@ std::unique_ptr ConstraintCatalog::InitializeSchema() { /*@brief Insert a constraint into the pg_constraint table * This targets PRIMARY KEY, FOREIGN KEY, UNIQUE or CHECK constraint * @param txn TransactionContext for adding the constraint. - * @param table_oid oid of the table related to this constraint - * @param column_ids vector of oids of column related to this constraint * @param constraint to be inserted into pg_constraint * @param pool to allocate memory for the column_map column. * @return true on success. @@ -308,7 +308,7 @@ bool ConstraintCatalog::DeleteConstraints(concurrency::TransactionContext *txn, std::vector values; values.push_back(type::ValueFactory::GetIntegerValue(table_oid).Copy()); - // delete columns from cache + // delete constraints from cache auto pg_table = Catalog::GetInstance() ->GetSystemCatalogs(database_oid_) ->GetTableCatalog(); @@ -331,7 +331,7 @@ bool ConstraintCatalog::DeleteConstraint(concurrency::TransactionContext *txn, std::vector values; values.push_back(type::ValueFactory::GetIntegerValue(constraint_oid).Copy()); - // delete column from cache + // delete constraint from cache auto pg_table = Catalog::GetInstance() ->GetSystemCatalogs(database_oid_) ->GetTableCatalog(); @@ -361,7 +361,7 @@ ConstraintCatalog::GetConstraintCatalogEntries(concurrency::TransactionContext * auto constraint_objects = table_object->GetConstraintCatalogEntries(true); if (constraint_objects.size() != 0) return constraint_objects; - // cache miss, get from pg_attribute + // cache miss, get from pg_constraint std::vector column_ids(all_column_ids_); oid_t index_offset = IndexId::SKEY_TABLE_OID; // Index of table_oid std::vector values; @@ -378,6 +378,7 @@ ConstraintCatalog::GetConstraintCatalogEntries(concurrency::TransactionContext * } } + table_object->SetValidConstraintCatalogEntries(true); return table_object->GetConstraintCatalogEntries(); } @@ -404,7 +405,7 @@ ConstraintCatalog::GetConstraintCatalogEntry(concurrency::TransactionContext *tx table_object->GetConstraintCatalogEntry(constraint_oid, true); if (constraint_object != nullptr) return constraint_object; - // cache miss, get from pg_attribute + // cache miss, get from pg_constraint std::vector column_ids(all_column_ids_); oid_t index_offset = IndexId::PRIMARY_KEY; // Index of table_oid std::vector values; diff --git a/src/catalog/table_catalog.cpp b/src/catalog/table_catalog.cpp index b22cf86e579..14cdd46c7ef 100644 --- a/src/catalog/table_catalog.cpp +++ b/src/catalog/table_catalog.cpp @@ -51,6 +51,7 @@ TableCatalogEntry::TableCatalogEntry(concurrency::TransactionContext *txn, column_names_(), valid_column_catalog_entries_(false), valid_layout_catalog_entries_(false), + constraint_catalog_entries_(), valid_constraint_catalog_entries_(false), txn_(txn) {} @@ -431,14 +432,14 @@ bool TableCatalogEntry::EvictLayout(oid_t layout_id) { * @return false if the constraint already exists in cache */ bool TableCatalogEntry::InsertConstraintCatalogEntry( - std::shared_ptr constraint_object) { + std::shared_ptr constraint_catalog_entry) { // Invalid object - if (!constraint_object - || (constraint_object->GetConstraintOid() == INVALID_OID)) { + if (!constraint_catalog_entry + || (constraint_catalog_entry->GetConstraintOid() == INVALID_OID)) { return false; } - oid_t constraint_oid = constraint_object->GetConstraintOid(); + oid_t constraint_oid = constraint_catalog_entry->GetConstraintOid(); // layout is already present in the cache. if (constraint_catalog_entries_.find(constraint_oid) != constraint_catalog_entries_.end()) { @@ -446,7 +447,8 @@ bool TableCatalogEntry::InsertConstraintCatalogEntry( return false; } - constraint_catalog_entries_.insert(std::make_pair(constraint_oid, constraint_object)); + constraint_catalog_entries_.insert(std::make_pair(constraint_oid, + constraint_catalog_entry)); return true; } @@ -501,19 +503,12 @@ TableCatalogEntry::GetConstraintCatalogEntries(bool cached_only) { */ std::shared_ptr TableCatalogEntry::GetConstraintCatalogEntry(oid_t constraint_oid, bool cached_only){ + GetConstraintCatalogEntries(cached_only); // fetch constraint in case we have not auto it = constraint_catalog_entries_.find(constraint_oid); - if (it != constraint_catalog_entries_.end()) return it->second; - - if (cached_only) { - // cache miss return empty object - return nullptr; - } else { - // cache miss get from pg_table - auto pg_constraint = Catalog::GetInstance() - ->GetSystemCatalogs(database_oid) - ->GetConstraintCatalog(); - return pg_constraint->GetConstraintCatalogEntry(txn_, table_oid, constraint_oid); + if (it != constraint_catalog_entries_.end()) { + return it->second; } + return nullptr; } diff --git a/src/common/internal_types.cpp b/src/common/internal_types.cpp index 8ccea6515f2..3b0c20900df 100644 --- a/src/common/internal_types.cpp +++ b/src/common/internal_types.cpp @@ -2138,6 +2138,9 @@ std::ostream &operator<<(std::ostream &os, const ConstraintType &type) { std::string FKConstrActionTypeToString(FKConstrActionType type) { switch (type) { + case FKConstrActionType::INVALID: { + return ("INVALID"); + } case FKConstrActionType::NOACTION: { return ("NOACTION"); } @@ -2164,7 +2167,9 @@ return "INVALID"; FKConstrActionType StringToFKConstrActionType(const std::string &str){ std::string upper_str = StringUtil::Upper(str); - if (upper_str == "NOACTION") { + if (upper_str == "INVALID") { + return FKConstrActionType::INVALID; + } else if (upper_str == "NOACTION") { return FKConstrActionType::NOACTION; } else if (upper_str == "RESTRICT") { return FKConstrActionType::RESTRICT; @@ -2179,7 +2184,7 @@ FKConstrActionType StringToFKConstrActionType(const std::string &str){ "No FKConstrActionType conversion from string '%s'", upper_str.c_str())); } - return FKConstrActionType::NOACTION; + return FKConstrActionType::INVALID; } diff --git a/src/include/catalog/table_catalog.h b/src/include/catalog/table_catalog.h index 6ce141a0263..f7d373c4d3e 100644 --- a/src/include/catalog/table_catalog.h +++ b/src/include/catalog/table_catalog.h @@ -122,46 +122,49 @@ class TableCatalogEntry { uint32_t version_id; oid_t default_layout_oid; - // Get index objects + // Insert/Evict index catalog entries bool InsertIndexCatalogEntry(std::shared_ptr index_catalog_entry); bool EvictIndexCatalogEntry(oid_t index_oid); bool EvictIndexCatalogEntry(const std::string &index_name); - // Get column objects + // Insert/Evict column catalog entries bool InsertColumnCatalogEntry(std::shared_ptr column_catalog_entry); bool EvictColumnCatalogEntry(oid_t column_id); bool EvictColumnCatalogEntry(const std::string &column_name); - // Insert layout into table object + // Insert layout catalog entry into table catalog entry bool InsertLayout(std::shared_ptr layout); - // Evict layout_id from the table object + // Evict layout_id from the table catalog entry bool EvictLayout(oid_t layout_id); - // Insert constraint object table object + // Insert constraint catalog entry into table catalog entry bool InsertConstraintCatalogEntry( - std::shared_ptr constraint_object); - // Evict constraint_oid from the table object + std::shared_ptr constraint_catalog_entry); + // Evict constraint_oid from the table catalog entry bool EvictConstraintCatalogEntry(oid_t constraint_oid); + void SetValidConstraintCatalogEntries(bool valid = true) { + valid_constraint_catalog_entries_ = valid; + } - // cache for *all* index catalog objects in this table + // cache for *all* index catalog entries in this table std::unordered_map> index_catalog_entries; std::unordered_map> index_catalog_entries_by_name_; bool valid_index_catalog_entries_; - // cache for *all* column catalog objects in this table + // cache for *all* column catalog entries in this table std::unordered_map> column_catalog_entries_; std::unordered_map> column_names_; bool valid_column_catalog_entries_; - // cache for *all* layout objects in the table + // cache for *all* layout catalog entries in the table std::unordered_map> layout_catalog_entries_; bool valid_layout_catalog_entries_; - // cache for *all* layout objects in the table + // cache for *all* constraint catalog entries in the table std::unordered_map> constraint_catalog_entries_; bool valid_constraint_catalog_entries_; diff --git a/src/include/common/internal_types.h b/src/include/common/internal_types.h index fb964aaba8d..b34d2971c70 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -903,11 +903,12 @@ ConstraintType StringToConstraintType(const std::string &str); std::ostream &operator<<(std::ostream &os, const ConstraintType &type); enum class FKConstrActionType { - NOACTION = 0, - RESTRICT = 1, - CASCADE = 2, - SETNULL = 3, - SETDEFAULT = 4 + INVALID = INVALID_TYPE_ID, // invalid + NOACTION = 1, + RESTRICT = 2, + CASCADE = 3, + SETNULL = 4, + SETDEFAULT = 5 }; std::string FKConstrActionTypeToString(FKConstrActionType type); FKConstrActionType StringToFKConstrActionType(const std::string &str); diff --git a/test/catalog/catalog_test.cpp b/test/catalog/catalog_test.cpp index 2b76c94b77c..7a15fa0f177 100644 --- a/test/catalog/catalog_test.cpp +++ b/test/catalog/catalog_test.cpp @@ -713,6 +713,10 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { LOG_DEBUG("Success all constraint creations"); // Check constraint + auto sink_schema = sink_table->GetSchema(); + EXPECT_EQ(false, sink_schema->HasForeignKeys()); + EXPECT_EQ(true, sink_schema->HasPrimary()); + EXPECT_EQ(false, sink_schema->HasUniqueConstraints()); auto constraint_objects = sink_table_object->GetConstraintCatalogEntries(); EXPECT_EQ(1, constraint_objects.size()); for (auto constraint_object_pair : constraint_objects) { @@ -729,13 +733,14 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { } // Check foreign key as sink table - auto fk_sources = sink_table->GetSchema()->GetForeignKeySources(); + EXPECT_EQ(true, sink_schema->HasForeignKeySources()); + auto fk_sources = sink_schema->GetForeignKeySources(); EXPECT_EQ(1, fk_sources.size()); auto fk_source = fk_sources.at(0); EXPECT_EQ(con_table_oid, fk_source->GetTableOid()); EXPECT_EQ(sink_table_oid, fk_source->GetFKSinkTableOid()); - LOG_DEBUG("%s", sink_table->GetSchema()->GetInfo().c_str()); + LOG_DEBUG("%s", sink_schema->GetInfo().c_str()); LOG_DEBUG("Complete check for sink table"); // Single column constraints @@ -760,7 +765,12 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { } } - // Multi-column constraints + // Table constraints + auto con_schema = con_table->GetSchema(); + EXPECT_EQ(true, con_schema->HasForeignKeys()); + EXPECT_EQ(true, con_schema->HasPrimary()); + EXPECT_EQ(true, con_schema->HasUniqueConstraints()); + EXPECT_EQ(false, con_schema->HasForeignKeySources()); constraint_objects = con_table_object->GetConstraintCatalogEntries(); EXPECT_EQ(4, constraint_objects.size()); for (auto constraint_object_pair : constraint_objects) { @@ -816,14 +826,15 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { EXPECT_TRUE(false); } } + con_table_object->GetConstraintCatalogEntries(); + txn_manager.CommitTransaction(txn); - LOG_DEBUG("%s", con_table->GetSchema()->GetInfo().c_str()); + LOG_DEBUG("%s", con_schema->GetInfo().c_str()); LOG_DEBUG("Complete check for constraint table"); // Drop constraint txn = txn_manager.BeginTransaction(); - auto con_schema = con_table->GetSchema(); for (auto not_null_column_id : con_schema->GetNotNullColumns()) { EXPECT_EQ(ResultType::SUCCESS, catalog->DropNotNullConstraint(txn, @@ -846,8 +857,32 @@ TEST_F(CatalogTests, ConstraintCatalogTest) { } txn_manager.CommitTransaction(txn); + LOG_DEBUG("%s", con_schema->GetInfo().c_str()); LOG_DEBUG("Complete drop constraints in constraint table"); + // Check dropping constraints + txn = txn_manager.BeginTransaction(); + con_table_object = catalog->GetTableCatalogEntry(txn, + db_name, + DEFAULT_SCHEMA_NAME, + con_table_name); + EXPECT_EQ(0, con_schema->GetNotNullColumns().size()); + for (oid_t column_id = 0; column_id < con_schema->GetColumnCount(); column_id++) { + EXPECT_EQ(true, con_schema->AllowNull(column_id)); + EXPECT_EQ(false, con_schema->AllowDefault(column_id)); + } + for (auto column_object_pair : con_table_object->GetColumnCatalogEntries()) { + auto column_object = column_object_pair.second; + EXPECT_EQ(false, column_object->IsNotNull()); + EXPECT_EQ(false, column_object->HasDefault()); + } + EXPECT_EQ(false, con_schema->HasForeignKeys()); + EXPECT_EQ(false, con_schema->HasPrimary()); + EXPECT_EQ(false, con_schema->HasUniqueConstraints()); + EXPECT_EQ(false, sink_table->GetSchema()->HasForeignKeySources()); + EXPECT_EQ(0, con_table_object->GetConstraintCatalogEntries().size()); + txn_manager.CommitTransaction(txn); + // Drop database txn = txn_manager.BeginTransaction(); catalog->DropDatabaseWithName(txn, db_name); diff --git a/test/concurrency/testing_transaction_util.cpp b/test/concurrency/testing_transaction_util.cpp index 6366c87597c..ca119c0b563 100644 --- a/test/concurrency/testing_transaction_util.cpp +++ b/test/concurrency/testing_transaction_util.cpp @@ -168,7 +168,7 @@ storage::DataTable *TestingTransactionUtil::CreatePrimaryKeyUniqueKeyTable() { storage::DataTable *TestingTransactionUtil::CreateTable( int num_key, std::string table_name, oid_t database_id, oid_t relation_id, - oid_t index_oid, bool need_primary_index, size_t tuples_per_tilegroup) { + oid_t index_oid, bool need_primary_key, size_t tuples_per_tilegroup) { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); @@ -193,7 +193,7 @@ storage::DataTable *TestingTransactionUtil::CreateTable( auto index_metadata = new index::IndexMetadata( "primary_btree_index", index_oid, relation_id, database_id, - IndexType::BWTREE, need_primary_index ? IndexConstraintType::PRIMARY_KEY + IndexType::BWTREE, need_primary_key ? IndexConstraintType::PRIMARY_KEY : IndexConstraintType::DEFAULT, tuple_schema, key_schema, key_attrs, unique); @@ -203,7 +203,7 @@ storage::DataTable *TestingTransactionUtil::CreateTable( table->AddIndex(pkey_index); // Create primary key constraint on the table - if (need_primary_index) { + if (need_primary_key) { std::shared_ptr constraint( new catalog::Constraint(1000, ConstraintType::PRIMARY, "con_primary", relation_id, key_attrs, index_oid)); diff --git a/test/include/concurrency/testing_transaction_util.h b/test/include/concurrency/testing_transaction_util.h index d7bb919a0f3..d2387f9ee98 100644 --- a/test/include/concurrency/testing_transaction_util.h +++ b/test/include/concurrency/testing_transaction_util.h @@ -122,7 +122,7 @@ class TestingTransactionUtil { int num_key = 10, std::string table_name = "TEST_TABLE", oid_t database_id = CATALOG_DATABASE_OID, oid_t relation_id = TEST_TABLE_OID, oid_t index_oid = 1234, - bool need_primary_index = false, size_t tuples_per_tilegroup = 100); + bool need_primary_key = false, size_t tuples_per_tilegroup = 100); // Create the same table as CreateTable with primary key constraints on id and // unique key constraints on value From c6ecd942fd6001ed38b41e2737d8812add1cdfc5 Mon Sep 17 00:00:00 2001 From: ksaito7 Date: Thu, 28 Jun 2018 18:14:58 -0400 Subject: [PATCH 09/10] Fix DEBUG_INFO argument --- src/catalog/catalog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index ea73e0552fe..927f7c0fb23 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -1075,7 +1075,7 @@ ResultType Catalog::AddForeignKeyConstraint(concurrency::TransactionContext *txn src_table_object->GetTableName().c_str(), catalog_map_[database_oid] ->GetTableCatalog() - ->GetTableObject(sink_table_oid, txn) + ->GetTableCatalogEntry(sink_table_oid, txn) ->GetTableName() .c_str()); @@ -1551,7 +1551,7 @@ ResultType Catalog::DropConstraint(concurrency::TransactionContext *txn, ConstraintTypeToString(constraint_object->GetConstraintType()).c_str(), catalog_map_[database_oid] ->GetTableCatalog() - ->GetTableObject(table_oid, txn) + ->GetTableCatalogEntry(txn, table_oid) ->GetTableName() .c_str()); From ad827a24da529aab279b6ca257b4ad03b442e572 Mon Sep 17 00:00:00 2001 From: ksaito7 Date: Thu, 28 Jun 2018 18:56:27 -0400 Subject: [PATCH 10/10] Fix LOG_TRACE argument --- src/catalog/catalog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 927f7c0fb23..99f58aeb53a 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -1075,7 +1075,7 @@ ResultType Catalog::AddForeignKeyConstraint(concurrency::TransactionContext *txn src_table_object->GetTableName().c_str(), catalog_map_[database_oid] ->GetTableCatalog() - ->GetTableCatalogEntry(sink_table_oid, txn) + ->GetTableCatalogEntry(txn, sink_table_oid) ->GetTableName() .c_str());