From e5c22139219880352074a471161ad41b1f37cd86 Mon Sep 17 00:00:00 2001 From: Matt Butrovich Date: Fri, 6 Jul 2018 17:12:46 -0400 Subject: [PATCH] Revert 1415 (#1453) * Revert "Constraint refactoring (#1415)" This reverts commit 898219f --- src/catalog/abstract_catalog.cpp | 31 +- src/catalog/catalog.cpp | 707 +++------------- src/catalog/column.cpp | 26 +- src/catalog/column_catalog.cpp | 218 ++--- src/catalog/constraint.cpp | 33 +- src/catalog/constraint_catalog.cpp | 428 ---------- src/catalog/database_catalog.cpp | 22 +- src/catalog/index_catalog.cpp | 49 +- src/catalog/layout_catalog.cpp | 28 +- src/catalog/manager.cpp | 1 + src/catalog/multi_constraint.cpp | 39 + src/catalog/schema.cpp | 24 +- src/catalog/schema_catalog.cpp | 26 +- src/catalog/system_catalogs.cpp | 26 +- src/catalog/table_catalog.cpp | 129 +-- src/common/internal_types.cpp | 88 +- src/executor/create_executor.cpp | 201 ++--- src/executor/update_executor.cpp | 3 +- src/include/catalog/catalog.h | 83 +- src/include/catalog/catalog_defaults.h | 36 +- src/include/catalog/column.h | 72 +- src/include/catalog/column_catalog.h | 31 +- src/include/catalog/constraint.h | 115 +-- src/include/catalog/constraint_catalog.h | 156 ---- src/include/catalog/foreign_key.h | 76 ++ src/include/catalog/layout_catalog.h | 3 +- src/include/catalog/multi_constraint.h | 70 ++ src/include/catalog/schema.h | 176 +--- src/include/catalog/system_catalogs.h | 10 - src/include/catalog/table_catalog.h | 40 +- src/include/common/internal_types.h | 27 +- src/include/planner/create_plan.h | 40 +- src/include/storage/abstract_table.h | 10 + src/include/storage/data_table.h | 57 +- 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 | 248 ++++-- src/storage/database.cpp | 11 +- test/brain/query_logger_test.cpp | 6 +- test/catalog/catalog_test.cpp | 413 +--------- test/catalog/constraints_test.cpp | 773 +++++++++--------- test/codegen/testing_codegen_util.cpp | 33 +- test/common/internal_types_test.cpp | 8 +- test/concurrency/testing_transaction_util.cpp | 43 +- test/executor/drop_test.cpp | 2 +- test/executor/testing_executor_util.cpp | 21 +- test/executor/update_test.cpp | 27 +- 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 +- .../concurrency/testing_transaction_util.h | 2 +- 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 | 15 +- test/statistics/testing_stats_util.cpp | 34 +- 61 files changed, 1591 insertions(+), 3415 deletions(-) delete mode 100644 src/catalog/constraint_catalog.cpp create mode 100644 src/catalog/multi_constraint.cpp delete mode 100644 src/include/catalog/constraint_catalog.h create mode 100644 src/include/catalog/foreign_key.h create mode 100644 src/include/catalog/multi_constraint.h diff --git a/src/catalog/abstract_catalog.cpp b/src/catalog/abstract_catalog.cpp index 4ddad1c61ca..5ce2bceaedc 100644 --- a/src/catalog/abstract_catalog.cpp +++ b/src/catalog/abstract_catalog.cpp @@ -29,7 +29,6 @@ #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" @@ -61,24 +60,30 @@ AbstractCatalog::AbstractCatalog(storage::Database *pg_catalog, AbstractCatalog::AbstractCatalog(concurrency::TransactionContext *txn, const std::string &catalog_table_ddl) { - // Execute create catalog table + // get catalog table schema 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)); - executor::CreateExecutor executor(create_plan.get(), context.get()); - - executor.Init(); - executor.Execute(); + 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(txn, + catalog_database_name, + catalog_schema_name, + std::unique_ptr( + catalog_table_schema), + catalog_table_name, + true); // get catalog table oid - auto catalog_table_object = - Catalog::GetInstance()->GetTableCatalogEntry(txn, - create_plan->GetDatabaseName(), - create_plan->GetSchemaName(), - create_plan->GetTableName()); + auto catalog_table_object = Catalog::GetInstance()->GetTableCatalogEntry(txn, + catalog_database_name, + catalog_schema_name, + catalog_table_name); // set catalog_table_ try { diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 99f58aeb53a..b3dcd815ac3 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -13,7 +13,6 @@ #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/index_catalog.h" @@ -233,49 +232,6 @@ void Catalog::BootstrapSystemCatalogs(concurrency::TransactionContext *txn, {TableCatalog::ColumnId::DATABASE_OID}, pool_.get()); - system_catalogs->GetIndexCatalog()->InsertIndex(txn, - CATALOG_SCHEMA_NAME, - LAYOUT_CATALOG_OID, - LAYOUT_CATALOG_PKEY_OID, - LAYOUT_CATALOG_NAME "_pkey", - IndexType::BWTREE, - IndexConstraintType::PRIMARY_KEY, - true, - {LayoutCatalog::ColumnId::TABLE_OID, - LayoutCatalog::ColumnId::LAYOUT_OID}, - pool_.get()); - system_catalogs->GetIndexCatalog()->InsertIndex(txn, - CATALOG_SCHEMA_NAME, - LAYOUT_CATALOG_OID, - LAYOUT_CATALOG_SKEY0_OID, - LAYOUT_CATALOG_NAME "_skey0", - IndexType::BWTREE, - IndexConstraintType::DEFAULT, - true, - {LayoutCatalog::ColumnId::TABLE_OID}, - pool_.get()); - - system_catalogs->GetIndexCatalog()->InsertIndex(txn, - CATALOG_SCHEMA_NAME, - CONSTRAINT_CATALOG_OID, - CONSTRAINT_CATALOG_PKEY_OID, - CONSTRAINT_CATALOG_NAME "_pkey", - IndexType::BWTREE, - IndexConstraintType::PRIMARY_KEY, - true, - {ConstraintCatalog::ColumnId::CONSTRAINT_OID}, - pool_.get()); - system_catalogs->GetIndexCatalog()->InsertIndex(txn, - CATALOG_SCHEMA_NAME, - CONSTRAINT_CATALOG_OID, - CONSTRAINT_CATALOG_SKEY0_OID, - CONSTRAINT_CATALOG_NAME "_skey0", - IndexType::BWTREE, - IndexConstraintType::DEFAULT, - true, - {ConstraintCatalog::ColumnId::TABLE_OID}, - pool_.get()); - // Insert records(default + pg_catalog namespace) into pg_namespace system_catalogs->GetSchemaCatalog()->InsertSchema(txn, CATALOG_SCHEMA_OID, @@ -330,13 +286,6 @@ void Catalog::BootstrapSystemCatalogs(concurrency::TransactionContext *txn, LAYOUT_CATALOG_NAME, ROW_STORE_LAYOUT_OID, pool_.get()); - system_catalogs->GetTableCatalog()->InsertTable(txn, - database_oid, - CATALOG_SCHEMA_NAME, - CONSTRAINT_CATALOG_OID, - CONSTRAINT_CATALOG_NAME, - ROW_STORE_LAYOUT_OID, - pool_.get()); } void Catalog::Bootstrap() { @@ -454,13 +403,11 @@ ResultType Catalog::CreateSchema(concurrency::TransactionContext *txn, } /*@brief create table - * @param txn TransactionContext * @param database_name the database which the table belongs to * @param schema_name name of schema the table belongs to - * @param schema schema, a.k.a metadata of the table * @param table_name name of the table - * @param is_catalog table is built as catalog or not(useful in - * catalog table Initialization) + * @param schema schema, a.k.a metadata of the table + * @param txn TransactionContext * @return TransactionContext ResultType(SUCCESS or FAILURE) */ ResultType Catalog::CreateTable(concurrency::TransactionContext *txn, @@ -541,24 +488,40 @@ ResultType Catalog::CreateTable(concurrency::TransactionContext *txn, table_name, table->GetDefaultLayout()->GetOid(), pool_.get()); - - // Insert column info into each catalog oid_t column_id = 0; for (const auto &column : table->GetSchema()->GetColumns()) { pg_attribute->InsertColumn(txn, table_oid, - column.GetName(), column_id, + column.GetName(), column.GetOffset(), column.GetType(), column.GetLength(), + column.GetConstraints(), column.IsInlined(), - column.IsNotNull(), - column.HasDefault(), - column.GetDefaultValue(), pool_.get()); + + // 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(txn, + database_name, + schema_name, + table_name, + index_name, + {column_id}, + true, + IndexType::BWTREE); + LOG_DEBUG("Added a UNIQUE index on %s in %s.", col_name.c_str(), + table_name.c_str()); + } column_id++; } + CreatePrimaryIndex(txn, + database_object->GetDatabaseOid(), + schema_name, + table_oid); // Create layout as default layout auto pg_layout = @@ -571,15 +534,93 @@ ResultType Catalog::CreateTable(concurrency::TransactionContext *txn, return ResultType::SUCCESS; } -/*@brief create index on table +/*@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(concurrency::TransactionContext *txn, + oid_t database_oid, + const std::string &schema_name, + oid_t table_oid) { + 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 (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(txn, + schema_name, + table_oid, + index_oid, + index_name, + IndexType::BWTREE, + IndexConstraintType::PRIMARY_KEY, + unique_keys, + key_attrs, + pool_.get()); + + LOG_TRACE("Successfully created primary key index '%s' for table '%s'", + index_name.c_str(), table->GetName().c_str()); + + return ResultType::SUCCESS; +} + +/*@brief create index on table * @param database_name the database which the indexed table belongs to * @param schema_name the namespace which the indexed table belongs to * @param table_name name of the table to add index on + * @param index_attr collection of the indexed attribute(column) name * @param index_name name of the table to add index on - * @param key_attrs collection of the indexed attribute(column) name * @param unique_keys index supports duplicate key or not * @param index_type the type of index(default value is BWTREE) + * @param txn TransactionContext + * @param is_catalog index is built on catalog table or not(useful in + * catalog table Initialization) * @return TransactionContext ResultType(SUCCESS or FAILURE) */ ResultType Catalog::CreateIndex(concurrency::TransactionContext *txn, @@ -614,9 +655,6 @@ ResultType Catalog::CreateIndex(concurrency::TransactionContext *txn, 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; @@ -625,7 +663,6 @@ ResultType Catalog::CreateIndex(concurrency::TransactionContext *txn, schema_name, table_object->GetTableOid(), false, - index_oid, index_name, key_attrs, unique_keys, @@ -635,27 +672,11 @@ ResultType Catalog::CreateIndex(concurrency::TransactionContext *txn, return success; } -/*@brief create index on table - * @param txn TransactionContext - * @param database_oid the database which the indexed table belongs to - * @param schema_name the namespace which the indexed table belongs to - * @param table_oid name of the table to add index on - * @param is_catalog index is built on catalog table or not(useful in - * catalog table Initialization) - * @param index_oid oid of the index to be added - * @param index_name index name to be added - * @param key_attrs collection of the indexed attribute(column) name - * @param unique_keys index supports duplicate key or not - * @param index_type the type of index - * @param index_constraint the constraint type of index - * @return TransactionContext ResultType(SUCCESS or FAILURE) - */ ResultType Catalog::CreateIndex(concurrency::TransactionContext *txn, oid_t database_oid, const std::string &schema_name, oid_t table_oid, bool is_catalog, - oid_t index_oid, const std::string &index_name, const std::vector &key_attrs, bool unique_keys, @@ -690,6 +711,8 @@ ResultType Catalog::CreateIndex(concurrency::TransactionContext *txn, // 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); @@ -706,7 +729,6 @@ ResultType Catalog::CreateIndex(concurrency::TransactionContext *txn, // 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(txn, schema_name, table_oid, @@ -767,371 +789,6 @@ std::shared_ptr Catalog::CreateDefaultLayout(concurrency: return new_layout; } -//===--------------------------------------------------------------------===// -// SET FUNCTIONS FOR COLUMN CONSTRAINT -//===--------------------------------------------------------------------===// - -/** - * @brief Set not null constraint for a column - * @param txn TransactionContext - * @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 - * @return ResultType(SUCCESS or FAILURE) - */ -ResultType Catalog::SetNotNullConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - oid_t column_id) { - auto table_object = catalog_map_[database_oid] - ->GetTableCatalog() - ->GetTableCatalogEntry(txn, table_oid); - 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(txn, - table_oid, - column.GetName(), - true); - - // Set not null constraint in the schema - { - 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; -} - -/** - * @brief Set default constraint for a column - * @param txn TransactionContext - * @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 - * @return ResultType(SUCCESS or FAILURE) - */ -ResultType Catalog::SetDefaultConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - oid_t column_id, - const type::Value &default_value) { - auto table_object = catalog_map_[database_oid]->GetTableCatalog() - ->GetTableCatalogEntry(txn, table_oid); - 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(txn, - table_oid, - column.GetName(), - true, - &default_value); - - // Set default constraint in the schema - { - std::lock_guard lock(catalog_mutex); - schema->SetDefaultValue(column_id, default_value); - } - - 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 -//===--------------------------------------------------------------------===// - -/** - * @brief Add a new primary constraint for a table - * @param txn TransactionContext - * @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 - * @return ResultType(SUCCESS or FAILURE) - */ -ResultType Catalog::AddPrimaryKeyConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - const std::vector &column_ids, - const std::string &constraint_name) { - auto table_object = - catalog_map_[database_oid]->GetTableCatalog() - ->GetTableCatalogEntry(txn,table_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(txn, - database_oid, - table_object->GetSchemaName(), - table_oid, - false, - index_oid, - index_name, - column_ids, - true, - IndexType::BWTREE, - IndexConstraintType::PRIMARY_KEY); - - // Insert constraint into pg_constraint - auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); - std::shared_ptr constraint( - new Constraint(pg_constraint->GetNextOid(), - ConstraintType::PRIMARY, - constraint_name, - table_oid, - column_ids, - index_oid)); - pg_constraint->InsertConstraint(txn, constraint, pool_.get()); - - // Add constraint into the schema - { - std::lock_guard lock(catalog_mutex); - schema->AddConstraint(constraint); - } - - LOG_TRACE("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 txn TransactionContext - * @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 - * @return ResultType(SUCCESS or FAILURE) - * note: if add a new foreign key constraint, use AddForeignKeyConstraint - */ -ResultType Catalog::AddUniqueConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - const std::vector &column_ids, - const std::string &constraint_name) { - auto table_object = - catalog_map_[database_oid]->GetTableCatalog() - ->GetTableCatalogEntry(txn, table_oid); - auto schema = storage::StorageManager::GetInstance() - ->GetTableWithOid(database_oid, table_oid) - ->GetSchema(); - - // Create index - std::stringstream index_name(table_object->GetTableName()); - 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(txn, - database_oid, - table_object->GetSchemaName(), - table_oid, - false, - index_oid, - index_name.str(), - column_ids, - true, - IndexType::BWTREE, - IndexConstraintType::UNIQUE); - - // 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(txn, constraint, pool_.get()); - - // Add constraint into the schema - { - std::lock_guard lock(catalog_mutex); - schema->AddConstraint(constraint); - } - - LOG_TRACE("Added a UNIQUE constraint in %s.", - table_object->GetTableName().c_str()); - - return ResultType::SUCCESS; -} - -/** - * @brief Add a new foreign key constraint for a table - * @param txn TransactionContext - * @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 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 - * @return ResultType(SUCCESS or FAILURE) - */ -ResultType Catalog::AddForeignKeyConstraint(concurrency::TransactionContext *txn, - 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) { - 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); - - // Add a non-unique index on the source table if needed - auto src_table_object = - catalog_map_[database_oid]->GetTableCatalog() - ->GetTableCatalogEntry(txn, src_table_oid); - auto src_schema = src_table->GetSchema(); - - 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"; - oid_t index_oid = catalog_map_[database_oid]->GetIndexCatalog()->GetNextOid(); - CreateIndex(txn, - database_oid, - src_table_object->GetSchemaName(), - src_table_oid, - false, - index_oid, - index_name.str(), - src_col_ids, - false, - IndexType::BWTREE, - IndexConstraintType::DEFAULT); - - // Insert constraint into pg_constraint - std::shared_ptr constraint( - 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(txn, constraint, pool_.get()); - - // 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_TRACE("Added a FOREIGN KEY constraint in %s to %s.", - src_table_object->GetTableName().c_str(), - catalog_map_[database_oid] - ->GetTableCatalog() - ->GetTableCatalogEntry(txn, sink_table_oid) - ->GetTableName() - .c_str()); - - return ResultType::SUCCESS; -} - -/** - * @brief Add a new check constraint for a table - * @param txn TransactionContext - * @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 - * @return ResultType(SUCCESS or FAILURE) - * note: if add a new foreign key constraint, use AddForeignKeyConstraint - */ -ResultType Catalog::AddCheckConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - const std::vector &column_ids, - const std::pair &exp, - const std::string &constraint_name) { - auto table_object = - catalog_map_[database_oid]->GetTableCatalog() - ->GetTableCatalogEntry(txn, table_oid); - 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(txn, constraint, pool_.get()); - - // Add constraint into the schema - { - std::lock_guard lock(catalog_mutex); - schema->AddConstraint(constraint); - } - - LOG_TRACE("Added a CHECK constraint in %s.", - table_object->GetTableName().c_str()); - - return ResultType::SUCCESS; -} - //===----------------------------------------------------------------------===// // DROP FUNCTIONS //===----------------------------------------------------------------------===// @@ -1306,11 +963,6 @@ ResultType Catalog::DropTable(concurrency::TransactionContext *txn, table_oid, trigger_lists->Get(i)->GetTriggerName()); - // delete record in pg_constraint - auto pg_constraint = - catalog_map_[database_object->GetDatabaseOid()]->GetConstraintCatalog(); - pg_constraint->DeleteConstraints(txn, table_oid); - // delete index and records pg_index for (auto it : index_objects) DropIndex(txn, database_oid, it.second->GetIndexOid()); @@ -1411,153 +1063,6 @@ ResultType Catalog::DropLayout(concurrency::TransactionContext *txn, return ResultType::SUCCESS; } -/** - * @brief Drop not null constraint for a column - * @param txn TransactionContext - * @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 not null constraint - * @return ResultType(SUCCESS or FAILURE) - */ -ResultType Catalog::DropNotNullConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - oid_t column_id) { - auto table_object = - catalog_map_[database_oid]->GetTableCatalog() - ->GetTableCatalogEntry(txn, table_oid); - 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(txn, - table_oid, - column.GetName(), - false); - - // 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 txn TransactionContext - * @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 - * @return ResultType(SUCCESS or FAILURE) - */ -ResultType Catalog::DropDefaultConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - oid_t column_id) { - auto table_object = - catalog_map_[database_oid]->GetTableCatalog() - ->GetTableCatalogEntry(txn, table_oid); - 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(txn, - table_oid, - column.GetName(), - false, - nullptr); - - // 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 txn TransactionContext - * @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 - * @return ResultType(SUCCESS or FAILURE) - */ -ResultType Catalog::DropConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - oid_t constraint_oid) { - auto pg_constraint = catalog_map_[database_oid]->GetConstraintCatalog(); - auto constraint_object = - pg_constraint->GetConstraintCatalogEntry(txn, - table_oid, - constraint_oid); - - // delete constraint object from pg_constraint - if (!pg_constraint->DeleteConstraint(txn, table_oid, 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(txn, database_oid, constraint_object->GetIndexOid()); - } - - // delete constraint from table - auto storage_manager = storage::StorageManager::GetInstance(); - auto table = storage_manager->GetTableWithOid(database_oid, table_oid); - { - std::lock_guard lock(catalog_mutex); - table->GetSchema()->DropConstraint(constraint_oid); - } - - // delete foreign key info from sink table - if (constraint_object->GetConstraintType() == ConstraintType::FOREIGN) { - auto sink_table = - storage_manager->GetTableWithOid(database_oid, - constraint_object->GetFKSinkTableOid()); - { - std::lock_guard lock(catalog_mutex); - sink_table->GetSchema() - ->DeleteForeignKeySource(constraint_object->GetConstraintOid()); - } - } - - LOG_TRACE( - "Drop a %s constraint in %s.", - ConstraintTypeToString(constraint_object->GetConstraintType()).c_str(), - catalog_map_[database_oid] - ->GetTableCatalog() - ->GetTableCatalogEntry(txn, table_oid) - ->GetTableName() - .c_str()); - - 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 a4c8e2f5acf..3195de231d4 100644 --- a/src/catalog/column.cpp +++ b/src/catalog/column.cpp @@ -45,9 +45,7 @@ void Column::SetInlined() { const std::string Column::GetInfo() const { std::ostringstream os; - os << "Column[" << column_name_ << ", " - << TypeIdToString(column_type_) << ", " - + os << "Column[" << column_name << ", " << TypeIdToString(column_type_) << ", " << "Offset:" << column_offset_ << ", "; if (is_inlined_) { @@ -56,17 +54,19 @@ const std::string Column::GetInfo() const { os << "VarLength:" << variable_length_; } - 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() << "}"; - + if (constraints_.empty() == false) { + os << ", {"; + bool first = true; + for (auto constraint : constraints_) { + if (first) { + first = false; + } else { + os << ", "; + } + os << constraint.GetInfo(); + } + os << "}"; } - os << "]"; return (os.str()); diff --git a/src/catalog/column_catalog.cpp b/src/catalog/column_catalog.cpp index 5bc3a1d7902..6d4e7b717c1 100644 --- a/src/catalog/column_catalog.cpp +++ b/src/catalog/column_catalog.cpp @@ -18,7 +18,6 @@ #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 { @@ -39,22 +38,14 @@ ColumnCatalogEntry::ColumnCatalogEntry(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_primary_(tile->GetValue(tupleId, ColumnCatalog::ColumnId::IS_PRIMARY) + .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()) {} ColumnCatalog::ColumnCatalog(concurrency::TransactionContext *txn, storage::Database *pg_catalog, @@ -82,15 +73,13 @@ ColumnCatalog::ColumnCatalog(concurrency::TransactionContext *txn, for (auto column : catalog_table_->GetSchema()->GetColumns()) { InsertColumn(txn, COLUMN_CATALOG_OID, - column.GetName(), column_id, + column.GetName(), column.GetOffset(), column.GetType(), column.GetLength(), + column.GetConstraints(), column.IsInlined(), - column.IsNotNull(), - column.HasDefault(), - column.GetDefaultValue(), pool); column_id++; } @@ -102,90 +91,82 @@ 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"; + auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.SetNotNull(); + table_id_column.AddConstraint(catalog::Constraint( + ConstraintType::PRIMARY, primary_key_constraint_name)); + table_id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto column_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size_, "column_name", false); - column_name_column.SetNotNull(); + column_name_column.AddConstraint(catalog::Constraint( + ConstraintType::PRIMARY, primary_key_constraint_name)); + column_name_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto column_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "column_id", true); - column_id_column.SetNotNull(); + column_id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto column_offset_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "column_offset", true); - column_offset_column.SetNotNull(); + column_offset_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto column_type_column = catalog::Column( type::TypeId::VARCHAR, max_name_size_, "column_type", false); - column_type_column.SetNotNull(); - + column_type_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto column_length_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "column_length", true); - column_length_column.SetNotNull(); + column_length_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto is_inlined_column = catalog::Column( type::TypeId::BOOLEAN, type::Type::GetTypeSize(type::TypeId::BOOLEAN), "is_inlined", true); - is_inlined_column.SetNotNull(); + is_inlined_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); - auto is_not_null_column = catalog::Column( + auto is_primary_column = catalog::Column( type::TypeId::BOOLEAN, type::Type::GetTypeSize(type::TypeId::BOOLEAN), - "is_not_null", true); - is_not_null_column.SetNotNull(); + "is_primary", true); + is_primary_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); - auto has_default_column = catalog::Column( + auto is_not_null_column = catalog::Column( type::TypeId::BOOLEAN, type::Type::GetTypeSize(type::TypeId::BOOLEAN), - "has_default", true); - has_default_column.SetNotNull(); - - auto default_value_src_column = catalog::Column( - type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), - "default_value_src", false); - - auto default_value_bin_column = catalog::Column( - type::TypeId::VARBINARY, type::Type::GetTypeSize(type::TypeId::VARBINARY), - "default_value_bin", false); + "is_not_null", true); + is_not_null_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); 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})); - - 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)); + is_inlined_column, is_primary_column, is_not_null_column})); return column_catalog_schema; } bool ColumnCatalog::InsertColumn(concurrency::TransactionContext *txn, oid_t table_oid, - const std::string &column_name, oid_t column_id, + const std::string &column_name, oid_t column_offset, type::TypeId column_type, size_t column_length, + const std::vector &constraints, bool is_inlined, - bool is_not_null, - bool is_default, - const std::shared_ptr default_value, type::AbstractPool *pool) { // Create the tuple first std::unique_ptr tuple( @@ -199,8 +180,17 @@ bool ColumnCatalog::InsertColumn(concurrency::TransactionContext *txn, type::ValueFactory::GetVarcharValue(TypeIdToString(column_type), nullptr); auto val5 = type::ValueFactory::GetIntegerValue(column_length); auto val6 = type::ValueFactory::GetBooleanValue(is_inlined); - auto val7 = type::ValueFactory::GetBooleanValue(is_not_null); - auto val8 = type::ValueFactory::GetBooleanValue(is_default); + 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 val7 = type::ValueFactory::GetBooleanValue(is_primary); + auto val8 = type::ValueFactory::GetBooleanValue(is_not_null); tuple->SetValue(ColumnId::TABLE_OID, val0, pool); tuple->SetValue(ColumnId::COLUMN_NAME, val1, pool); @@ -209,22 +199,8 @@ bool ColumnCatalog::InsertColumn(concurrency::TransactionContext *txn, tuple->SetValue(ColumnId::COLUMN_TYPE, val4, pool); 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::HAS_DEFAULT, val8, pool); - - // 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); - - tuple->SetValue(ColumnId::DEFAULT_VALUE_SRC, val9, pool); - tuple->SetValue(ColumnId::DEFAULT_VALUE_BIN, val10, pool); - } + tuple->SetValue(ColumnId::IS_PRIMARY, val7, pool); + tuple->SetValue(ColumnId::IS_NOT_NULL, val8, pool); // Insert the tuple return InsertTuple(txn, std::move(tuple)); @@ -271,91 +247,11 @@ bool ColumnCatalog::DeleteColumns(concurrency::TransactionContext *txn, oid_t ta return DeleteWithIndexScan(txn, index_offset, values); } -bool ColumnCatalog::UpdateNotNullConstraint(concurrency::TransactionContext *txn, - oid_t table_oid, - const std::string &column_name, - bool is_not_null) { - 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->GetTableCatalogEntry(txn, table_oid); - table_object->EvictColumnCatalogEntry(column_name); - - return UpdateWithIndexScan(txn, - index_offset, - scan_values, - update_columns, - update_values); -} - -bool ColumnCatalog::UpdateDefaultConstraint(concurrency::TransactionContext *txn, - oid_t table_oid, - const std::string &column_name, - bool has_default, - const type::Value *default_value) { - 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->GetTableCatalogEntry(txn, table_oid); - table_object->EvictColumnCatalogEntry(column_name); - - return UpdateWithIndexScan(txn, - index_offset, - scan_values, - update_columns, - update_values); -} - -const std::unordered_map> -ColumnCatalog::GetColumnCatalogEntries(concurrency::TransactionContext *txn, - oid_t table_oid) { +const std::unordered_map> +ColumnCatalog::GetColumnCatalogEntries( + concurrency::TransactionContext *txn, + oid_t table_oid) { // try get from cache auto pg_table = Catalog::GetInstance() ->GetSystemCatalogs(database_oid_) diff --git a/src/catalog/constraint.cpp b/src/catalog/constraint.cpp index f1de24cfba6..f9c2e025a9e 100644 --- a/src/catalog/constraint.cpp +++ b/src/catalog/constraint.cpp @@ -20,37 +20,10 @@ namespace catalog { const std::string Constraint::GetInfo() const { std::ostringstream os; os << "Constraint[" << GetName() << ", " - << "OID=" << constraint_oid_ << ", " - << ConstraintTypeToString(constraint_type_) << ", "; + << ConstraintTypeToString(constraint_type_); - os << "Column: ("; - bool first = true; - for (auto col_id : column_ids_) { - if(first) first = false; - else os << ", "; - os << std::to_string(col_id); - } - os << "), "; - - 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() << ")"; + if (GetType() == ConstraintType::CHECK) { + os << ", " << exp_.first << " " << exp_.second.GetInfo(); } os << "]"; return os.str(); diff --git a/src/catalog/constraint_catalog.cpp b/src/catalog/constraint_catalog.cpp deleted file mode 100644 index f780333e700..00000000000 --- a/src/catalog/constraint_catalog.cpp +++ /dev/null @@ -1,428 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Peloton -// -// constraint_catalog.cpp -// -// Identification: src/catalog/constraint_catalog.cpp -// -// Copyright (c) 2015-17, Carnegie Mellon University Database Group -// -//===----------------------------------------------------------------------===// - -#include "catalog/constraint_catalog.h" - -#include -#include - -#include "catalog/catalog.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 { - -ConstraintCatalogEntry::ConstraintCatalogEntry(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: - // 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::EXCLUSION: - default: - LOG_ERROR("Invalid Constraint type from pg_constraint: %s", - ConstraintTypeToString(constraint_type_).c_str()); - break; - } -} - -ConstraintCatalog::ConstraintCatalog( - UNUSED_ATTRIBUTE concurrency::TransactionContext *txn, - storage::Database *pg_catalog, UNUSED_ATTRIBUTE type::AbstractPool *pool) - : AbstractCatalog(pg_catalog, - InitializeSchema().release(), - CONSTRAINT_CATALOG_OID, - CONSTRAINT_CATALOG_NAME) { - // Add indexes for pg_constraint - AddIndex(CONSTRAINT_CATALOG_NAME "_pkey", - CONSTRAINT_CATALOG_PKEY_OID, - {ColumnId::CONSTRAINT_OID}, - IndexConstraintType::PRIMARY_KEY); - AddIndex(CONSTRAINT_CATALOG_NAME "_skey0", - CONSTRAINT_CATALOG_SKEY0_OID, - {ColumnId::TABLE_OID}, - IndexConstraintType::DEFAULT); -} - -ConstraintCatalog::~ConstraintCatalog() {} - -/*@brief private function for initialize schema of pg_constraint - * @return unqiue pointer to schema - */ -std::unique_ptr ConstraintCatalog::InitializeSchema() { - auto constraint_oid_column = catalog::Column( - type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), - "constraint_oid", true); - constraint_oid_column.SetNotNull(); - - auto constraint_name_column = catalog::Column( - type::TypeId::VARCHAR, max_name_size_, "constraint_name_", false); - constraint_name_column.SetNotNull(); - - auto constraint_type_column = catalog::Column( - type::TypeId::VARCHAR, max_name_size_, "constraint_type", false); - 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.SetNotNull(); - - auto column_ids_column = catalog::Column( - type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), - "column_ids", false); - 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.SetNotNull(); - - 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 check_exp_src_column = catalog::Column( - type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), - "check_exp_src", false); - - auto check_exp_bin_column = catalog::Column( - 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})); - - 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, FOREIGN KEY, UNIQUE or CHECK constraint - * @param txn TransactionContext for adding the constraint. - * @param constraint to be inserted into pg_constraint - * @param pool to allocate memory for the column_map column. - * @return true on success. - */ -bool ConstraintCatalog::InsertConstraint(concurrency::TransactionContext *txn, - const std::shared_ptr constraint, - type::AbstractPool *pool) { - // 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(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); - 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::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::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(txn, std::move(tuple)); -} - -/* @brief delete all constraint records from the same table - * this function is useful when calling DropTable - * @param txn TransactionContext - * @param table_oid - * @return a vector of table oid - */ -bool ConstraintCatalog::DeleteConstraints(concurrency::TransactionContext *txn, - oid_t table_oid) { - 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 constraints from cache - auto pg_table = Catalog::GetInstance() - ->GetSystemCatalogs(database_oid_) - ->GetTableCatalog(); - auto table_object = pg_table->GetTableCatalogEntry(txn, table_oid); - table_object->EvictAllConstraintCatalogEntries(); - - return DeleteWithIndexScan(txn, index_offset, values); -} - -/** @brief Delete a constraint from the pg_constraint table. - * @param txn TransactionContext for deleting the constraint. - * @param table_oid oid of the table to which the old constraint belongs. - * @param constraint_oid oid of the constraint to be deleted. - * @return true on success. - */ -bool ConstraintCatalog::DeleteConstraint(concurrency::TransactionContext *txn, - oid_t table_oid, - oid_t constraint_oid) { - oid_t index_offset = IndexId::PRIMARY_KEY; // Index of constraint_oid - std::vector values; - values.push_back(type::ValueFactory::GetIntegerValue(constraint_oid).Copy()); - - // delete constraint from cache - auto pg_table = Catalog::GetInstance() - ->GetSystemCatalogs(database_oid_) - ->GetTableCatalog(); - auto table_object = pg_table->GetTableCatalogEntry(txn, table_oid); - table_object->EvictConstraintCatalogEntry(constraint_oid); - - return DeleteWithIndexScan(txn, index_offset, values); -} - -/** @brief Get all constraint objects correponding to a table - * from the pg_constraint. - * @param txn TransactionContext for getting the constraints. - * @param table_oid oid of the table to fetch all constraints. - * @return unordered_map containing a constraint_oid -> - * constraint object mapping. - */ -const std::unordered_map> -ConstraintCatalog::GetConstraintCatalogEntries(concurrency::TransactionContext *txn, - oid_t table_oid) { - // try get from cache - auto pg_table = Catalog::GetInstance() - ->GetSystemCatalogs(database_oid_) - ->GetTableCatalog(); - auto table_object = pg_table->GetTableCatalogEntry(txn, table_oid); - PELOTON_ASSERT(table_object && table_object->GetTableOid() == table_oid); - - auto constraint_objects = table_object->GetConstraintCatalogEntries(true); - if (constraint_objects.size() != 0) return constraint_objects; - - // 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; - values.push_back(type::ValueFactory::GetIntegerValue(table_oid).Copy()); - - auto result_tiles = - GetResultWithIndexScan(txn, column_ids, index_offset, values); - - for (auto &tile : (*result_tiles)) { - for (auto tuple_id : *tile) { - auto constraint_object = - std::make_shared(tile.get(), tuple_id); - table_object->InsertConstraintCatalogEntry(constraint_object); - } - } - - table_object->SetValidConstraintCatalogEntries(true); - return table_object->GetConstraintCatalogEntries(); -} - -/** @brief Get the constraint object by constraint_oid from - * the pg_constraint. - * @param txn TransactionContext for getting the constraint. - * @param table_oid oid of the table to fetch the constraint. - * @param constraint_oid oid of the constraint being queried. - * @return shared_ptr constraint object to the constraint_oid if found. - * nullptr otherwise. - */ -const std::shared_ptr -ConstraintCatalog::GetConstraintCatalogEntry(concurrency::TransactionContext *txn, - oid_t table_oid, - oid_t constraint_oid) { - // try get from cache - auto pg_table = Catalog::GetInstance() - ->GetSystemCatalogs(database_oid_) - ->GetTableCatalog(); - auto table_object = pg_table->GetTableCatalogEntry(txn, table_oid); - PELOTON_ASSERT(table_object && table_object->GetTableOid() == table_oid); - - auto constraint_object = - table_object->GetConstraintCatalogEntry(constraint_oid, true); - if (constraint_object != nullptr) return constraint_object; - - // 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; - values.push_back(type::ValueFactory::GetIntegerValue(constraint_oid).Copy()); - - auto result_tiles = - GetResultWithIndexScan(txn, column_ids, index_offset, values); - - if (result_tiles->size() == 1 && (*result_tiles)[0]->GetTupleCount() == 1) { - auto constraint_object = - std::make_shared((*result_tiles)[0].get()); - table_object->InsertConstraintCatalogEntry(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 d869b20654d..555e8c9d7d6 100644 --- a/src/catalog/database_catalog.cpp +++ b/src/catalog/database_catalog.cpp @@ -276,28 +276,24 @@ 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"; + auto database_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "database_oid", true); - database_id_column.SetNotNull(); + database_id_column.AddConstraint(catalog::Constraint( + ConstraintType::PRIMARY, primary_key_constraint_name)); + database_id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto database_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size_, "database_name", false); - database_name_column.SetNotNull(); + database_name_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); 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 69a2633ed44..eaab5f3cfa7 100644 --- a/src/catalog/index_catalog.cpp +++ b/src/catalog/index_catalog.cpp @@ -64,15 +64,15 @@ IndexCatalog::IndexCatalog(concurrency::TransactionContext *, // Add indexes for pg_index AddIndex(INDEX_CATALOG_NAME "_pkey", INDEX_CATALOG_PKEY_OID, - {ColumnId::INDEX_OID}, + {0}, IndexConstraintType::PRIMARY_KEY); AddIndex(INDEX_CATALOG_NAME "_skey0", INDEX_CATALOG_SKEY0_OID, - {ColumnId::INDEX_NAME, ColumnId::SCHEMA_NAME}, + {1, 3}, IndexConstraintType::UNIQUE); AddIndex(INDEX_CATALOG_NAME "_skey1", INDEX_CATALOG_SKEY1_OID, - {ColumnId::TABLE_OID}, + {2}, IndexConstraintType::DEFAULT); } @@ -82,60 +82,59 @@ 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"; + auto index_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "index_oid", true); - index_id_column.SetNotNull(); + index_id_column.AddConstraint(catalog::Constraint( + ConstraintType::PRIMARY, primary_key_constraint_name)); + index_id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto index_name_column = catalog::Column(type::TypeId::VARCHAR, max_name_size_, "index_name", false); - index_name_column.SetNotNull(); + index_name_column.AddConstraint( + catalog::Constraint(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.SetNotNull(); + table_id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto schema_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size_, "schema_name", false); - schema_name_column.SetNotNull(); - + schema_name_column.AddConstraint( + catalog::Constraint(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.SetNotNull(); + index_type_column.AddConstraint( + catalog::Constraint(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.SetNotNull(); + index_constraint_column.AddConstraint( + catalog::Constraint(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.SetNotNull(); + unique_keys.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto indexed_attributes_column = catalog::Column( type::TypeId::VARCHAR, max_name_size_, "indexed_attributes", false); - indexed_attributes_column.SetNotNull(); - - + indexed_attributes_column.AddConstraint( + catalog::Constraint(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, 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 4d5ac563dde..8db442a03e0 100644 --- a/src/catalog/layout_catalog.cpp +++ b/src/catalog/layout_catalog.cpp @@ -50,36 +50,42 @@ 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( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.SetNotNull(); + table_id_column.AddConstraint(catalog::Constraint( + ConstraintType::PRIMARY, primary_key_constraint_name)); + table_id_column.AddConstraint( + catalog::Constraint(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.SetNotNull(); + layout_oid_column.AddConstraint(catalog::Constraint( + ConstraintType::PRIMARY, primary_key_constraint_name)); + layout_oid_column.AddConstraint( + catalog::Constraint(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.SetNotNull(); + num_columns_column.AddConstraint( + catalog::Constraint(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.SetNotNull(); + column_map_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); - std::unique_ptr layout_catalog_schema( + std::unique_ptr column_catalog_schema( new catalog::Schema({table_id_column, layout_oid_column, 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)); - - return layout_catalog_schema; + return column_catalog_schema; } /** @brief Insert a layout into the pg_layout table. diff --git a/src/catalog/manager.cpp b/src/catalog/manager.cpp index a683d36843e..7c17c53d7bc 100644 --- a/src/catalog/manager.cpp +++ b/src/catalog/manager.cpp @@ -13,6 +13,7 @@ #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 new file mode 100644 index 00000000000..d1e4e3d9817 --- /dev/null +++ b/src/catalog/multi_constraint.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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 3024ef0a1c3..66f557f2532 100644 --- a/src/catalog/schema.cpp +++ b/src/catalog/schema.cpp @@ -76,14 +76,10 @@ Schema::Schema(const std::vector &columns) CreateTupleSchema(column_types, column_lengths, column_names, is_inlined); - // Set constraints + // Add 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())); - } + for (auto constraint : columns[column_itr].GetConstraints()) + AddConstraint(column_itr, constraint); } } @@ -296,20 +292,6 @@ 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 d93f2c0f4b7..815c6e467a6 100644 --- a/src/catalog/schema_catalog.cpp +++ b/src/catalog/schema_catalog.cpp @@ -42,11 +42,11 @@ SchemaCatalog::SchemaCatalog(concurrency::TransactionContext *, // Add indexes for pg_namespace AddIndex(SCHEMA_CATALOG_NAME "_pkey", SCHEMA_CATALOG_PKEY_OID, - {ColumnId::SCHEMA_OID}, + {0}, IndexConstraintType::PRIMARY_KEY); AddIndex(SCHEMA_CATALOG_NAME "_skey0", SCHEMA_CATALOG_SKEY0_OID, - {ColumnId::SCHEMA_NAME}, + {1}, IndexConstraintType::UNIQUE); } @@ -56,28 +56,24 @@ 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"; + auto schema_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "schema_oid", true); - schema_id_column.SetNotNull(); + schema_id_column.AddConstraint(catalog::Constraint( + ConstraintType::PRIMARY, primary_key_constraint_name)); + schema_id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto schema_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size_, "schema_name", false); - schema_name_column.SetNotNull(); + schema_name_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); 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 7d9267abfa9..7e92755c001 100644 --- a/src/catalog/system_catalogs.cpp +++ b/src/catalog/system_catalogs.cpp @@ -35,48 +35,40 @@ SystemCatalogs::SystemCatalogs(concurrency::TransactionContext *txn, pg_index_metrics_(nullptr), pg_query_metrics_(nullptr) { oid_t database_oid = database->GetOid(); - pg_attribute_ = new ColumnCatalog(txn, database, pool); pg_namespace_ = new SchemaCatalog(txn, database, pool); pg_table_ = new TableCatalog(txn, database, pool); pg_index_ = new IndexCatalog(txn, database, pool); pg_layout_ = new LayoutCatalog(txn, database, pool); - pg_constraint_ = new ConstraintCatalog(txn, database, pool); // 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, CONSTRAINT_CATALOG_OID}}; + {database_oid, LAYOUT_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 : schema->GetColumns()) { + for (auto column : + storage::StorageManager::GetInstance() + ->GetTableWithOid(shared_tables[i].first, shared_tables[i].second) + ->GetSchema() + ->GetColumns()) { pg_attribute_->InsertColumn(txn, shared_tables[i].second, - column.GetName(), column_id, + column.GetName(), column.GetOffset(), column.GetType(), column.GetLength(), + column.GetConstraints(), column.IsInlined(), - column.IsNotNull(), - column.HasDefault(), - column.GetDefaultValue(), pool); column_id++; } - for (auto constraint : schema->GetConstraints()) { - pg_constraint_->InsertConstraint(txn, constraint.second, pool); - } } } @@ -86,7 +78,6 @@ 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_; @@ -128,7 +119,6 @@ void SystemCatalogs::Bootstrap(concurrency::TransactionContext *txn, 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_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 14cdd46c7ef..8031fdd961e 100644 --- a/src/catalog/table_catalog.cpp +++ b/src/catalog/table_catalog.cpp @@ -16,7 +16,6 @@ #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" @@ -51,8 +50,6 @@ 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) {} /* @brief insert index catalog object into cache @@ -333,15 +330,15 @@ TableCatalog::TableCatalog(concurrency::TransactionContext *, // Add indexes for pg_namespace AddIndex(TABLE_CATALOG_NAME "_pkey", TABLE_CATALOG_PKEY_OID, - {ColumnId::TABLE_OID}, + {0}, IndexConstraintType::PRIMARY_KEY); AddIndex(TABLE_CATALOG_NAME "_skey0", TABLE_CATALOG_SKEY0_OID, - {ColumnId::TABLE_NAME, ColumnId::SCHEMA_NAME}, + {1, 2}, IndexConstraintType::UNIQUE); AddIndex(TABLE_CATALOG_NAME "_skey1", TABLE_CATALOG_SKEY1_OID, - {ColumnId::DATABASE_OID}, + {3}, IndexConstraintType::DEFAULT); } @@ -426,141 +423,55 @@ bool TableCatalogEntry::EvictLayout(oid_t layout_id) { return true; } - -/** @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 TableCatalogEntry::InsertConstraintCatalogEntry( - std::shared_ptr constraint_catalog_entry) { - // Invalid object - if (!constraint_catalog_entry - || (constraint_catalog_entry->GetConstraintOid() == INVALID_OID)) { - return false; - } - - 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()) { - LOG_DEBUG("Constraint Object %u already exists in cache!", constraint_oid); - return false; - } - - constraint_catalog_entries_.insert(std::make_pair(constraint_oid, - constraint_catalog_entry)); - return true; -} - - -/** @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 TableCatalogEntry::EvictConstraintCatalogEntry(oid_t constraint_oid) { - if (!valid_constraint_catalog_entries_) return false; - - // find the constraint catalog entry from the cache - auto it = constraint_catalog_entries_.find(constraint_oid); - if (it == constraint_catalog_entries_.end()) { - return false; // constraint_oid not found in cache - } - - auto constraint_object = it->second; - PELOTON_ASSERT(constraint_object); - constraint_catalog_entries_.erase(it); - return true; -} - -/** @brief evict all constraint catalog entries from cache. */ -void TableCatalogEntry::EvictAllConstraintCatalogEntries() { - constraint_catalog_entries_.clear(); - valid_constraint_catalog_entries_ = false; -} - -/** @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 constraints. - * @return Map from constraint_oid to cached constraint object. - */ -std::unordered_map> -TableCatalogEntry::GetConstraintCatalogEntries(bool cached_only) { - if (!valid_constraint_catalog_entries_ && !cached_only) { - // get constraint catalog objects from pg_constraint - auto pg_constraint = Catalog::GetInstance() - ->GetSystemCatalogs(database_oid) - ->GetConstraintCatalog(); - pg_constraint->GetConstraintCatalogEntries(txn_, table_oid); - valid_constraint_catalog_entries_ = true; - } - return constraint_catalog_entries_; -} - -/** @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. - * @return Constraint catalog object of corresponding to the oid if present. - */ -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; - } - return nullptr; -} - - TableCatalog::~TableCatalog() {} /*@brief private function for initialize schema of pg_table * @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"; + auto table_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "table_oid", true); - table_id_column.SetNotNull(); + table_id_column.AddConstraint(catalog::Constraint( + ConstraintType::PRIMARY, primary_key_constraint_name)); + table_id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto table_name_column = catalog::Column(type::TypeId::VARCHAR, max_name_size_, "table_name", false); - table_name_column.SetNotNull(); + table_name_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto schema_name_column = catalog::Column( type::TypeId::VARCHAR, max_name_size_, "schema_name", false); - schema_name_column.SetNotNull(); - + schema_name_column.AddConstraint( + catalog::Constraint(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.SetNotNull(); + database_id_column.AddConstraint( + catalog::Constraint(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.SetNotNull(); + version_id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); auto default_layout_id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "default_layout_oid", true); - default_layout_id_column.SetNotNull(); + default_layout_id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, not_null_constraint_name)); 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 3b0c20900df..855f7ef2d9b 100644 --- a/src/common/internal_types.cpp +++ b/src/common/internal_types.cpp @@ -2082,6 +2082,15 @@ 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"); } @@ -2110,6 +2119,12 @@ 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") { @@ -2132,67 +2147,6 @@ 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::INVALID: { - return ("INVALID"); - } - 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 == "INVALID") { - return FKConstrActionType::INVALID; - } else 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::INVALID; -} - - -std::ostream &operator<<(std::ostream &os, const FKConstrActionType &type) { - os << FKConstrActionTypeToString(type); - return os; -} - //===--------------------------------------------------------------------===// // SetOpType - String Utilities //===--------------------------------------------------------------------===// @@ -2828,6 +2782,18 @@ 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 9bd21ddaceb..bbd3e773d43 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -13,6 +13,7 @@ #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" @@ -129,130 +130,89 @@ 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(current_txn, - database_name, - schema_name, - table_name); - // 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()); - - // Create the catalog object and shove it into the table - catalog->AddPrimaryKeyConstraint(current_txn, - source_table->GetDatabaseOid(), - source_table->GetOid(), - col_ids, - pk.constraint_name); - } - // 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); + // 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(current_txn, + database_name, + schema_name, + table_name); + + for (auto fk : node.GetForeignKeys()) { + auto sink_table = catalog->GetTableWithName(current_txn, + database_name, + schema_name, + fk.sink_table_name); + // 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 + 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(current_txn, + database_name, + schema_name, + table_name, + index_name, + source_col_ids, + false, + IndexType::BWTREE); + count++; + +#ifdef LOG_DEBUG_ENABLED + 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()); } - 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(current_txn, - source_table->GetDatabaseOid(), - source_table->GetOid(), - col_ids, - unique.constraint_name); - } - - // Add the foreign key constraint - for (auto fk : node.GetForeignKeys()) { - auto sink_table = catalog->GetTableWithName(current_txn, - database_name, - schema_name, - fk.sink_table_name); - // 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); + for (auto c : fk.foreign_key_sinks) { + LOG_DEBUG("FK sink col name: %s\n", c.c_str()); } - 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(current_txn, - source_table->GetDatabaseOid(), - source_table->GetOid(), - source_col_ids, - sink_table->GetOid(), - sink_col_ids, - fk.upd_action, - fk.del_action, - fk.constraint_name); - } - - // 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); - } - col_ids.push_back(col_id); +#endif } - PELOTON_ASSERT(col_ids.size() == check.check_cols.size()); - - // Create the catalog object and shove it into the table - catalog->AddCheckConstraint(current_txn, - source_table->GetDatabaseOid(), - source_table->GetOid(), - col_ids, check.exp, - check.constraint_name); } - } else if (current_txn->GetResult() == ResultType::FAILURE) { LOG_TRACE("Creating table failed!"); } else { @@ -311,7 +271,8 @@ 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/executor/update_executor.cpp b/src/executor/update_executor.cpp index 0c80039fc54..f387e674974 100644 --- a/src/executor/update_executor.cpp +++ b/src/executor/update_executor.cpp @@ -23,6 +23,7 @@ #include "storage/tile_group_header.h" #include "storage/tile.h" #include "storage/storage_manager.h" +#include "catalog/foreign_key.h" namespace peloton { namespace executor { @@ -118,7 +119,7 @@ bool UpdateExecutor::PerformUpdatePrimaryKey( } // Check the source table of any foreign key constraint - if (target_table_->GetSchema()->HasForeignKeySources()) { + if (target_table_->GetForeignKeySrcCount() > 0) { 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 03cc2a1abbb..5940f162864 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -20,7 +20,6 @@ namespace peloton { namespace catalog { -class Constraint; class Schema; class DatabaseCatalogEntry; class TableCatalogEntry; @@ -125,14 +124,12 @@ class Catalog { const std::string &schema_name, oid_t table_oid, bool is_catalog, - oid_t index_oid, const std::string &index_name, const std::vector &key_attrs, bool unique_keys, IndexType index_type, IndexConstraintType index_constraint); - /** * @brief create a new layout for a table * @param database_oid database to which the table belongs to @@ -162,60 +159,6 @@ class Catalog { oid_t table_oid, const column_map_type &column_map); - //===--------------------------------------------------------------------===// - // SET FUNCTIONS FOR COLUMN CONSTRAINT - //===--------------------------------------------------------------------===// - - // Set not null constraint for a column - ResultType SetNotNullConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - oid_t column_id); - - // Set default constraint for a column - ResultType SetDefaultConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - oid_t column_id, - const type::Value &default_value); - - //===--------------------------------------------------------------------===// - // ADD FUNCTIONS FOR TABLE CONSTRAINT - //===--------------------------------------------------------------------===// - - // Add a new primary constraint for a table - ResultType AddPrimaryKeyConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - const std::vector &column_ids, - const std::string &constraint_name); - - // Add a new unique constraint for a table - ResultType AddUniqueConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - const std::vector &column_ids, - const std::string &constraint_name); - - // Add a new foreign key constraint for a table - ResultType AddForeignKeyConstraint(concurrency::TransactionContext *txn, - 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); - - // Add a new check constraint for a table - ResultType AddCheckConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - const std::vector &column_ids, - const std::pair &exp, - const std::string &constraint_name); - //===--------------------------------------------------------------------===// // DROP FUNCTIONS //===--------------------------------------------------------------------===// @@ -260,25 +203,6 @@ class Catalog { oid_t database_oid, oid_t table_oid, oid_t layout_oid); - - // Drop not null constraint for a column - ResultType DropNotNullConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - oid_t column_id); - - // Drop default constraint for a column - ResultType DropDefaultConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - oid_t column_id); - - // Drop constraint for a table - ResultType DropConstraint(concurrency::TransactionContext *txn, - oid_t database_oid, - oid_t table_oid, - oid_t constraint_oid); - //===--------------------------------------------------------------------===// // GET WITH NAME - CHECK FROM CATALOG TABLES, USING TRANSACTION //===--------------------------------------------------------------------===// @@ -372,6 +296,13 @@ class Catalog { void BootstrapSystemCatalogs(concurrency::TransactionContext *txn, storage::Database *database); + // Create the primary key index for a table, don't call this function outside + // catalog.cpp + ResultType CreatePrimaryIndex(concurrency::TransactionContext *txn, + oid_t database_oid, + const std::string &schema_name, + oid_t table_oid); + // The pool for new varlen tuple fields std::unique_ptr pool_; std::mutex catalog_mutex; diff --git a/src/include/catalog/catalog_defaults.h b/src/include/catalog/catalog_defaults.h index 4a3a5bcd1b2..d8afd1a16d6 100644 --- a/src/include/catalog/catalog_defaults.h +++ b/src/include/catalog/catalog_defaults.h @@ -33,12 +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 OID_FOR_USER_OFFSET 10000 -#define CATALOG_TABLES_COUNT 10 +#define CATALOG_TABLES_COUNT 9 // Oid mask for each type #define DATABASE_OID_MASK (static_cast(catalog::CatalogType::DATABASE)) @@ -48,7 +47,6 @@ 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) @@ -71,7 +69,6 @@ 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) @@ -100,36 +97,6 @@ namespace catalog { #define LAYOUT_CATALOG_PKEY_OID (13 | INDEX_OID_MASK) #define LAYOUT_CATALOG_SKEY0_OID (14 | INDEX_OID_MASK) -// 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 @@ -143,7 +110,6 @@ 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 7aa0fd13192..a8741247648 100644 --- a/src/include/catalog/column.h +++ b/src/include/catalog/column.h @@ -36,7 +36,7 @@ class Column : public Printable { 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_name(column_name), column_type_(value_type), fixed_length_(INVALID_OID), is_inlined_(is_inlined), @@ -61,52 +61,47 @@ class Column : public Printable { // Set the appropriate column length void SetLength(size_t column_length); - inline oid_t GetOffset() const { return column_offset_; } + oid_t GetOffset() const { return column_offset_; } - inline std::string GetName() const { return column_name_; } + std::string GetName() const { return column_name; } - inline size_t GetLength() const { + size_t GetLength() const { if (is_inlined_) return fixed_length_; else return variable_length_; } - inline size_t GetFixedLength() const { return fixed_length_; } + size_t GetFixedLength() const { return fixed_length_; } - inline size_t GetVariableLength() const { return variable_length_; } + size_t GetVariableLength() const { return variable_length_; } inline type::TypeId GetType() const { return column_type_; } inline bool IsInlined() const { return is_inlined_; } - // Constraint check functions for NOT NULL and DEFAULT - inline bool IsNotNull() const { return is_not_null_; } + inline bool IsPrimary() const { return is_primary_; } - inline bool HasDefault() const { return has_default_; } + inline bool IsUnique() const { return is_unique_; } - // Manage NOT NULL constraint - inline void SetNotNull() { is_not_null_ = true; } - - inline void ClearNotNull() { is_not_null_ = false; } - - // Manage DEFAULT constraint - inline void SetDefaultValue(const type::Value &value) { - if (default_value_.get() != nullptr) { - return; + // Add a constraint to the column + void AddConstraint(const catalog::Constraint &constraint) { + if (constraint.GetType() == ConstraintType::DEFAULT) { + // Add the default constraint to the front + constraints_.insert(constraints_.begin(), constraint); + } else { + constraints_.push_back(constraint); } - default_value_.reset(new type::Value(value)); - has_default_ = true; - } - inline std::shared_ptr GetDefaultValue() const { - return default_value_; + if (constraint.GetType() == ConstraintType::PRIMARY) { + is_primary_ = true; + } + if (constraint.GetType() == ConstraintType::UNIQUE) { + is_unique_ = true; + } } - inline void ClearDefaultValue() { - default_value_.reset(); - has_default_ = false; - } + const std::vector &GetConstraints() const { return constraints_; } hash_t Hash() const { hash_t hash = HashUtil::Hash(&column_type_); @@ -115,8 +110,7 @@ class Column : public Printable { // 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; @@ -127,14 +121,14 @@ 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; @@ -149,17 +143,17 @@ class Column : public Printable { // is the column inlined ? bool is_inlined_ = false; - // is the column allowed null - bool is_not_null_ = false; - - // does the column have the default value - bool has_default_ = false; + // is the column contained the primary key? + bool is_primary_ = false; - // default value - std::shared_ptr default_value_; + // is the column unique + bool is_unique_ = false; // 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 72b14a052f8..490855822f1 100644 --- a/src/include/catalog/column_catalog.h +++ b/src/include/catalog/column_catalog.h @@ -49,9 +49,8 @@ class ColumnCatalogEntry { 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,9 +61,8 @@ class ColumnCatalogEntry { type::TypeId column_type_; size_t column_length_; bool is_inlined_; + bool is_primary_; bool is_not_null_; - bool has_default_; - type::Value default_value_; }; class ColumnCatalog : public AbstractCatalog { @@ -89,15 +87,13 @@ class ColumnCatalog : public AbstractCatalog { //===--------------------------------------------------------------------===// bool InsertColumn(concurrency::TransactionContext *txn, oid_t table_oid, - const std::string &column_name, oid_t column_id, + const std::string &column_name, oid_t column_offset, type::TypeId column_type, size_t column_length, + const std::vector &constraints, bool is_inlined, - bool is_not_null, - bool is_default, - const std::shared_ptr default_value, type::AbstractPool *pool); bool DeleteColumn(concurrency::TransactionContext *txn, @@ -106,17 +102,6 @@ class ColumnCatalog : public AbstractCatalog { bool DeleteColumns(concurrency::TransactionContext *txn, oid_t table_oid); - bool UpdateNotNullConstraint(concurrency::TransactionContext *txn, - oid_t table_oid, - const std::string &column_name, - bool is_not_null); - - bool UpdateDefaultConstraint(concurrency::TransactionContext *txn, - oid_t table_oid, - const std::string &column_name, - bool has_default, - const type::Value *default_value); - private: //===--------------------------------------------------------------------===// // Read Related API(only called within table catalog object) @@ -135,13 +120,11 @@ class ColumnCatalog : public AbstractCatalog { COLUMN_TYPE = 4, COLUMN_LENGTH = 5, IS_INLINED = 6, - IS_NOT_NULL = 7, - HAS_DEFAULT = 8, - DEFAULT_VALUE_SRC = 9, - DEFAULT_VALUE_BIN = 10, + IS_PRIMARY = 7, + IS_NOT_NULL = 8, // Add new columns here in creation order }; - std::vector all_column_ids_ = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + 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 72c5076a1ba..7f67b1f78b6 100644 --- a/src/include/catalog/constraint.h +++ b/src/include/catalog/constraint.h @@ -30,108 +30,79 @@ namespace catalog { class Constraint : public Printable { public: - // 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) {} + Constraint(ConstraintType type, std::string constraint_name) + : constraint_type_(type), constraint_name_(std::move(constraint_name)) {} + Constraint(ConstraintType type, std::string constraint_name, + std::string check_cmd) + : constraint_type_(type), + constraint_name_(std::move(constraint_name)), + check_cmd_(std::move(check_cmd)) {} //===--------------------------------------------------------------------===// // ACCESSORS //===--------------------------------------------------------------------===// - // Set oid for catalog - void SetConstraintOid(oid_t oid) { constraint_oid_ = oid; } + ConstraintType GetType() const { return constraint_type_; } - inline oid_t GetConstraintOid() const { return constraint_oid_; } + std::pair GetCheckExpression() { return exp_; } - inline ConstraintType GetType() const { return constraint_type_; } + // Offset into the list of "reference tables" in the Table. + void SetForeignKeyListOffset(oid_t offset) { fk_list_offset_ = offset; } - // Get the table oid - inline oid_t GetTableOid() const { return table_oid_; } + // Offset into the list of "unique indices" in the Table. + void SetUniqueIndexOffset(oid_t offset) { + unique_index_list_offset_ = offset; + } - // Get the column ids - inline const std::vector &GetColumnIds() const { return column_ids_; } + // 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 - inline oid_t GetIndexOid() const { return index_oid_; } - - inline std::string GetName() const { return constraint_name_; } + std::string GetName() const { return constraint_name_; } // Get a string representation for debugging const std::string GetInfo() const override; - inline oid_t GetFKSinkTableOid() const { return fk_sink_table_oid_; } - - inline const std::vector &GetFKSinkColumnIds() const { return fk_sink_col_ids_; } - - inline FKConstrActionType GetFKUpdateAction() const { return fk_update_action_; } + // Todo: default union data structure, + // For default constraint + void addDefaultValue(const type::Value &value) { + if (constraint_type_ != ConstraintType::DEFAULT + || default_value_.get() != nullptr) return; + default_value_.reset(new peloton::type::Value(value)); + } - inline FKConstrActionType GetFKDeleteAction() const { return fk_delete_action_; } + type::Value *getDefaultValue() { + return default_value_.get(); + } - inline std::pair GetCheckExpression() const { return check_exp_; } + // Add check constrain + void AddCheck(ExpressionType op, peloton::type::Value val) { + exp_ = std::pair(op, val); + }; private: //===--------------------------------------------------------------------===// // MEMBERS //===--------------------------------------------------------------------===// - // constraint oid created by catalog - oid_t constraint_oid_; - - std::string constraint_name_; - // The type of constraint - ConstraintType constraint_type_; - - // Table having this constraints - oid_t table_oid_; + ConstraintType constraint_type_ = ConstraintType::INVALID; - // Column ids related the constraint - std::vector column_ids_; + // Offsets into the Unique index and reference table lists in Table + oid_t fk_list_offset_ = INVALID_OID; - // Index constructing the constraint - oid_t index_oid_; + oid_t unique_index_list_offset_ = INVALID_OID; - // 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_; + std::string constraint_name_; - FKConstrActionType fk_update_action_ = FKConstrActionType::NOACTION; + std::shared_ptr default_value_; - FKConstrActionType fk_delete_action_ = FKConstrActionType::NOACTION; + std::string check_cmd_ = ""; - // key string is column name for check constraint - std::pair check_exp_; + // key string is column name + std::pair exp_; }; } // namespace catalog diff --git a/src/include/catalog/constraint_catalog.h b/src/include/catalog/constraint_catalog.h deleted file mode 100644 index a64ec5e3a75..00000000000 --- a/src/include/catalog/constraint_catalog.h +++ /dev/null @@ -1,156 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 ConstraintCatalogEntry { - friend class ConstraintCatalog; - - public: - ConstraintCatalogEntry(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::pair &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::pair check_exp_; -}; - -class ConstraintCatalog : public AbstractCatalog { - friend class ConstraintCatalogEntry; - friend class TableCatalogEntry; - friend class Catalog; - - public: - ConstraintCatalog(concurrency::TransactionContext *txn, - storage::Database *pg_catalog, - type::AbstractPool *pool); - - ~ConstraintCatalog(); - - inline oid_t GetNextOid() { return oid_++ | CONSTRAINT_OID_MASK; } - - void UpdateOid(oid_t add_value) { oid_ += add_value; } - - //===--------------------------------------------------------------------===// - // write Related API - //===--------------------------------------------------------------------===// - bool InsertConstraint(concurrency::TransactionContext *txn, - const std::shared_ptr constraint, - type::AbstractPool *pool); - - bool DeleteConstraints(concurrency::TransactionContext *txn, - oid_t table_oid); - - bool DeleteConstraint(concurrency::TransactionContext *txn, - oid_t table_oid, - oid_t constraint_oid); - - private: - //===--------------------------------------------------------------------===// - // Read Related API(only called within table catalog object) - //===--------------------------------------------------------------------===// - const std::unordered_map> - GetConstraintCatalogEntries(concurrency::TransactionContext *txn, - oid_t table_oid); - - const std::shared_ptr - GetConstraintCatalogEntry(concurrency::TransactionContext *txn, - oid_t table_oid, - oid_t constraint_oid); - - 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, - 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}; - - 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/foreign_key.h b/src/include/catalog/foreign_key.h new file mode 100644 index 00000000000..1fb745560e7 --- /dev/null +++ b/src/include/catalog/foreign_key.h @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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/layout_catalog.h b/src/include/catalog/layout_catalog.h index 616d0335b55..babdb346583 100644 --- a/src/include/catalog/layout_catalog.h +++ b/src/include/catalog/layout_catalog.h @@ -23,7 +23,6 @@ class Layout; namespace catalog { class LayoutCatalog : public AbstractCatalog { - friend class Catalog; public: LayoutCatalog(concurrency::TransactionContext *txn, @@ -76,4 +75,4 @@ class LayoutCatalog : public AbstractCatalog { }; } // namespace catalog -} // namespace peloton +} // namespace peloton \ No newline at end of file diff --git a/src/include/catalog/multi_constraint.h b/src/include/catalog/multi_constraint.h new file mode 100644 index 00000000000..46b254ed90e --- /dev/null +++ b/src/include/catalog/multi_constraint.h @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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 ead95e673a5..e70c7636d5d 100644 --- a/src/include/catalog/schema.h +++ b/src/include/catalog/schema.h @@ -14,7 +14,7 @@ #include #include "catalog/column.h" -#include "catalog/constraint.h" +#include "catalog/multi_constraint.h" #include "common/printable.h" #include "type/type.h" #include "boost/algorithm/string.hpp" @@ -174,146 +174,58 @@ 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 { - if (columns_[column_id].IsNotNull()) { - return false; + for (auto constraint : columns_[column_id].GetConstraints()) { + if (constraint.GetType() == ConstraintType::NOTNULL) return false; } 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; - } - } - } - - // 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 { - if (columns_[column_id].HasDefault()) { - 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) { - if (columns_[column_id].HasDefault()) { - columns_[column_id].ClearDefaultValue(); - } - 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(); + for (auto constraint : columns_[column_id].GetConstraints()) { + if (constraint.GetType() == ConstraintType::DEFAULT) { + return true; + } } - } - //===--------------------------------------------------------------------===// - // 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()); - } + return false; } - // 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; - } + // 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(); } } - constraints.erase(constraint_oid); - } - - inline std::unordered_map> GetConstraints() const { - return 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; + return nullptr; } - inline bool HasForeignKeys() const { return (fk_constraints_.size() > 0); } - - inline void RegisterForeignKeySource(const std::shared_ptr constraint) { - fk_sources_.push_back(constraint); + // Add constraint for column by id + inline void AddConstraint(oid_t column_id, + const catalog::Constraint &constraint) { + columns_[column_id].AddConstraint(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; + // Add constraint for column by name + inline void AddConstraint(std::string column_name, + const catalog::Constraint &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); } } } - inline bool HasForeignKeySources() const { return (fk_sources_.size() > 0); } + inline void AddMultiConstraints(const catalog::MultiConstraint &mc) { + multi_constraints_.push_back(mc); + } - inline std::vector> GetForeignKeySources() { - return fk_sources_; + inline std::vector GetMultiConstraints() { + return multi_constraints_; } // Get a string representation for debugging @@ -326,12 +238,15 @@ class Schema : public Printable { // all inlined and uninlined columns in the tuple std::vector columns_; - // keep these in sync with the vectors above - oid_t column_count_ = INVALID_OID; - // 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; + oid_t uninlined_column_count_ = INVALID_OID; // are all columns inlined @@ -339,27 +254,6 @@ 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/catalog/system_catalogs.h b/src/include/catalog/system_catalogs.h index e143d4c227d..1d3e8c081dc 100644 --- a/src/include/catalog/system_catalogs.h +++ b/src/include/catalog/system_catalogs.h @@ -14,7 +14,6 @@ #include -#include "catalog/constraint_catalog.h" #include "catalog/database_catalog.h" #include "catalog/index_metrics_catalog.h" #include "catalog/query_metrics_catalog.h" @@ -36,7 +35,6 @@ class TableCatalog; class IndexCatalog; class ColumnCatalog; class LayoutCatalog; -class ConstraintCatalog; class SystemCatalogs { public: @@ -90,13 +88,6 @@ 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"); @@ -131,7 +122,6 @@ 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 f7d373c4d3e..e22af23b262 100644 --- a/src/include/catalog/table_catalog.h +++ b/src/include/catalog/table_catalog.h @@ -45,14 +45,12 @@ namespace catalog { class IndexCatalogEntry; class ColumnCatalogEntry; -class ConstraintCatalogEntry; class TableCatalogEntry { friend class TableCatalog; friend class IndexCatalog; friend class ColumnCatalog; friend class LayoutCatalog; - friend class ConstraintCatalog; public: TableCatalogEntry(concurrency::TransactionContext *txn, @@ -97,15 +95,6 @@ class TableCatalogEntry { std::shared_ptr GetLayout(oid_t layout_id, bool cached_entry = false); - // Evict all constraints from the cache - void EvictAllConstraintCatalogEntries(); - - // Get constraints - 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; } inline const std::string &GetSchemaName() { return schema_name; } @@ -122,53 +111,39 @@ class TableCatalogEntry { uint32_t version_id; oid_t default_layout_oid; - // Insert/Evict index catalog entries + // Get index objects bool InsertIndexCatalogEntry(std::shared_ptr index_catalog_entry); bool EvictIndexCatalogEntry(oid_t index_oid); bool EvictIndexCatalogEntry(const std::string &index_name); - // Insert/Evict column catalog entries + // Get column objects bool InsertColumnCatalogEntry(std::shared_ptr column_catalog_entry); bool EvictColumnCatalogEntry(oid_t column_id); bool EvictColumnCatalogEntry(const std::string &column_name); - // Insert layout catalog entry into table catalog entry + // Insert layout into table object bool InsertLayout(std::shared_ptr layout); - // Evict layout_id from the table catalog entry + // Evict layout_id from the table object bool EvictLayout(oid_t layout_id); - // Insert constraint catalog entry into table catalog entry - bool InsertConstraintCatalogEntry( - 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 entries in this table + // cache for *all* index catalog objects 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 entries in this table + // cache for *all* column catalog objects in this table std::unordered_map> column_catalog_entries_; std::unordered_map> column_names_; bool valid_column_catalog_entries_; - // cache for *all* layout catalog entries in the table + // cache for *all* layout objects in the table std::unordered_map> layout_catalog_entries_; bool valid_layout_catalog_entries_; - // cache for *all* constraint catalog entries in the table - std::unordered_map> - constraint_catalog_entries_; - bool valid_constraint_catalog_entries_; - // Pointer to its corresponding transaction concurrency::TransactionContext *txn_; }; @@ -179,7 +154,6 @@ 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 b34d2971c70..22598226407 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -892,27 +892,26 @@ enum class PostgresConstraintType { enum class ConstraintType { INVALID = INVALID_TYPE_ID, // invalid - CHECK = 1, // check - PRIMARY = 2, // primary key - UNIQUE = 3, // unique - FOREIGN = 4, // foreign key - EXCLUSION = 5 // foreign key + 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 }; std::string ConstraintTypeToString(ConstraintType type); ConstraintType StringToConstraintType(const std::string &str); std::ostream &operator<<(std::ostream &os, const ConstraintType &type); enum class FKConstrActionType { - INVALID = INVALID_TYPE_ID, // invalid - NOACTION = 1, - RESTRICT = 2, - CASCADE = 3, - SETNULL = 4, - SETDEFAULT = 5 + NOACTION = 0, + RESTRICT = 1, + CASCADE = 2, + 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/planner/create_plan.h b/src/include/planner/create_plan.h index 5f76c0f194b..ecf6a0524fe 100644 --- a/src/include/planner/create_plan.h +++ b/src/include/planner/create_plan.h @@ -33,16 +33,11 @@ class AbstractExpression; namespace planner { /** - * The meta-data for a constraint reference. + * The meta-data for a foreign key 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; @@ -52,17 +47,6 @@ 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; @@ -106,18 +90,9 @@ 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; } @@ -140,16 +115,11 @@ class CreatePlan : public AbstractPlan { int16_t GetTriggerType() const { return trigger_type; } protected: - // These following protected function are a helper method for extracting - // Multi-column constraint information and storing it in an internal struct. + // This is a helper method for extracting foreign key 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; @@ -180,11 +150,7 @@ 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 b9e5cdafa10..6b49cf9e431 100644 --- a/src/include/storage/abstract_table.h +++ b/src/include/storage/abstract_table.h @@ -111,6 +111,16 @@ 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 48708b9edb5..1f0d4be29c4 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,12 +167,13 @@ 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 //===--------------------------------------------------------------------===// @@ -197,15 +198,29 @@ class DataTable : public AbstractTable { const std::vector> &GetIndexColumns() const { return indexes_columns_; } - //===--------------------------------------------------------------------===// // 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); + + void AddForeignKey(catalog::ForeignKey *key); + + catalog::ForeignKey *GetForeignKey(const oid_t &key_offset) const; + + void DropForeignKey(const oid_t &key_offset); + + size_t GetForeignKeyCount() const; + + void RegisterForeignKeySource(catalog::ForeignKey *key); + + size_t GetForeignKeySrcCount() const; + + catalog::ForeignKey *GetForeignKeySrc(const size_t) const; //===--------------------------------------------------------------------===// // TRANSFORMERS @@ -275,6 +290,12 @@ 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. @@ -314,8 +335,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; @@ -404,6 +425,20 @@ class DataTable : public AbstractTable { // columns present in the indexes std::vector> indexes_columns_; + // CONSTRAINTS + // fk constraints for which this table is the source + std::vector 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_; + + // 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 cc45b541890..f6b94640750 100644 --- a/src/include/storage/temp_table.h +++ b/src/include/storage/temp_table.h @@ -91,6 +91,12 @@ 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 f805258538d..f474504f954 100644 --- a/src/optimizer/stats/column_stats_collector.cpp +++ b/src/optimizer/stats/column_stats_collector.cpp @@ -44,12 +44,11 @@ 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 0824a978b21..4231e95ee9e 100644 --- a/src/optimizer/stats/stats_storage.cpp +++ b/src/optimizer/stats/stats_storage.cpp @@ -296,7 +296,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_DEBUG("Analyzing table: %s", table->GetName().c_str()); + LOG_TRACE("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 47b415175b7..2a23a75abb4 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -53,31 +53,49 @@ 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 pri_cols; + std::vector column_constraints; 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); - // Create column - auto column = catalog::Column(val, type::Type::GetTypeSize(val), - std::string(col->name), false); - if (!column.IsInlined()) { - column.SetLength(col->varlen); + // Check main constraints + if (col->primary) { + catalog::Constraint 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()); } - // Add NOT NULL constraints to the column if (col->not_null) { - column.SetNotNull(); + catalog::Constraint 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()); } - // Add DEFAULT constraints to the column + if (col->unique) { + catalog::Constraint 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 if (col->default_value != nullptr) { // Referenced from insert_plan.cpp if (col->default_value->GetExpressionType() != @@ -85,58 +103,53 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { expression::ConstantValueExpression *const_expr_elem = dynamic_cast( col->default_value.get()); - column.SetDefaultValue(const_expr_elem->GetValue()); + + catalog::Constraint constraint(ConstraintType::DEFAULT, + "con_default"); + type::Value v = const_expr_elem->GetValue(); + constraint.addDefaultValue(v); + column_constraints.push_back(constraint); LOG_TRACE("Added a default constraint %s on column \"%s.%s\"", - const_expr_elem->GetValue().ToString().c_str(), - table_name.c_str(), col->name.c_str()); + 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) { - ProcessCheckConstraint(col.get()); + // TODO: more expression types need to be supported + if (col->check_expression->GetValueType() == type::TypeId::BOOLEAN) { + catalog::Constraint 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()); + } } - } - catalog::Schema *schema = new catalog::Schema(columns); + auto column = catalog::Column(val, type::Type::GetTypeSize(val), + std::string(col->name), false); + if (!column.IsInlined()) { + column.SetLength(col->varlen); + } - // 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()); - } + for (auto con : column_constraints) { + column.AddConstraint(con); + } - // foreign key - for (auto &fk : parse_tree->foreign_keys) { - ProcessForeignKeyConstraint(table_name, fk.get()); + column_constraints.clear(); + columns.push_back(column); } - - // TODO: UNIQUE and CHECK constraints - + catalog::Schema *schema = new catalog::Schema(columns); table_schema = schema; break; } @@ -228,40 +241,6 @@ 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 0d1593738e3..8b6bccc4c8a 100644 --- a/src/planner/update_plan.cpp +++ b/src/planner/update_plan.cpp @@ -23,8 +23,18 @@ UpdatePlan::UpdatePlan(storage::DataTable *table, std::unique_ptr project_info) : target_table_(table), project_info_(std::move(project_info)), - update_primary_key_(table->GetSchema()->HasPrimary()) { + update_primary_key_(false) { 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 85240e196e1..c292e8d3718 100644 --- a/src/storage/data_table.cpp +++ b/src/storage/data_table.cpp @@ -14,6 +14,7 @@ #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,6 +110,17 @@ DataTable::~DataTable() { } } + // clean up foreign keys + for (auto foreign_key : foreign_keys_) { + delete foreign_key; + } + foreign_keys_.clear(); + + for (auto foreign_key_src : foreign_key_sources_) { + delete foreign_key_src; + } + foreign_key_sources_.clear(); + // drop all indirection arrays for (auto indirection_array : active_indirection_arrays_) { auto oid = indirection_array->GetOid(); @@ -134,61 +146,71 @@ 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); + // 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. + size_t column_count = schema->GetColumnCount(); + for (oid_t column_itr = 0; column_itr < column_count; column_itr++) { + const std::vector &column_constraints = + schema->GetColumn(column_itr).GetConstraints(); + for (const auto &constraint : column_constraints) { + ConstraintType type = constraint.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); + } + } } } - - // 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 +236,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 +386,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,14 +591,18 @@ 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; + size_t fk_count = GetForeignKeySrcCount(); + + if (fk_count == 0) return true; auto &transaction_manager = concurrency::TransactionManagerFactory::GetInstance(); - for (auto cons : schema->GetForeignKeySources()) { + for (size_t iter = 0; iter < fk_count; iter++) { + catalog::ForeignKey *fk = GetForeignKeySrc(iter); + // Check if any row in the source table references the current tuple - oid_t source_table_id = cons->GetTableOid(); + oid_t source_table_id = fk->GetSourceTableOid(); storage::DataTable *src_table = nullptr; try { src_table = (storage::DataTable *)storage::StorageManager::GetInstance() @@ -592,18 +618,17 @@ bool DataTable::CheckForeignKeySrcAndCascade( if (index == nullptr) continue; // Make sure this is the right index to search in - if (index->GetOid() == cons->GetIndexOid() && - index->GetMetadata()->GetKeyAttrs() == cons->GetColumnIds()) { + if (index->GetMetadata()->GetName().find("_FK_") != std::string::npos && + index->GetMetadata()->GetKeyAttrs() == fk->GetSourceColumnIds()) { LOG_DEBUG("Searching in source tables's fk index...\n"); - std::vector key_attrs = cons->GetColumnIds(); + std::vector key_attrs = fk->GetSourceColumnIds(); 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, cons->GetFKSinkColumnIds(), - index->GetPool()); + key->SetFromTuple(prev_tuple, fk->GetSinkColumnIds(), index->GetPool()); std::vector location_ptrs; index->ScanKey(key.get(), location_ptrs); @@ -621,7 +646,7 @@ bool DataTable::CheckForeignKeySrcAndCascade( if (visibility != VisibilityType::OK) continue; - switch (cons->GetFKUpdateAction()) { + switch (fk->GetUpdateAction()) { // Currently NOACTION is the same as RESTRICT case FKConstrActionType::NOACTION: case FKConstrActionType::RESTRICT: { @@ -636,8 +661,11 @@ 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) { @@ -662,7 +690,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 = cons->GetFKSinkColumnIds()[k]; + auto sink_col_index = fk->GetSinkColumnIds()[k]; src_new_tuple.SetValue(src_col_index, new_tuple->GetValue(sink_col_index), context->GetPool()); @@ -728,14 +756,14 @@ bool DataTable::CheckForeignKeySrcAndCascade( */ bool DataTable::CheckForeignKeyConstraints( const AbstractTuple *tuple, concurrency::TransactionContext *transaction) { - for (auto foreign_key : schema->GetForeignKeyConstraints()) { - oid_t sink_table_id = foreign_key->GetFKSinkTableOid(); + for (auto foreign_key : foreign_keys_) { + oid_t sink_table_id = foreign_key->GetSinkTableOid(); storage::DataTable *ref_table = nullptr; try { ref_table = (storage::DataTable *)storage::StorageManager::GetInstance() ->GetTableWithOid(database_oid, sink_table_id); } catch (CatalogException &e) { - LOG_ERROR("Can't find table %d! Return false", sink_table_id); + LOG_TRACE("Can't find table %d! Return false", sink_table_id); return false; } int ref_table_index_count = ref_table->GetIndexCount(); @@ -747,12 +775,13 @@ 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->GetFKSinkColumnIds(); + std::vector key_attrs = foreign_key->GetSinkColumnIds(); 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->GetColumnIds(), index->GetPool()); + key->SetFromTuple(tuple, foreign_key->GetSourceColumnIds(), + index->GetPool()); LOG_TRACE("check key: %s", key->GetInfo().c_str()); std::vector location_ptrs; @@ -761,7 +790,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->GetName().c_str()); + key->GetInfo().c_str(), ref_table->GetInfo().c_str()); return false; } @@ -779,7 +808,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->GetName().c_str(), + key->GetInfo().c_str(), ref_table->GetInfo().c_str(), VisibilityTypeToString(visibility).c_str()); return false; } @@ -846,8 +875,7 @@ 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_)); } @@ -887,8 +915,7 @@ 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; @@ -934,8 +961,7 @@ 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,8 +984,7 @@ 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_. @@ -1023,6 +1048,14 @@ 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( @@ -1114,6 +1147,55 @@ oid_t DataTable::GetValidIndexCount() const { return valid_index_count; } +//===--------------------------------------------------------------------===// +// 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::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); + } +} + +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); + } +} + +size_t DataTable::GetForeignKeySrcCount() const { + return foreign_key_sources_.size(); +} + +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( storage::TileGroup *tile_group, const Layout &layout) { diff --git a/src/storage/database.cpp b/src/storage/database.cpp index 55eaccc6892..8a7506805c8 100644 --- a/src/storage/database.cpp +++ b/src/storage/database.cpp @@ -12,6 +12,7 @@ #include +#include "catalog/foreign_key.h" #include "codegen/query_cache.h" #include "common/exception.h" #include "common/logger.h" @@ -145,11 +146,15 @@ const std::string Database::GetInfo() const { } } - if (table->GetSchema()->HasForeignKeys()) { + if (table->HasForeignKeys()) { os << "foreign tables \n"; - for (auto foreign_key : table->GetSchema()->GetForeignKeyConstraints()) { - auto sink_table_oid = foreign_key->GetFKSinkTableOid(); + 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(); auto sink_table = GetTableWithOid(sink_table_oid); os << "table name : " << sink_table->GetName() << std::endl; diff --git a/test/brain/query_logger_test.cpp b/test/brain/query_logger_test.cpp index 301e3408dbd..c3affa7fd40 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); + expected_result, true); // 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); + expected_result, true); // 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); + expected_result, true); // the select query we used will also be logged for next time temporary_expected_result.push_back(select_query_ + "|" + select_query_fingerprint_); diff --git a/test/catalog/catalog_test.cpp b/test/catalog/catalog_test.cpp index 7a15fa0f177..bda84540f89 100644 --- a/test/catalog/catalog_test.cpp +++ b/test/catalog/catalog_test.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "catalog/catalog.h" -#include "catalog/column.h" #include "catalog/column_catalog.h" #include "catalog/database_catalog.h" #include "catalog/database_metrics_catalog.h" @@ -26,7 +25,6 @@ #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 { @@ -72,6 +70,8 @@ TEST_F(CatalogTests, CreatingTable) { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); + id_column.AddConstraint( + catalog::Constraint(ConstraintType::PRIMARY, "primary_key")); auto name_column = catalog::Column(type::TypeId::VARCHAR, 32, "name", true); std::unique_ptr table_schema( @@ -81,55 +81,24 @@ TEST_F(CatalogTests, CreatingTable) { std::unique_ptr table_schema_3( new catalog::Schema({id_column, name_column})); - auto catalog = catalog::Catalog::GetInstance(); - catalog->CreateTable(txn, - "emp_db", - DEFAULT_SCHEMA_NAME, - std::move(table_schema), - "emp_table", - false); - catalog->CreateTable(txn, - "emp_db", - DEFAULT_SCHEMA_NAME, - std::move(table_schema_2), - "department_table", - false); - catalog->CreateTable(txn, - "emp_db", - DEFAULT_SCHEMA_NAME, - std::move(table_schema_3), - "salary_table", - false); - - auto emp = catalog->GetTableCatalogEntry(txn, - "emp_db", - DEFAULT_SCHEMA_NAME, - "emp_table"); - auto department = catalog->GetTableCatalogEntry(txn, - "emp_db", - DEFAULT_SCHEMA_NAME, - "department_table"); - auto salary = catalog->GetTableCatalogEntry(txn, - "emp_db", - DEFAULT_SCHEMA_NAME, - "salary_table"); - - catalog->AddPrimaryKeyConstraint(txn, - emp->GetDatabaseOid(), - emp->GetTableOid(), - {0}, - "con_primary"); - catalog->AddPrimaryKeyConstraint(txn, - department->GetDatabaseOid(), - department->GetTableOid(), - {0}, - "con_primary"); - catalog->AddPrimaryKeyConstraint(txn, - salary->GetDatabaseOid(), - salary->GetTableOid(), - {0}, - "con_primary"); - + catalog::Catalog::GetInstance()->CreateTable(txn, + "emp_db", + DEFAULT_SCHEMA_NAME, + std::move(table_schema), + "emp_table", + false); + catalog::Catalog::GetInstance()->CreateTable(txn, + "emp_db", + DEFAULT_SCHEMA_NAME, + std::move(table_schema_2), + "department_table", + false); + catalog::Catalog::GetInstance()->CreateTable(txn, + "emp_db", + DEFAULT_SCHEMA_NAME, + std::move(table_schema_3), + "salary_table", + false); // insert random tuple into DATABASE_METRICS_CATALOG and check std::unique_ptr pool(new type::EphemeralPool()); catalog::DatabaseMetricsCatalog::GetInstance()->InsertDatabaseMetrics(txn, @@ -144,8 +113,10 @@ TEST_F(CatalogTests, CreatingTable) { param.len = 1; param.buf = (unsigned char *) pool->Allocate(1); *param.buf = 'a'; - auto database_object = catalog->GetDatabaseCatalogEntry(txn, "emp_db"); - catalog->GetSystemCatalogs(database_object->GetDatabaseOid()) + auto database_object = + catalog::Catalog::GetInstance()->GetDatabaseCatalogEntry(txn, "emp_db"); + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_object->GetDatabaseOid()) ->GetQueryMetricsCatalog() ->InsertQueryMetrics(txn, "a query", @@ -162,13 +133,20 @@ TEST_F(CatalogTests, CreatingTable) { 1, 1, pool.get()); - auto param1 = catalog->GetSystemCatalogs(database_object->GetDatabaseOid()) - ->GetQueryMetricsCatalog() - ->GetParamTypes(txn, "a query"); + auto param1 = catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetQueryMetricsCatalog() + ->GetParamTypes(txn, "a query"); EXPECT_EQ(1, param1.len); EXPECT_EQ('a', *param1.buf); // check colum object - EXPECT_EQ("name", department->GetColumnCatalogEntry(1)->GetColumnName()); + EXPECT_EQ("name", catalog::Catalog::GetInstance() + ->GetTableCatalogEntry(txn, + "emp_db", + DEFAULT_SCHEMA_NAME, + "department_table") + ->GetColumnCatalogEntry(1) + ->GetColumnName()); txn_manager.CommitTransaction(txn); } @@ -177,7 +155,8 @@ TEST_F(CatalogTests, TestingCatalogCache) { auto txn = txn_manager.BeginTransaction(); auto catalog = catalog::Catalog::GetInstance(); - auto catalog_db_object = + auto + catalog_db_object = catalog->GetDatabaseCatalogEntry(txn, CATALOG_DATABASE_OID); auto catalog_table_objects = catalog_db_object->GetTableCatalogEntries(); EXPECT_NE(0, catalog_table_objects.size()); @@ -192,7 +171,6 @@ TEST_F(CatalogTests, TestingCatalogCache) { auto table = user_database->GetTable(table_idx); auto user_table_object = user_db_object->GetTableCatalogEntry(table->GetOid()); - EXPECT_EQ(user_db_object->GetDatabaseOid(), user_table_object->GetDatabaseOid()); } @@ -204,11 +182,10 @@ TEST_F(CatalogTests, TableObject) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); - auto table_object = - catalog::Catalog::GetInstance()->GetTableCatalogEntry(txn, - "emp_db", - DEFAULT_SCHEMA_NAME, - "department_table"); + auto table_object = catalog::Catalog::GetInstance()->GetTableCatalogEntry(txn, + "emp_db", + DEFAULT_SCHEMA_NAME, + "department_table"); auto index_objects = table_object->GetIndexCatalogEntries(); auto column_objects = table_object->GetColumnCatalogEntries(); @@ -224,8 +201,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()); @@ -234,8 +211,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(); @@ -510,7 +487,6 @@ TEST_F(CatalogTests, LayoutCatalogTest) { *(default_layout.get()), *(pg_layout->GetLayoutWithOid(txn, table_oid, default_layout_oid).get())); EXPECT_EQ(default_layout_oid, - catalog->GetTableCatalogEntry(txn, database_oid, table_oid)->GetDefaultLayoutOid()); @@ -570,7 +546,6 @@ TEST_F(CatalogTests, LayoutCatalogTest) { EXPECT_EQ(nullptr, pg_layout->GetLayoutWithOid(txn, table_oid, default_layout_oid)); EXPECT_EQ(ROW_STORE_LAYOUT_OID, - catalog->GetTableCatalogEntry(txn, database_oid, table_oid)->GetDefaultLayoutOid()); @@ -587,307 +562,5 @@ 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(txn, db_name)); - - // Create table for foreign key. - 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, - catalog->CreateTable(txn, - db_name, - DEFAULT_SCHEMA_NAME, - std::move(sink_table_schema), - sink_table_name, - false)); - - // 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); - 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})); - EXPECT_EQ(ResultType::SUCCESS, - catalog->CreateTable(txn, - db_name, - DEFAULT_SCHEMA_NAME, - std::move(con_table_schema), - con_table_name, - false)); - - LOG_DEBUG("Success two table creations"); - - auto database_oid = - catalog->GetDatabaseCatalogEntry(txn, db_name)->GetDatabaseOid(); - auto sink_table_object = catalog->GetTableCatalogEntry(txn, - db_name, - DEFAULT_SCHEMA_NAME, - sink_table_name); - auto sink_table = catalog->GetTableWithName(txn, - db_name, - DEFAULT_SCHEMA_NAME, - sink_table_name); - auto sink_table_oid = sink_table_object->GetTableOid(); - auto con_table_object = catalog->GetTableCatalogEntry(txn, - db_name, - DEFAULT_SCHEMA_NAME, - con_table_name); - auto con_table = catalog->GetTableWithName(txn, - db_name, - DEFAULT_SCHEMA_NAME, - con_table_name); - auto con_table_oid = con_table_object->GetTableOid(); - - // Add primary key constraint to sink table - EXPECT_EQ(ResultType::SUCCESS, - catalog->AddPrimaryKeyConstraint(txn, - database_oid, - sink_table_oid, - {0}, - "con_primary")); - - // Add constraints for constraint catalog test. - EXPECT_EQ(ResultType::SUCCESS, - catalog->AddPrimaryKeyConstraint(txn, - database_oid, - con_table_oid, - {0, 1}, - "con_primary")); - EXPECT_EQ(ResultType::SUCCESS, - catalog->AddUniqueConstraint(txn, - database_oid, - con_table_oid, - {2}, - "con_unique")); - - EXPECT_EQ(ResultType::SUCCESS, - catalog->AddForeignKeyConstraint(txn, - database_oid, - con_table_oid, - {3}, - sink_table_oid, - {0}, - FKConstrActionType::NOACTION, - FKConstrActionType::NOACTION, - "con_foreign")); - auto exp = std::make_pair(ExpressionType::COMPARE_GREATERTHAN, - type::ValueFactory::GetIntegerValue(0)); - EXPECT_EQ(ResultType::SUCCESS, - catalog->AddCheckConstraint(txn, - database_oid, - con_table_oid, - {4}, - exp, - "con_check")); - - 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) { - 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()); - } - - // Check foreign key as sink table - 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_schema->GetInfo().c_str()); - LOG_DEBUG("Complete check for sink table"); - - // Single column constraints - for (auto column_object_pair : con_table_object->GetColumnCatalogEntries()) { - 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); - } - } - - // 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) { - 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); - } - } - con_table_object->GetConstraintCatalogEntries(); - - txn_manager.CommitTransaction(txn); - - LOG_DEBUG("%s", con_schema->GetInfo().c_str()); - LOG_DEBUG("Complete check for constraint table"); - - // Drop constraint - txn = txn_manager.BeginTransaction(); - for (auto not_null_column_id : con_schema->GetNotNullColumns()) { - EXPECT_EQ(ResultType::SUCCESS, - catalog->DropNotNullConstraint(txn, - database_oid, - con_table_oid, - not_null_column_id)); - } - EXPECT_EQ(ResultType::SUCCESS, - catalog->DropDefaultConstraint(txn, - database_oid, - con_table_oid, - 6)); - for (auto constraint : con_schema->GetConstraints()) { - EXPECT_EQ( - ResultType::SUCCESS, - catalog->DropConstraint(txn, - database_oid, - con_table_oid, - constraint.second->GetConstraintOid())); - } - 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); - txn_manager.CommitTransaction(txn); -} - } // namespace test } // namespace peloton diff --git a/test/catalog/constraints_test.cpp b/test/catalog/constraints_test.cpp index f9563f9b251..8235e85e9a9 100644 --- a/test/catalog/constraints_test.cpp +++ b/test/catalog/constraints_test.cpp @@ -16,6 +16,7 @@ #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" @@ -28,9 +29,7 @@ #define CONSTRAINT_NOTNULL_TEST #define CONSTRAINT_DEFAULT_TEST -// #define CONSTRAINT_CHECK_TEST -#define CONSTRAINT_UNIQUE_TEST -#define CONSTRAINT_FOREIGN_KEY_TEST +//#define CONSTRAINT_CHECK_TEST namespace peloton { namespace test { @@ -53,14 +52,15 @@ TEST_F(ConstraintsTests, NOTNULLTest) { // 140 141 142 "143" // Set all of the columns to be NOT NULL - std::vector notnull_col_ids; + std::vector> constraints; for (int i = 0; i < CONSTRAINTS_NUM_COLS; i++) { - notnull_col_ids.push_back(i); + constraints.push_back( + {catalog::Constraint(ConstraintType::NOTNULL, "notnull_constraint")}); } - std::unordered_map default_values; + std::vector multi_constraints; storage::DataTable *data_table = - TestingConstraintsUtil::CreateTable(notnull_col_ids, default_values); - TestingConstraintsUtil::PopulateTable(data_table); + TestingConstraintsUtil::CreateAndPopulateTable(constraints, + multi_constraints); // Bootstrap auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); @@ -113,43 +113,29 @@ TEST_F(ConstraintsTests, NOTNULLTest) { #ifdef CONSTRAINT_DEFAULT_TEST TEST_F(ConstraintsTests, DEFAULTTEST) { - // Set default value within col_B - std::vector notnull_col_ids; - std::unordered_map default_values; + // Set all of the columns to be NOT NULL + std::vector> constraints; 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) { - catalog->AddPrimaryKeyConstraint(txn, - data_table->GetDatabaseOid(), - data_table->GetOid(), - {i}, - "con_primary"); + 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({}); } - // COL_B + COL_C + COL_D + // COL_C + COL_D else { - // do nothing + constraints.push_back({}); } } - txn_manager.CommitTransaction(txn); - - // populate test data - TestingConstraintsUtil::PopulateTable(data_table); + std::vector multi_constraints; + TestingConstraintsUtil::CreateAndPopulateTable(constraints, + multi_constraints); // Bootstrap std::vector result; @@ -167,14 +153,13 @@ TEST_F(ConstraintsTests, DEFAULTTEST) { rows_affected, error_message); EXPECT_EQ(ResultType::SUCCESS, status); - sql = StringUtil::Format("SELECT col_b FROM %s WHERE col_a = 9999", + sql = StringUtil::Format("SELECT col_d 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); - EXPECT_EQ(std::to_string(DEFAULT_VALUE), resultStr); - LOG_INFO("OUTPUT:%s", resultStr.c_str()); + LOG_INFO("OUTPUT:\n%s", resultStr.c_str()); } #endif @@ -188,47 +173,32 @@ 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(txn, DEFAULT_DB_NAME); auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "A", false, 0); - std::unique_ptr table_schema(new catalog::Schema({column1})); - - std::string table_name("TEST_TABLE"); - auto result = - catalog->CreateTable(txn, - DEFAULT_DB_NAME, - DEFAULT_SCHEMA_NAME, - std::move(table_schema), - table_name, - false); - EXPECT_EQ(ResultType::SUCCESS, result); - - auto data_table = catalog->GetTableWithName(txn, - DEFAULT_DB_NAME, - DEFAULT_SCHEMA_NAME, - table_name); - EXPECT_NE(nullptr, data_table); - - // add check constraint + auto constraints = catalog::Constraint(ConstraintType::CHECK, "check1"); type::Value tmp_value = type::ValueFactory::GetIntegerValue(0); - catalog->AddCheckConstraint(txn, - data_table->GetDatabaseOid(), - data_table->GetOid(), - {0}, - std::make_pair(ExpressionType::COMPARE_GREATERTHAN, tmp_value), - "con_check"); - txn_manager.CommitTransaction(txn); + 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::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 &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); // begin this transaction - txn = txn_manager.BeginTransaction(); + auto txn = txn_manager.BeginTransaction(); // Test1: insert a tuple with column meet the constraint requirment bool hasException = false; try { TestingConstraintsUtil::ExecuteOneInsert( - txn, data_table, type::ValueFactory::GetIntegerValue(10)); + txn, data_table.get(), type::ValueFactory::GetIntegerValue(10)); } catch (ConstraintException e) { hasException = true; } @@ -238,7 +208,7 @@ TEST_F(ConstraintsTests, CHECKTest) { hasException = false; try { TestingConstraintsUtil::ExecuteOneInsert( - txn, data_table, type::ValueFactory::GetIntegerValue(-1)); + txn, data_table.get(), type::ValueFactory::GetIntegerValue(-1)); } catch (ConstraintException e) { hasException = true; } @@ -246,11 +216,7 @@ TEST_F(ConstraintsTests, CHECKTest) { // commit this transaction txn_manager.CommitTransaction(txn); - - txn = txn_manager.BeginTransaction(); - auto result = catalog->DropDatabaseWithName(txn, DEFAULT_DB_NAME); - EXPECT_EQ(ResultType::SUCCESS, result); - txn_manager.CommitTransaction(txn); + delete data_table.release(); } #endif @@ -259,350 +225,355 @@ TEST_F(ConstraintsTests, UNIQUETest) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto catalog = catalog::Catalog::GetInstance(); auto txn = txn_manager.BeginTransaction(); - std::string db_name = "db1"; - catalog->CreateDatabase(txn, db_name); - auto column1 = catalog::Column(type::TypeId::INTEGER, 25, "A", false); - auto column2 = catalog::Column(type::TypeId::INTEGER, 25, "B", false); + catalog->CreateDatabase(DEFAULT_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 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->CreateTable(txn, - db_name, - DEFAULT_SCHEMA_NAME, - std::move(table_schema), - table_name, - false); - - auto table = catalog->GetTableWithName(txn, - db_name, - DEFAULT_SCHEMA_NAME, - table_name); - catalog->AddUniqueConstraint(txn, - table->GetDatabaseOid(), - table->GetOid(), - {0}, - "con_unique"); + catalog::Catalog::GetInstance()->CreateTable(txn, DEFAULT_DB_NAME, + DEFAULT_SCHEMA_NAME, + std::move(table_schema), + table_name, + false); + storage::DataTable *table = catalog::Catalog::GetInstance()->GetTableWithName( + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, table_name, txn); txn_manager.CommitTransaction(txn); + // table->AddUNIQUEIndex(); + txn = txn_manager.BeginTransaction(); // begin this transaction - // Test1: insert a tuple with column meet the unique requirement - bool result = TestingConstraintsUtil::ExecuteOneInsert( - txn, table, type::ValueFactory::GetIntegerValue(10)); - EXPECT_TRUE(result); + // 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); // Test2: insert not a valid column violate the constraint - result = TestingConstraintsUtil::ExecuteOneInsert( + hasException = false; + try { + // bool result = true; + // result = + TestingConstraintsUtil::ExecuteOneInsert( txn, table, type::ValueFactory::GetIntegerValue(10)); - EXPECT_FALSE(result); + // if (result == false) hasException = true; + } catch (ConstraintException e) { + hasException = true; + } + EXPECT_TRUE(hasException); - result = TestingConstraintsUtil::ExecuteOneInsert( + hasException = false; + try { + TestingConstraintsUtil::ExecuteOneInsert( txn, table, type::ValueFactory::GetIntegerValue(20)); - EXPECT_TRUE(result); + } catch (ConstraintException e) { + hasException = true; + } + EXPECT_FALSE(hasException); // commit this transaction txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - catalog->DropDatabaseWithName(txn, db_name); - 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(txn, db_name); - 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(txn, - db_name, - DEFAULT_SCHEMA_NAME, - std::move(table_schema), - table_name, - false); - - // Add multi-unique constraint - auto table = catalog->GetTableWithName(txn, - db_name, - DEFAULT_SCHEMA_NAME, - table_name); - catalog->AddUniqueConstraint(txn, - table->GetDatabaseOid(), - table->GetOid(), - cols, - "con_unique"); - 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(txn, db_name); + catalog::Catalog::GetInstance()->DropDatabaseWithName(DEFAULT_DB_NAME, txn); txn_manager.CommitTransaction(txn); } #endif -#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(txn, db_name); - - // 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(txn, - db_name, - DEFAULT_SCHEMA_NAME, - std::move(tableA_schema), - table_a_name, - false); - - auto table_a = catalog->GetTableWithName(txn, - db_name, - DEFAULT_SCHEMA_NAME, - table_a_name); - catalog->AddPrimaryKeyConstraint(txn, - table_a->GetDatabaseOid(), - table_a->GetOid(), - {0}, - "con_primary"); - 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(txn, - db_name, - DEFAULT_SCHEMA_NAME, - std::move(tableB_schema), - table_b_name, - false); - - auto table_b = catalog->GetTableWithName(txn, - db_name, - DEFAULT_SCHEMA_NAME, - table_b_name); - catalog->AddPrimaryKeyConstraint(txn, - table_b->GetDatabaseOid(), - table_b->GetOid(), - {0}, - "con_primary"); - - 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(txn, - table_a->GetDatabaseOid(), - table_a->GetOid(), - source_col_ids, - sink_table_id, - sink_col_ids, - FKConstrActionType::NOACTION, - FKConstrActionType::NOACTION, - "con_foreign"); - 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(txn, db_name); - 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(txn, db_name); - - // 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(txn, - db_name, - DEFAULT_SCHEMA_NAME, - std::move(tableA_schema), - table_a_name, - false); - - auto table_a = catalog->GetTableWithName(txn, - db_name, - DEFAULT_SCHEMA_NAME, - table_a_name); - 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(txn, - db_name, - DEFAULT_SCHEMA_NAME, - std::move(tableB_schema), - table_b_name, - false); - - std::vector cols; - cols.push_back(0); - cols.push_back(1); - auto table_b = catalog->GetTableWithName(txn, - db_name, - DEFAULT_SCHEMA_NAME, - table_b_name); - catalog->AddPrimaryKeyConstraint(txn, - table_b->GetDatabaseOid(), - table_b->GetOid(), - cols, - "con_primary"); - - // 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(txn, - table_a->GetDatabaseOid(), - table_a->GetOid(), - source_col_ids, - sink_table_id, - sink_col_ids, - FKConstrActionType::RESTRICT, - FKConstrActionType::CASCADE, - "con_foreign"); - 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(txn, db_name); - 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; +//} // ======================================================== diff --git a/test/codegen/testing_codegen_util.cpp b/test/codegen/testing_codegen_util.cpp index afc498c53b0..98879d6de59 100644 --- a/test/codegen/testing_codegen_util.cpp +++ b/test/codegen/testing_codegen_util.cpp @@ -86,15 +86,23 @@ catalog::Column PelotonCodeGenTest::GetTestColumn(uint32_t col_id) const { } // Create the test schema for all the tables -std::unique_ptr PelotonCodeGenTest::CreateTestSchema() const { +std::unique_ptr PelotonCodeGenTest::CreateTestSchema( + bool add_primary) 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].SetNotNull(); - cols[2].SetNotNull(); - cols[3].SetNotNull(); + cols[0].AddConstraint( + catalog::Constraint{ConstraintType::NOTNULL, "not_null"}); + if (add_primary) { + cols[0].AddConstraint( + catalog::Constraint{ConstraintType::PRIMARY, "con_primary"}); + } + cols[2].AddConstraint( + catalog::Constraint{ConstraintType::NOTNULL, "not_null"}); + cols[3].AddConstraint( + catalog::Constraint{ConstraintType::NOTNULL, "not_null"}); // Return the schema return std::unique_ptr{new catalog::Schema(cols)}; @@ -123,7 +131,7 @@ void PelotonCodeGenTest::CreateTestTables(concurrency::TransactionContext *txn, ->GetTableOid()); } for (int i = 4; i < 5; i++) { - auto table_schema = CreateTestSchema(); + auto table_schema = CreateTestSchema(true); catalog->CreateTable(txn, test_db_name, DEFAULT_SCHEMA_NAME, @@ -132,15 +140,12 @@ void PelotonCodeGenTest::CreateTestTables(concurrency::TransactionContext *txn, false, tuples_per_tilegroup, layout_type); - auto table_object = catalog->GetTableCatalogEntry(txn, test_db_name, - DEFAULT_SCHEMA_NAME, - test_table_names[i]); - catalog->AddPrimaryKeyConstraint(txn, - table_object->GetDatabaseOid(), - table_object->GetTableOid(), - {0}, - "con_primary"); - test_table_oids.push_back(table_object->GetTableOid()); + test_table_oids.push_back(catalog + ->GetTableCatalogEntry(txn, + test_db_name, + DEFAULT_SCHEMA_NAME, + test_table_names[i]) + ->GetTableOid()); } } diff --git a/test/common/internal_types_test.cpp b/test/common/internal_types_test.cpp index a8ff6b0881c..7a616315e20 100644 --- a/test/common/internal_types_test.cpp +++ b/test/common/internal_types_test.cpp @@ -405,9 +405,11 @@ TEST_F(InternalTypesTests, ResultTypeTest) { TEST_F(InternalTypesTests, ConstraintTypeTest) { std::vector list = { - ConstraintType::INVALID, ConstraintType::CHECK, - ConstraintType::PRIMARY, ConstraintType::UNIQUE, - ConstraintType::FOREIGN, ConstraintType::EXCLUSION}; + ConstraintType::INVALID, ConstraintType::NOT_NULL, + ConstraintType::NOTNULL, ConstraintType::DEFAULT, + 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 ca119c0b563..7f61cc0b765 100644 --- a/test/concurrency/testing_transaction_util.cpp +++ b/test/concurrency/testing_transaction_util.cpp @@ -43,11 +43,13 @@ storage::DataTable *TestingTransactionUtil::CreateCombinedPrimaryKeyTable() { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); - id_column.SetNotNull(); + id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, "not_null")); auto value_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "value", true); - value_column.SetNotNull(); + value_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, "not_null")); // Create the table catalog::Schema *table_schema = @@ -75,12 +77,6 @@ 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(); @@ -96,7 +92,8 @@ storage::DataTable *TestingTransactionUtil::CreatePrimaryKeyUniqueKeyTable() { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); - id_column.SetNotNull(); + id_column.AddConstraint( + catalog::Constraint(ConstraintType::NOTNULL, "not_null")); auto value_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "value", true); @@ -127,12 +124,6 @@ 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(); @@ -149,12 +140,6 @@ 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(); @@ -168,7 +153,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_key, size_t tuples_per_tilegroup) { + oid_t index_oid, bool need_primary_index, size_t tuples_per_tilegroup) { auto id_column = catalog::Column( type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "id", true); @@ -192,8 +177,8 @@ storage::DataTable *TestingTransactionUtil::CreateTable( key_schema->SetIndexedColumns(key_attrs); auto index_metadata = new index::IndexMetadata( - "primary_btree_index", index_oid, relation_id, database_id, - IndexType::BWTREE, need_primary_key ? IndexConstraintType::PRIMARY_KEY + "primary_btree_index", index_oid, TEST_TABLE_OID, CATALOG_DATABASE_OID, + IndexType::BWTREE, need_primary_index ? IndexConstraintType::PRIMARY_KEY : IndexConstraintType::DEFAULT, tuple_schema, key_schema, key_attrs, unique); @@ -202,14 +187,6 @@ storage::DataTable *TestingTransactionUtil::CreateTable( table->AddIndex(pkey_index); - // Create primary key constraint on the table - if (need_primary_key) { - 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); @@ -218,7 +195,7 @@ storage::DataTable *TestingTransactionUtil::CreateTable( db = storage::StorageManager::GetInstance()->GetDatabaseWithOid(database_id); } catch (CatalogException &e) { - LOG_ERROR("Can't find database %d! ", database_id); + LOG_TRACE("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 d5f915f152b..2c1b9e5d1fb 100644 --- a/test/executor/drop_test.cpp +++ b/test/executor/drop_test.cpp @@ -286,7 +286,7 @@ TEST_F(DropTests, DroppingIndexByName) { TEST_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table_01"); - oid_t col_id = source_table->GetSchema()->GetColumnID(id_column.GetName()); + oid_t col_id = source_table->GetSchema()->GetColumnID(id_column.column_name); 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 4adb7827475..eeb9c88095d 100644 --- a/test/executor/testing_executor_util.cpp +++ b/test/executor/testing_executor_util.cpp @@ -81,6 +81,7 @@ 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,7 +90,8 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "COL_A", is_inlined); - column.SetNotNull(); + column.AddConstraint(catalog::Constraint(ConstraintType::NOTNULL, + not_null_constraint_name)); return column; } break; @@ -98,7 +100,8 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { type::TypeId::INTEGER, type::Type::GetTypeSize(type::TypeId::INTEGER), "COL_B", is_inlined); - column.SetNotNull(); + column.AddConstraint(catalog::Constraint(ConstraintType::NOTNULL, + not_null_constraint_name)); return column; } break; @@ -107,7 +110,8 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { type::TypeId::DECIMAL, type::Type::GetTypeSize(type::TypeId::DECIMAL), "COL_C", is_inlined); - column.SetNotNull(); + column.AddConstraint(catalog::Constraint(ConstraintType::NOTNULL, + not_null_constraint_name)); return column; } break; @@ -116,7 +120,8 @@ catalog::Column TestingExecutorUtil::GetColumnInfo(int index) { catalog::Column(type::TypeId::VARCHAR, 25, // Column length. "COL_D", !is_inlined); // inlined. - column.SetNotNull(); + column.AddConstraint(catalog::Constraint(ConstraintType::NOTNULL, + not_null_constraint_name)); return column; } break; @@ -385,7 +390,7 @@ storage::DataTable *TestingExecutorUtil::CreateTable( unique = true; index_metadata = new index::IndexMetadata( - "primary_btree_index", 123, table_oid, INVALID_OID, IndexType::BWTREE, + "primary_btree_index", 123, INVALID_OID, INVALID_OID, IndexType::BWTREE, IndexConstraintType::PRIMARY_KEY, tuple_schema, key_schema, key_attrs, unique); @@ -394,12 +399,6 @@ 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 230d749ae0d..80cbc4bce7c 100644 --- a/test/executor/update_test.cpp +++ b/test/executor/update_test.cpp @@ -18,7 +18,6 @@ #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" @@ -173,6 +172,8 @@ 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); @@ -181,22 +182,14 @@ TEST_F(UpdateTests, UpdatingOld) { std::unique_ptr table_schema( new catalog::Schema({id_column, manager_id_column, name_column})); - - catalog->CreateTable(txn, - DEFAULT_DB_NAME, - DEFAULT_SCHEMA_NAME, - std::move(table_schema), - "department_table", - false); - auto table_object = - catalog->GetTableCatalogEntry(txn, - DEFAULT_DB_NAME, - DEFAULT_SCHEMA_NAME, - "department_table"); - catalog->AddPrimaryKeyConstraint(txn, - table_object->GetDatabaseOid(), - table_object->GetTableOid(), - {0}, "con_primary"); + 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(); LOG_INFO("Table created!"); diff --git a/test/gc/garbage_collection_test.cpp b/test/gc/garbage_collection_test.cpp index bc7c6b1061b..886131e5fb0 100644 --- a/test/gc/garbage_collection_test.cpp +++ b/test/gc/garbage_collection_test.cpp @@ -129,14 +129,12 @@ 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, 12345, 1234, true)); + num_key, "UPDATE_TABLE", db_id, INVALID_OID, 1234, true)); - EXPECT_EQ(1, gc_manager.GetTableCount() - prev_tc); + EXPECT_TRUE(gc_manager.GetTableCount() == 1); gc_manager.StartGC(gc_threads); @@ -225,15 +223,12 @@ 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, 12346, 1234, true)); + num_key, "DELETE_TABLE", db_id, INVALID_OID, 1234, true)); - EXPECT_EQ(1, gc_manager.GetTableCount() - prev_tc); + EXPECT_TRUE(gc_manager.GetTableCount() == 1); 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 b53f9084ad2..e574f5bd4d8 100644 --- a/test/gc/transaction_level_gc_manager_test.cpp +++ b/test/gc/transaction_level_gc_manager_test.cpp @@ -97,14 +97,12 @@ 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, 12345, 1234, true)); + num_key, "TABLE0", db_id, INVALID_OID, 1234, true)); - EXPECT_EQ(1, gc_manager.GetTableCount() - prev_tc); + EXPECT_TRUE(gc_manager.GetTableCount() == 1); //=========================== // update a version here. @@ -230,14 +228,12 @@ 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, 12346, 1234, true)); + num_key, "TABLE1", db_id, INVALID_OID, 1234, true)); - EXPECT_EQ(1, gc_manager.GetTableCount() - prev_tc); + EXPECT_TRUE(gc_manager.GetTableCount() == 1); //=========================== // insert a tuple here. @@ -401,15 +397,13 @@ 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, 12347, 1234, true, tuples_per_tilegroup)); + num_key, "TABLE1", db_id, INVALID_OID, 1234, true, tuples_per_tilegroup)); - EXPECT_EQ(1, gc_manager.GetTableCount() - prev_tc); + EXPECT_TRUE(gc_manager.GetTableCount() == 1); 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 8bd27540dbf..ab39e311bd1 100644 --- a/test/include/catalog/testing_constraints_util.h +++ b/test/include/catalog/testing_constraints_util.h @@ -91,10 +91,26 @@ 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 notnull_col_ids, - std::unordered_map default_values, + std::vector> constraints, + UNUSED_ATTRIBUTE std::vector multi_constraints, UNUSED_ATTRIBUTE bool indexes = true) { // Create the database auto catalog = catalog::Catalog::GetInstance(); @@ -108,24 +124,13 @@ class TestingConstraintsUtil { std::vector columns; for (int i = 0; i < CONSTRAINTS_NUM_COLS; i++) { columns.push_back( - TestingConstraintsUtil::GetColumnInfo(i)); + TestingConstraintsUtil::GetColumnInfo(i, constraints[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(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, std::move(table_schema), table_name, false); @@ -323,18 +328,6 @@ 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. @@ -364,7 +357,8 @@ class TestingConstraintsUtil { } }; - static catalog::Column GetColumnInfo(int index) { + static catalog::Column GetColumnInfo( + int index, std::vector constraints) { catalog::Column column; switch (index) { // COL_A @@ -400,6 +394,11 @@ 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 4c39f08c92b..fa9fcf852cd 100644 --- a/test/include/codegen/testing_codegen_util.h +++ b/test/include/codegen/testing_codegen_util.h @@ -89,7 +89,8 @@ class PelotonCodeGenTest : public PelotonTest { // Create the schema (common among all tables) catalog::Column GetTestColumn(uint32_t col_id) const; - std::unique_ptr CreateTestSchema() const; + std::unique_ptr CreateTestSchema( + bool add_primary = false) const; // Create the test tables void CreateTestTables(concurrency::TransactionContext *txn, diff --git a/test/include/concurrency/testing_transaction_util.h b/test/include/concurrency/testing_transaction_util.h index d2387f9ee98..d7bb919a0f3 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_key = false, size_t tuples_per_tilegroup = 100); + bool need_primary_index = 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 diff --git a/test/optimizer/stats_storage_test.cpp b/test/optimizer/stats_storage_test.cpp index 131bfbdb6ac..edf42131355 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 +} // namespace peloton \ No newline at end of file diff --git a/test/planner/plan_util_test.cpp b/test/planner/plan_util_test.cpp index d58aae8a5e0..6130d29d260 100644 --- a/test/planner/plan_util_test.cpp +++ b/test/planner/plan_util_test.cpp @@ -68,7 +68,7 @@ TEST_F(PlanUtilTests, GetAffectedIndexesTest) { txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - oid_t col_id = source_table->GetSchema()->GetColumnID(id_column.GetName()); + oid_t col_id = source_table->GetSchema()->GetColumnID(id_column.column_name); std::vector source_col_ids; source_col_ids.push_back(col_id); @@ -83,7 +83,7 @@ TEST_F(PlanUtilTests, GetAffectedIndexesTest) { IndexType::BWTREE); // create index on 'id' and 'first_name' - col_id = source_table->GetSchema()->GetColumnID(fname_column.GetName()); + col_id = source_table->GetSchema()->GetColumnID(fname_column.column_name); source_col_ids.push_back(col_id); catalog->CreateIndex(txn, @@ -232,11 +232,11 @@ TEST_F(PlanUtilTests, GetIndexableColumnsTest) { oid_t table_id = source_table->GetOid(); oid_t id_col_oid = - source_table->GetSchema()->GetColumnID(id_column.GetName()); + source_table->GetSchema()->GetColumnID(id_column.column_name); oid_t fname_col_oid = - source_table->GetSchema()->GetColumnID(fname_column.GetName()); + source_table->GetSchema()->GetColumnID(fname_column.column_name); oid_t lname_col_oid = - source_table->GetSchema()->GetColumnID(lname_column.GetName()); + source_table->GetSchema()->GetColumnID(lname_column.column_name); // Insert a 'test_table_job' with 'age', 'job' and 'pid' txn = txn_manager.BeginTransaction(); @@ -266,11 +266,11 @@ TEST_F(PlanUtilTests, GetIndexableColumnsTest) { "test_table_job"); oid_t table_job_id = source_table_job->GetOid(); oid_t age_col_oid = - source_table_job->GetSchema()->GetColumnID(age_column.GetName()); + source_table_job->GetSchema()->GetColumnID(age_column.column_name); oid_t job_col_oid = - source_table_job->GetSchema()->GetColumnID(job_column.GetName()); + source_table_job->GetSchema()->GetColumnID(job_column.column_name); oid_t pid_col_oid = - source_table_job->GetSchema()->GetColumnID(pid_column.GetName()); + source_table_job->GetSchema()->GetColumnID(pid_column.column_name); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); diff --git a/test/planner/planner_test.cpp b/test/planner/planner_test.cpp index fc865ab86a1..19304048dd9 100644 --- a/test/planner/planner_test.cpp +++ b/test/planner/planner_test.cpp @@ -193,10 +193,10 @@ TEST_F(PlannerTest, UpdatePlanTestParameter) { ExpressionType::COMPARE_EQUAL, tuple_expr, parameter_expr); auto &schema_columns = schema->GetColumns(); - for (oid_t i = 0; i < schema_columns.size(); i++) { + for (uint i = 0; i < schema_columns.size(); i++) { bool is_in_target_list = false; for (auto col_id : column_ids) { - if (schema_columns[i].GetName() == schema_columns[col_id].GetName()) { + if (schema_columns[i].column_name == schema_columns[col_id].column_name) { is_in_target_list = true; break; } @@ -206,7 +206,7 @@ TEST_F(PlannerTest, UpdatePlanTestParameter) { } column_ids.clear(); - for (oid_t i = 0; i < schema_columns.size(); i++) { + for (uint 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 b9248b1c5be..9ebd230346c 100644 --- a/test/sql/optimizer_sql_test.cpp +++ b/test/sql/optimizer_sql_test.cpp @@ -339,7 +339,7 @@ TEST_F(OptimizerSQLTests, DDLSqlTest) { auto cols = table->GetSchema()->GetColumns(); EXPECT_EQ(3, cols.size()); EXPECT_EQ("a", cols[0].GetName()); - EXPECT_EQ(true, table->GetSchema()->HasPrimary()); + EXPECT_EQ(true, cols[0].IsPrimary()); 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 792c4317b38..b40efd823e6 100644 --- a/test/statistics/stats_test.cpp +++ b/test/statistics/stats_test.cpp @@ -128,6 +128,8 @@ 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,16 +148,9 @@ TEST_F(StatsTests, MultiThreadStatsTest) { storage::Database *database = catalog->GetDatabaseWithName(txn, "emp_db"); storage::DataTable *table = catalog->GetTableWithName(txn, - "emp_db", - DEFAULT_SCHEMA_NAME, - "department_table"); - - catalog->AddPrimaryKeyConstraint(txn, - database->GetOid(), - table->GetOid(), - {0}, - "con_primary"); - + "emp_db", + DEFAULT_SCHEMA_NAME, + "department_table"); 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 169999efe9d..5c087e4aba4 100644 --- a/test/statistics/testing_stats_util.cpp +++ b/test/statistics/testing_stats_util.cpp @@ -12,8 +12,6 @@ #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" @@ -114,32 +112,24 @@ 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) { + catalog::Constraint 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(); - catalog->CreateTable(txn, - "emp_db", - DEFAULT_SCHEMA_NAME, - std::move(table_schema), - "department_table", - false); - - if (has_primary_key) { - auto table_object = catalog->GetTableCatalogEntry(txn, - "emp_db", - DEFAULT_SCHEMA_NAME, - "department_table"); - catalog->AddPrimaryKeyConstraint(txn, - table_object->GetDatabaseOid(), - table_object->GetTableOid(), - {0}, - "con_primary"); - } + 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(); txn_manager.CommitTransaction(txn); }