diff --git a/script/testing/junit/SequenceTest.java b/script/testing/junit/SequenceTest.java new file mode 100644 index 00000000000..07d9f30fac9 --- /dev/null +++ b/script/testing/junit/SequenceTest.java @@ -0,0 +1,172 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// SequenceTest.java +// +// Identification: script/testing/junit/SequenceTest.java +// +// Copyright (c) 2015-2018, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +import java.sql.*; +import org.junit.*; +import org.postgresql.util.PSQLException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static junit.framework.TestCase.fail; + +public class SequenceTest extends PLTestBase { + private Connection conn1; + private Connection conn2; + + private static final String SQL_DROP_SEQ = + "DROP SEQUENCE seq;"; + + private static final String SQL_CREATE_SEQ = + "CREATE SEQUENCE seq;"; + + private static final String SQL_NEXTVAL = + "SELECT NEXTVAL('seq')"; + + private static final String SQL_CURRVAL = + "SELECT CURRVAL('seq')"; + + /** + * Test sequence functions for single-statment transactions + */ + @Test + public void test_SingleStmtTxn() throws SQLException { + conn1 = makeDefaultConnection(); + conn1.setAutoCommit(true); + Statement stmt1 = conn1.createStatement(); + + conn2 = makeDefaultConnection(); + conn2.setAutoCommit(true); + Statement stmt2 = conn2.createStatement(); + + // Create a sequence + stmt1.execute(SQL_CREATE_SEQ); + + // Check the sequence is visible by others + try { + stmt2.execute(SQL_CREATE_SEQ); + fail(); + } catch (PSQLException e) { } + + // Check currval cannot be called before nextval + try { + stmt1.execute(SQL_CURRVAL); + fail(); + } catch (PSQLException e) { } + + // Check functionality with conn1 + stmt1.execute(SQL_NEXTVAL); + ResultSet res1 = stmt1.executeQuery(SQL_CURRVAL); + res1.next(); + assertEquals(1, res1.getInt(1)); + assertNoMoreRows(res1); + + // Update should be visible to conn2 + stmt2.execute(SQL_NEXTVAL); + ResultSet res2 = stmt2.executeQuery(SQL_CURRVAL); + res2.next(); + assertEquals(2, res2.getInt(1)); + assertNoMoreRows(res2); + + // Currval should be session consistent + res1 = stmt1.executeQuery(SQL_CURRVAL); + res1.next(); + assertEquals(1, res1.getInt(1)); + assertNoMoreRows(res1); + + // Clean up + stmt1.close(); + conn1.close(); + stmt2.close(); + conn2.close(); + } + + /** + * Test sequence functions for multi-statment transactions + */ + @Test + public void test_MultiStmtTxn() throws SQLException { + conn1 = makeDefaultConnection(); + conn1.setAutoCommit(false); + Statement stmt1 = conn1.createStatement(); + + conn2 = makeDefaultConnection(); + conn2.setAutoCommit(false); + Statement stmt2 = conn2.createStatement(); + + // Check functionality with conn1 + stmt1.execute(SQL_NEXTVAL); + ResultSet res1 = stmt1.executeQuery(SQL_CURRVAL); + res1.next(); + assertEquals(3, res1.getInt(1)); + assertNoMoreRows(res1); + + // Update should be visible to conn2 + stmt2.execute(SQL_NEXTVAL); + ResultSet res2 = stmt2.executeQuery(SQL_CURRVAL); + res2.next(); + assertEquals(4, res2.getInt(1)); + assertNoMoreRows(res2); + + // Rollback transactions + conn1.rollback(); + conn2.rollback(); + + // Check sequence incremental will not rollback + conn1.setAutoCommit(true); + stmt1.execute(SQL_NEXTVAL); + res1 = stmt1.executeQuery(SQL_CURRVAL); + res1.next(); + assertEquals(5, res1.getInt(1)); + assertNoMoreRows(res1); + + // Clean up + stmt1.close(); + conn1.close(); + stmt2.close(); + conn2.close(); + } + + /** + * Test dropping sequence + */ + @Test + public void test_Drop_Seq() throws SQLException { + conn1 = makeDefaultConnection(); + conn1.setAutoCommit(true); + Statement stmt1 = conn1.createStatement(); + + conn2 = makeDefaultConnection(); + conn2.setAutoCommit(true); + Statement stmt2 = conn2.createStatement(); + + // Drop the sequence + stmt1.execute(SQL_DROP_SEQ); + + // Check the sequence is invisible to all conns + try { + stmt1.execute(SQL_CURRVAL); + fail(); + } catch (PSQLException e) { } + try { + stmt2.execute(SQL_CURRVAL); + fail(); + } catch (PSQLException e) { } + + // Check the same sequence can be created w/o exception + stmt2.execute(SQL_CREATE_SEQ); + + // Clean up + stmt1.close(); + conn1.close(); + stmt2.close(); + conn2.close(); + } +} diff --git a/script/testing/junit/TempTableTest.java b/script/testing/junit/TempTableTest.java new file mode 100644 index 00000000000..b25ad6132e5 --- /dev/null +++ b/script/testing/junit/TempTableTest.java @@ -0,0 +1,179 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// TempTableTest.java +// +// Identification: script/testing/junit/TempTableTest.java +// +// Copyright (c) 2015-2018, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +import java.sql.*; +import org.junit.*; +import org.postgresql.util.PSQLException; + +import static junit.framework.TestCase.fail; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TempTableTest extends PLTestBase { + + private static final String SQL_DROP_TABLE = + "DROP TABLE IF EXISTS tbl;"; + + // Create a permanent table called "tbl" + private static final String SQL_CREATE_PERM_TABLE = + "CREATE TABLE tbl (id integer, year integer);"; + // Create temp table using "TEMP" keyword + private static final String SQL_CREATE_TEMP_TABLE = + "CREATE TEMP TABLE tbl (id integer, year integer);"; + // Create temp table using "TEMPORARY" keyword + private static final String SQL_CREATE_TEMPORARY_TABLE = + "CREATE TEMPORARY TABLE tbl (id integer, year integer);"; + + private static final String SQL_INSERT = + "INSERT INTO tbl VALUES (10, 1995);"; + + private static final String SQL_SELECT = "SELECT * FROM tbl;"; + + /** + * Check the temp table created by one session is visible to itself, + * but not visible to other sessions + */ + @Test + public void test_Visibility() throws SQLException { + Connection conn1 = makeDefaultConnection(); + conn1.setAutoCommit(true); + Statement stmt1 = conn1.createStatement(); + + Connection conn2 = makeDefaultConnection(); + conn2.setAutoCommit(true); + Statement stmt2 = conn2.createStatement(); + + // Part 1: Create temp table using "TEMP" keyword + stmt1.execute(SQL_DROP_TABLE); + // Create a temp table called "tbl" + stmt1.execute(SQL_CREATE_TEMP_TABLE); + // Insert a tuple into the temp table + stmt1.execute(SQL_INSERT); + + // Check the temp table is visible to the session created it + ResultSet res1 = stmt1.executeQuery(SQL_SELECT); + res1.next(); + checkRow(res1, + new String [] {"id", "year"}, + new int [] {10, 1995}); + assertNoMoreRows(res1); + + // Check the temp table is invisible to another session started + // before the temp table was created + // Expect an exception: "Table tbl is not found" + try { + stmt2.execute(SQL_SELECT); + fail(); + } catch (PSQLException e) { } + + // Check the temp table is invisible to another session started + // after the temp table was created + // Expect an exception: "Table tbl is not found" + conn2 = makeDefaultConnection(); + conn2.setAutoCommit(true); + stmt2 = conn2.createStatement(); + try { + stmt2.execute(SQL_SELECT); + fail(); + } catch (PSQLException e) { } + stmt2.close(); + conn2.close(); + + // Check the temp table is invisible to another session started + // after the session which created it has closed + // Expect an exception: "Table tbl is not found" + stmt1.close(); + conn1.close(); + conn2 = makeDefaultConnection(); + conn2.setAutoCommit(true); + stmt2 = conn2.createStatement(); + try { + stmt2.execute(SQL_SELECT); + fail(); + } catch (PSQLException e) { } + stmt2.close(); + conn2.close(); + + // Part 2: Create temp table using "TEMPORARY" keyword + conn1 = makeDefaultConnection(); + conn1.setAutoCommit(true); + stmt1 = conn1.createStatement(); + stmt1.execute(SQL_DROP_TABLE); + stmt1.execute(SQL_CREATE_TEMPORARY_TABLE); + + // Check the temp table is visible to the session created it + ResultSet res2 = stmt1.executeQuery(SQL_SELECT); + res2.next(); + assertNoMoreRows(res2); + + // Check the temp table is invisible to another session started + // before the table was created + // Expect an exception: "Table tbl is not found" + try { + stmt2.execute(SQL_SELECT); + fail(); + } catch (PSQLException e) { } + + stmt1.close(); + conn1.close(); + stmt2.close(); + conn2.close(); + } + + /** + * Check that during the lifetime of a temp table, the permanent table + * with the same name is invisible + */ + @Test + public void test_Temp_Table_Hides_Perm_Table() throws SQLException { + Connection conn = makeDefaultConnection(); + conn.setAutoCommit(true); + Statement stmt = conn.createStatement(); + + stmt.execute(SQL_DROP_TABLE); + // Create a permanent table called "tbl" + stmt.execute(SQL_CREATE_PERM_TABLE); + // Create a temp table called "tbl" + stmt.execute(SQL_CREATE_TEMP_TABLE); + // Insert a tuple into the temp table + stmt.execute(SQL_INSERT); + + // Check the "tbl" visible now is the temp table, not the permanent table + ResultSet res1 = stmt.executeQuery(SQL_SELECT); + res1.next(); + checkRow(res1, + new String [] {"id", "year"}, + new int [] {10, 1995}); + assertNoMoreRows(res1); + + // Drop the temp table + stmt.execute(SQL_DROP_TABLE); + + // Check the "tbl" visible now is the permanent table + ResultSet res2 = stmt.executeQuery(SQL_SELECT); + res2.next(); + assertNoMoreRows(res2); + + // Drop the permanent table + stmt.execute(SQL_DROP_TABLE); + + // No table named "tbl" should exist now + // Expect an exception: "Table tbl is not found" + try { + stmt.execute(SQL_SELECT); + fail(); + } catch (PSQLException e) { } + + stmt.close(); + conn.close(); + } +} diff --git a/src/binder/bind_node_visitor.cpp b/src/binder/bind_node_visitor.cpp index a6ffe17b322..db7d5564d4c 100644 --- a/src/binder/bind_node_visitor.cpp +++ b/src/binder/bind_node_visitor.cpp @@ -28,8 +28,10 @@ namespace peloton { namespace binder { BindNodeVisitor::BindNodeVisitor(concurrency::TransactionContext *txn, - std::string default_database_name) - : txn_(txn), default_database_name_(default_database_name) { + std::string default_database_name, + std::string session_namespace) + : txn_(txn), default_database_name_(default_database_name), + session_namespace_(session_namespace) { catalog_ = catalog::Catalog::GetInstance(); context_ = nullptr; } @@ -117,7 +119,7 @@ void BindNodeVisitor::Visit(parser::TableRef *node) { } // Single table else { - context_->AddRegularTable(node, default_database_name_, txn_); + context_->AddRegularTable(node, default_database_name_, session_namespace_, txn_); } } @@ -156,7 +158,8 @@ void BindNodeVisitor::Visit(parser::DeleteStatement *node) { context_ = std::make_shared(nullptr); node->TryBindDatabaseName(default_database_name_); context_->AddRegularTable(node->GetDatabaseName(), node->GetSchemaName(), - node->GetTableName(), node->GetTableName(), txn_); + node->GetTableName(), node->GetTableName(), + session_namespace_, txn_); if (node->expr != nullptr) { node->expr->Accept(this); @@ -175,7 +178,8 @@ void BindNodeVisitor::Visit(parser::InsertStatement *node) { node->TryBindDatabaseName(default_database_name_); context_ = std::make_shared(nullptr); context_->AddRegularTable(node->GetDatabaseName(), node->GetSchemaName(), - node->GetTableName(), node->GetTableName(), txn_); + node->GetTableName(), node->GetTableName(), + session_namespace_, txn_); if (node->select != nullptr) { node->select->Accept(this); } diff --git a/src/binder/binder_context.cpp b/src/binder/binder_context.cpp index 0413b488c37..a180c176d54 100644 --- a/src/binder/binder_context.cpp +++ b/src/binder/binder_context.cpp @@ -25,21 +25,23 @@ namespace binder { void BinderContext::AddRegularTable(parser::TableRef *table_ref, const std::string default_database_name, + const std::string session_namespace, concurrency::TransactionContext *txn) { table_ref->TryBindDatabaseName(default_database_name); auto table_alias = table_ref->GetTableAlias(); AddRegularTable(table_ref->GetDatabaseName(), table_ref->GetSchemaName(), - table_ref->GetTableName(), table_alias, txn); + table_ref->GetTableName(), table_alias, session_namespace, txn); } void BinderContext::AddRegularTable(const std::string db_name, const std::string schema_name, const std::string table_name, const std::string table_alias, + const std::string session_namespace, concurrency::TransactionContext *txn) { // using catalog object to retrieve meta-data auto table_object = catalog::Catalog::GetInstance()->GetTableObject( - db_name, schema_name, table_name, txn); + db_name, schema_name, session_namespace, table_name, txn); if (regular_table_alias_map_.find(table_alias) != regular_table_alias_map_.end() || diff --git a/src/catalog/abstract_catalog.cpp b/src/catalog/abstract_catalog.cpp index 645e9c9d93f..12b061fae43 100644 --- a/src/catalog/abstract_catalog.cpp +++ b/src/catalog/abstract_catalog.cpp @@ -67,6 +67,7 @@ AbstractCatalog::AbstractCatalog(const std::string &catalog_table_ddl, auto catalog_table_name = create_plan->GetTableName(); auto catalog_schema_name = create_plan->GetSchemaName(); auto catalog_database_name = create_plan->GetDatabaseName(); + auto catalog_session_namespace = create_plan->GetSessionNamespace(); PELOTON_ASSERT(catalog_schema_name == std::string(CATALOG_SCHEMA_NAME)); // create catalog table Catalog::GetInstance()->CreateTable( @@ -75,7 +76,7 @@ AbstractCatalog::AbstractCatalog(const std::string &catalog_table_ddl, // get catalog table oid auto catalog_table_object = Catalog::GetInstance()->GetTableObject( - catalog_database_name, catalog_schema_name, catalog_table_name, txn); + catalog_database_name, catalog_schema_name, catalog_session_namespace, catalog_table_name, txn); // set catalog_table_ try { diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 90b9d13a62a..bb0a6ffa608 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -30,6 +30,8 @@ #include "function/date_functions.h" #include "function/decimal_functions.h" #include "function/old_engine_string_functions.h" +#include "function/string_functions.h" +#include "function/sequence_functions.h" #include "function/timestamp_functions.h" #include "index/index_factory.h" #include "settings/settings_manager.h" @@ -94,9 +96,8 @@ void Catalog::BootstrapSystemCatalogs(storage::Database *database, system_catalogs->GetIndexCatalog()->InsertIndex( COLUMN_CATALOG_PKEY_OID, COLUMN_CATALOG_NAME "_pkey", COLUMN_CATALOG_OID, CATALOG_SCHEMA_NAME, IndexType::BWTREE, IndexConstraintType::PRIMARY_KEY, - true, - {ColumnCatalog::ColumnId::TABLE_OID, - ColumnCatalog::ColumnId::COLUMN_NAME}, + true, {ColumnCatalog::ColumnId::TABLE_OID, + ColumnCatalog::ColumnId::COLUMN_NAME}, pool_.get(), txn); system_catalogs->GetIndexCatalog()->InsertIndex( COLUMN_CATALOG_SKEY0_OID, COLUMN_CATALOG_NAME "_skey0", @@ -161,7 +162,7 @@ void Catalog::BootstrapSystemCatalogs(storage::Database *database, system_catalogs->GetSchemaCatalog()->InsertSchema( CATALOG_SCHEMA_OID, CATALOG_SCHEMA_NAME, pool_.get(), txn); system_catalogs->GetSchemaCatalog()->InsertSchema( - DEFUALT_SCHEMA_OID, DEFUALT_SCHEMA_NAME, pool_.get(), txn); + DEFUALT_SCHEMA_OID, DEFAULT_SCHEMA_NAME, pool_.get(), txn); // Insert catalog tables into pg_table // pg_database record is shared across different databases @@ -185,9 +186,9 @@ void Catalog::BootstrapSystemCatalogs(storage::Database *database, void Catalog::Bootstrap() { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); - // bootstrap pg_catalog database + // Bootstrap pg_catalog database catalog_map_[CATALOG_DATABASE_OID]->Bootstrap(CATALOG_DATABASE_NAME, txn); - // bootstrap other global catalog tables + // Bootstrap other global catalog tables DatabaseMetricsCatalog::GetInstance(txn); SettingsCatalog::GetInstance(txn); LanguageCatalog::GetInstance(txn); @@ -233,12 +234,12 @@ ResultType Catalog::CreateDatabase(const std::string &database_name, std::lock_guard lock(catalog_mutex); storage_manager->AddDatabaseToStorageManager(database); } - // put database object into rw_object_set + // Put database object into rw_object_set txn->RecordCreate(database_oid, INVALID_OID, INVALID_OID); // Insert database record into pg_db pg_database->InsertDatabase(database_oid, database_name, pool_.get(), txn); - // add core & non-core system catalog tables into database + // Add core & non-core system catalog tables into database BootstrapSystemCatalogs(database, txn); catalog_map_[database_oid]->Bootstrap(database_name, txn); LOG_TRACE("Database %s created. Returning RESULT_SUCCESS.", @@ -246,7 +247,7 @@ ResultType Catalog::CreateDatabase(const std::string &database_name, return ResultType::SUCCESS; } -/*@brief create schema(namespace) +/* @brief create schema(namespace) * @param database_name the database which the namespace belongs to * @param schema_name name of the schema * @param txn TransactionContext @@ -259,19 +260,24 @@ ResultType Catalog::CreateSchema(const std::string &database_name, throw CatalogException( "Do not have transaction to create schema(namespace) " + database_name); - // check whether database exists from pg_database + // Check whether database exists from pg_database auto database_object = DatabaseCatalog::GetInstance()->GetDatabaseObject(database_name, txn); if (database_object == nullptr) throw CatalogException("Can't find Database " + database_name + " to create schema"); - // check whether namespace exists from pg_namespace + // Check whether namespace exists from pg_namespace auto pg_namespace = catalog_map_[database_object->GetDatabaseOid()]->GetSchemaCatalog(); auto schema_object = pg_namespace->GetSchemaObject(schema_name, txn); - if (schema_object != nullptr) + if (schema_object != nullptr) { + // If the temporary schema exists + if (schema_name.find(TEMP_NAMESPACE_PREFIX) != std::string::npos) { + return ResultType::SUCCESS; + } throw CatalogException("Schema(namespace) " + schema_name + " already exists"); + } // Since there isn't physical class corresponds to schema(namespace), the only // thing needs to be done is inserting record into pg_namespace pg_namespace->InsertSchema(pg_namespace->GetNextOid(), schema_name, @@ -282,7 +288,7 @@ ResultType Catalog::CreateSchema(const std::string &database_name, return ResultType::SUCCESS; } -/*@brief create table +/* @brief create table * @param database_name the database which the table belongs to * @param schema_name name of schema the table belongs to * @param table_name name of the table @@ -302,13 +308,13 @@ ResultType Catalog::CreateTable(const std::string &database_name, LOG_TRACE("Creating table %s in database %s", table_name.c_str(), database_name.c_str()); - // check whether database exists from pg_database + // Check whether database exists from pg_database auto database_object = DatabaseCatalog::GetInstance()->GetDatabaseObject(database_name, txn); if (database_object == nullptr) throw CatalogException("Can't find Database " + database_name + " to create table"); - // check whether namespace exists from pg_namespace + // Check whether namespace exists from pg_namespace auto schema_object = catalog_map_[database_object->GetDatabaseOid()] ->GetSchemaCatalog() ->GetSchemaObject(schema_name, txn); @@ -316,8 +322,9 @@ ResultType Catalog::CreateTable(const std::string &database_name, throw CatalogException("Can't find namespace " + schema_name + " to create table"); - // get table oid from pg_table - auto table_object = database_object->GetTableObject(table_name, schema_name); + // Get table oid from pg_table + auto table_object = + database_object->GetTableObject(table_name, schema_name, schema_name); if (table_object != nullptr) throw CatalogException("Table: " + schema_name + "." + table_name + " already exists"); @@ -350,7 +357,7 @@ ResultType Catalog::CreateTable(const std::string &database_name, database_object->GetDatabaseOid(), table_oid, schema.release(), table_name, tuples_per_tilegroup, own_schema, adapt_table, is_catalog); database->AddTable(table, is_catalog); - // put data table object into rw_object_set + // Put data table object into rw_object_set txn->RecordCreate(database_object->GetDatabaseOid(), table_oid, INVALID_OID); // Update pg_table with table info @@ -367,8 +374,8 @@ ResultType Catalog::CreateTable(const std::string &database_name, if (column.IsUnique()) { std::string col_name = column.GetName(); std::string index_name = table->GetName() + "_" + col_name + "_UNIQ"; - CreateIndex(database_name, schema_name, table_name, {column_id}, - index_name, true, IndexType::BWTREE, txn); + CreateIndex(database_name, schema_name, schema_name, table_name, + {column_id}, index_name, true, IndexType::BWTREE, txn); LOG_DEBUG("Added a UNIQUE index on %s in %s.", col_name.c_str(), table_name.c_str()); } @@ -379,7 +386,7 @@ ResultType Catalog::CreateTable(const std::string &database_name, return ResultType::SUCCESS; } -/*@brief create primary 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 @@ -434,9 +441,9 @@ ResultType Catalog::CreatePrimaryIndex(oid_t database_oid, oid_t table_oid, index::IndexFactory::GetIndex(index_metadata)); table->AddIndex(pkey_index); - // put index object into rw_object_set + // Put index object into rw_object_set txn->RecordCreate(database_oid, table_oid, index_oid); - // insert index record into index_catalog(pg_index) table + // Insert index record into index_catalog(pg_index) table pg_index->InsertIndex(index_oid, index_name, table_oid, schema_name, IndexType::BWTREE, IndexConstraintType::PRIMARY_KEY, unique_keys, key_attrs, pool_.get(), txn); @@ -447,9 +454,10 @@ ResultType Catalog::CreatePrimaryIndex(oid_t database_oid, oid_t table_oid, return ResultType::SUCCESS; } -/*@brief create index on table +/* @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 session_namespace the session namespace of the query running on * @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 @@ -462,6 +470,7 @@ ResultType Catalog::CreatePrimaryIndex(oid_t database_oid, oid_t table_oid, */ ResultType Catalog::CreateIndex(const std::string &database_name, const std::string &schema_name, + const std::string &session_namespace, const std::string &table_name, const std::vector &key_attrs, const std::string &index_name, bool unique_keys, @@ -474,15 +483,15 @@ ResultType Catalog::CreateIndex(const std::string &database_name, LOG_TRACE("Trying to create index %s for table %s", index_name.c_str(), table_name.c_str()); - // check if database exists + // Check if database exists auto database_object = DatabaseCatalog::GetInstance()->GetDatabaseObject(database_name, txn); if (database_object == nullptr) throw CatalogException("Can't find Database " + database_name + " to create index"); - - // check if table exists - auto table_object = database_object->GetTableObject(table_name, schema_name); + // Check if table exists + auto table_object = database_object->GetTableObject(table_name, schema_name, + session_namespace); if (table_object == nullptr) throw CatalogException("Can't find table " + schema_name + "." + table_name + " to create index"); @@ -490,9 +499,11 @@ ResultType Catalog::CreateIndex(const std::string &database_name, IndexConstraintType index_constraint = unique_keys ? IndexConstraintType::UNIQUE : IndexConstraintType::DEFAULT; + // Schema not sure. should get from the table object ResultType success = CreateIndex( database_object->GetDatabaseOid(), table_object->GetTableOid(), key_attrs, - schema_name, index_name, index_type, index_constraint, unique_keys, txn); + table_object->GetSchemaName(), index_name, index_type, index_constraint, + unique_keys, txn); return success; } @@ -509,8 +520,8 @@ ResultType Catalog::CreateIndex( LOG_TRACE("Trying to create index for table %d", table_oid); if (is_catalog == false) { - // check if table already has index with same name - // only check when is_catalog flag == false + // Check if table already has index with same name + // Only check when is_catalog flag == false auto database_object = DatabaseCatalog::GetInstance()->GetDatabaseObject(database_oid, txn); auto table_object = database_object->GetTableObject(table_oid); @@ -594,14 +605,14 @@ ResultType Catalog::DropDatabaseWithOid(oid_t database_oid, " does not exist in pg_database"); catalog_map_.erase(database_oid); - // put database object into rw_object_set + // Put database object into rw_object_set storage_manager->GetDatabaseWithOid(database_oid); txn->RecordDrop(database_oid, INVALID_OID, INVALID_OID); return ResultType::SUCCESS; } -/*@brief Drop schema +/* @brief Drop schema * 1. drop all the tables within this schema * 2. delete record within pg_namespace * @param database_name the database which the dropped table belongs to @@ -622,7 +633,7 @@ ResultType Catalog::DropSchema(const std::string &database_name, throw CatalogException("Drop Schema: database " + database_name + " does not exist"); - // check whether namespace exists from pg_namespace + // Check whether namespace exists from pg_namespace auto pg_namespace = catalog_map_[database_object->GetDatabaseOid()]->GetSchemaCatalog(); auto schema_object = pg_namespace->GetSchemaObject(schema_name, txn); @@ -634,11 +645,21 @@ ResultType Catalog::DropSchema(const std::string &database_name, DropTable(it->GetDatabaseOid(), it->GetTableOid(), txn); } - // remove record within pg_namespace + // Remove record within pg_namespace pg_namespace->DeleteSchema(schema_name, txn); return ResultType::SUCCESS; } +void Catalog::RemoveCachedSequenceCurrVal(const std::string &database_name, + const std::string &temp_session_name_, + concurrency::TransactionContext *txn){ + oid_t database_oid = DatabaseCatalog::GetInstance() + ->GetDatabaseObject(database_name, txn)->GetDatabaseOid(); + // get the sequence copy from cache + GetSystemCatalogs(database_oid)->GetSequenceCatalog() + ->EvictNamespaceCurrValCache(temp_session_name_); +} + /*@brief Drop table * 1. drop all the indexes on actual table, and drop index records in * pg_index @@ -649,12 +670,14 @@ ResultType Catalog::DropSchema(const std::string &database_name, * @param database_name the database which the dropped table belongs to * @param schema_name the namespace which the dropped table belongs * to + * @param session_namespace the session that the transaction running over. * @param table_name the dropped table name * @param txn TransactionContext * @return TransactionContext ResultType(SUCCESS or FAILURE) */ ResultType Catalog::DropTable(const std::string &database_name, const std::string &schema_name, + const std::string &session_namespace, const std::string &table_name, concurrency::TransactionContext *txn) { if (txn == nullptr) @@ -668,8 +691,10 @@ ResultType Catalog::DropTable(const std::string &database_name, throw CatalogException("Drop Table: database " + database_name + " does not exist"); - // check if table exists - auto table_object = database_object->GetTableObject(table_name, schema_name); + // Check if table exists + auto table_object = database_object->GetTableObject(table_name, schema_name, + session_namespace); + if (table_object == nullptr) throw CatalogException("Drop Table: table " + schema_name + "." + table_name + " does not exist"); @@ -679,7 +704,7 @@ ResultType Catalog::DropTable(const std::string &database_name, return result; } -/*@brief Drop table +/* @brief Drop table * 1. drop all the indexes on actual table, and drop index records in pg_index * 2. drop all the columns records in pg_attribute * 3. drop table record in pg_table @@ -701,7 +726,7 @@ ResultType Catalog::DropTable(oid_t database_oid, oid_t table_oid, auto index_objects = table_object->GetIndexObjects(); LOG_TRACE("dropping #%d indexes", (int)index_objects.size()); - // delete trigger and records in pg_trigger + // Delete trigger and records in pg_trigger auto pg_trigger = catalog_map_[database_object->GetDatabaseOid()]->GetTriggerCatalog(); std::unique_ptr trigger_lists = @@ -710,16 +735,16 @@ ResultType Catalog::DropTable(oid_t database_oid, oid_t table_oid, pg_trigger->DropTrigger(database_oid, table_oid, trigger_lists->Get(i)->GetTriggerName(), txn); - // delete index and records pg_index + // Delete index and records pg_index for (auto it : index_objects) DropIndex(database_oid, it.second->GetIndexOid(), txn); - // delete record in pg_attribute + // Delete record in pg_attribute auto pg_attribute = catalog_map_[database_object->GetDatabaseOid()]->GetColumnCatalog(); pg_attribute->DeleteColumns(table_oid, txn); - // delete record in pg_table + // Delete record in pg_table auto pg_table = catalog_map_[database_object->GetDatabaseOid()]->GetTableCatalog(); pg_table->DeleteTable(table_oid, txn); @@ -730,7 +755,7 @@ ResultType Catalog::DropTable(oid_t database_oid, oid_t table_oid, return ResultType::SUCCESS; } -/*@brief Drop Index on table +/* @brief Drop Index on table * @param index_oid the oid of the index to be dropped * @param txn TransactionContext * @return TransactionContext ResultType(SUCCESS or FAILURE) @@ -740,7 +765,7 @@ ResultType Catalog::DropIndex(oid_t database_oid, oid_t index_oid, if (txn == nullptr) throw CatalogException("Do not have transaction to drop index " + std::to_string(index_oid)); - // find index catalog object by looking up pg_index or read from cache using + // Find index catalog object by looking up pg_index or read from cache using // index_oid auto pg_index = catalog_map_[database_oid]->GetIndexCatalog(); auto index_object = pg_index->GetIndexObject(index_oid, txn); @@ -752,12 +777,12 @@ ResultType Catalog::DropIndex(oid_t database_oid, oid_t index_oid, auto storage_manager = storage::StorageManager::GetInstance(); auto table = storage_manager->GetTableWithOid(database_oid, index_object->GetTableOid()); - // drop record in pg_index + // Drop record in pg_index pg_index->DeleteIndex(index_oid, txn); LOG_TRACE("Successfully drop index %d for table %s", index_oid, table->GetName().c_str()); - // register index object in rw_object_set + // Register index object in rw_object_set table->GetIndexWithOid(index_oid); txn->RecordDrop(database_oid, index_object->GetTableOid(), index_oid); @@ -795,14 +820,15 @@ storage::Database *Catalog::GetDatabaseWithName( * */ storage::DataTable *Catalog::GetTableWithName( const std::string &database_name, const std::string &schema_name, - const std::string &table_name, concurrency::TransactionContext *txn) { + const std::string &session_namespace, const std::string &table_name, + concurrency::TransactionContext *txn) { PELOTON_ASSERT(txn != nullptr); LOG_TRACE("Looking for table %s in database %s", table_name.c_str(), database_name.c_str()); // Check in pg_table, throw exception and abort txn if not exists - auto table_object = - GetTableObject(database_name, schema_name, table_name, txn); + auto table_object = GetTableObject(database_name, schema_name, + session_namespace, table_name, txn); // Get table from storage manager auto storage_manager = storage::StorageManager::GetInstance(); @@ -861,7 +887,8 @@ std::shared_ptr Catalog::GetDatabaseObject( * */ std::shared_ptr Catalog::GetTableObject( const std::string &database_name, const std::string &schema_name, - const std::string &table_name, concurrency::TransactionContext *txn) { + const std::string &session_namespace, const std::string &table_name, + concurrency::TransactionContext *txn) { if (txn == nullptr) { throw CatalogException("Do not have transaction to get table object " + database_name + "." + table_name); @@ -879,10 +906,11 @@ std::shared_ptr Catalog::GetTableObject( } // Check in pg_table using txn - auto table_object = database_object->GetTableObject(table_name, schema_name); + auto table_object = database_object->GetTableObject(table_name, schema_name, + session_namespace); if (!table_object || table_object->GetTableOid() == INVALID_OID) { - // throw table not found exception and explicitly abort txn + // Throw table not found exception and explicitly abort txn throw CatalogException("Table " + schema_name + "." + table_name + " is not found"); } @@ -913,7 +941,7 @@ std::shared_ptr Catalog::GetTableObject( auto table_object = database_object->GetTableObject(table_oid); if (!table_object || table_object->GetTableOid() == INVALID_OID) { - // throw table not found exception and explicitly abort txn + // Throw table not found exception and explicitly abort txn throw CatalogException("Table " + std::to_string(table_oid) + " is not found"); } @@ -921,6 +949,28 @@ std::shared_ptr Catalog::GetTableObject( return table_object; } +/** + * Drop all the temporary tables associated with the namespace. + */ +void Catalog::DropTempTables(const std::string &database_name, + const std::string &session_namespace, + concurrency::TransactionContext *txn) { + auto database_object = + DatabaseCatalog::GetInstance()->GetDatabaseObject(database_name, txn); + // Get pg_table + auto pg_table = + catalog_map_[database_object->GetDatabaseOid()]->GetTableCatalog(); + // Get all the tables to be dropped + auto tables_dropped = pg_table->GetTableObjects(session_namespace, txn); + // Drop all tables. + for (auto iter = tables_dropped.begin(); iter != tables_dropped.end(); + iter++) { + // Is this a safeway to use? + auto table_ptr = *iter; + DropTable(table_ptr->GetDatabaseOid(), table_ptr->GetTableOid(), txn); + } +} + std::shared_ptr Catalog::GetSystemCatalogs( const oid_t database_oid) { if (catalog_map_.find(database_oid) == catalog_map_.end()) { @@ -1083,7 +1133,7 @@ void Catalog::InitializeLanguages() { if (!initialized) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); - // add "internal" language + // Add "internal" language if (!LanguageCatalog::GetInstance().InsertLanguage("internal", pool_.get(), txn)) { txn_manager.AbortTransaction(txn); @@ -1204,6 +1254,20 @@ void Catalog::InitializeFunctions() { function::BuiltInFuncType{OperatorId::Like, function::OldEngineStringFunctions::Like}, txn); + // Sequence + AddBuiltinFunction( + "nextval", {type::TypeId::VARCHAR}, type::TypeId::INTEGER, + internal_lang, "Nextval", + function::BuiltInFuncType{OperatorId::Nextval, + function::SequenceFunctions::_Nextval}, + txn); + AddBuiltinFunction( + "currval", {type::TypeId::VARCHAR}, type::TypeId::INTEGER, + internal_lang, "Currval", + function::BuiltInFuncType{OperatorId::Currval, + function::SequenceFunctions::_Currval}, + txn); + /** * decimal functions @@ -1215,9 +1279,8 @@ void Catalog::InitializeFunctions() { txn); AddBuiltinFunction( "sqrt", {type::TypeId::TINYINT}, type::TypeId::DECIMAL, internal_lang, - "Sqrt", - function::BuiltInFuncType{OperatorId::Sqrt, - function::DecimalFunctions::Sqrt}, + "Sqrt", function::BuiltInFuncType{OperatorId::Sqrt, + function::DecimalFunctions::Sqrt}, txn); AddBuiltinFunction( "sqrt", {type::TypeId::SMALLINT}, type::TypeId::DECIMAL, @@ -1227,21 +1290,18 @@ void Catalog::InitializeFunctions() { txn); AddBuiltinFunction( "sqrt", {type::TypeId::INTEGER}, type::TypeId::DECIMAL, internal_lang, - "Sqrt", - function::BuiltInFuncType{OperatorId::Sqrt, - function::DecimalFunctions::Sqrt}, + "Sqrt", function::BuiltInFuncType{OperatorId::Sqrt, + function::DecimalFunctions::Sqrt}, txn); AddBuiltinFunction( "sqrt", {type::TypeId::BIGINT}, type::TypeId::DECIMAL, internal_lang, - "Sqrt", - function::BuiltInFuncType{OperatorId::Sqrt, - function::DecimalFunctions::Sqrt}, + "Sqrt", function::BuiltInFuncType{OperatorId::Sqrt, + function::DecimalFunctions::Sqrt}, txn); AddBuiltinFunction( "sqrt", {type::TypeId::DECIMAL}, type::TypeId::DECIMAL, internal_lang, - "Sqrt", - function::BuiltInFuncType{OperatorId::Sqrt, - function::DecimalFunctions::Sqrt}, + "Sqrt", function::BuiltInFuncType{OperatorId::Sqrt, + function::DecimalFunctions::Sqrt}, txn); AddBuiltinFunction( "floor", {type::TypeId::DECIMAL}, type::TypeId::DECIMAL, @@ -1310,16 +1370,14 @@ void Catalog::InitializeFunctions() { AddBuiltinFunction( "ceil", {type::TypeId::DECIMAL}, type::TypeId::DECIMAL, internal_lang, - "Ceil", - function::BuiltInFuncType{OperatorId::Ceil, - function::DecimalFunctions::_Ceil}, + "Ceil", function::BuiltInFuncType{OperatorId::Ceil, + function::DecimalFunctions::_Ceil}, txn); AddBuiltinFunction( "ceil", {type::TypeId::TINYINT}, type::TypeId::DECIMAL, internal_lang, - "Ceil", - function::BuiltInFuncType{OperatorId::Ceil, - function::DecimalFunctions::_Ceil}, + "Ceil", function::BuiltInFuncType{OperatorId::Ceil, + function::DecimalFunctions::_Ceil}, txn); AddBuiltinFunction( @@ -1331,16 +1389,14 @@ void Catalog::InitializeFunctions() { AddBuiltinFunction( "ceil", {type::TypeId::INTEGER}, type::TypeId::DECIMAL, internal_lang, - "Ceil", - function::BuiltInFuncType{OperatorId::Ceil, - function::DecimalFunctions::_Ceil}, + "Ceil", function::BuiltInFuncType{OperatorId::Ceil, + function::DecimalFunctions::_Ceil}, txn); AddBuiltinFunction( "ceil", {type::TypeId::BIGINT}, type::TypeId::DECIMAL, internal_lang, - "Ceil", - function::BuiltInFuncType{OperatorId::Ceil, - function::DecimalFunctions::_Ceil}, + "Ceil", function::BuiltInFuncType{OperatorId::Ceil, + function::DecimalFunctions::_Ceil}, txn); AddBuiltinFunction( @@ -1395,7 +1451,7 @@ void Catalog::InitializeFunctions() { function::TimestampFunctions::_DateTrunc}, txn); - // add now() + // Add now() AddBuiltinFunction("now", {}, type::TypeId::TIMESTAMP, internal_lang, "Now", function::BuiltInFuncType{ diff --git a/src/catalog/catalog_cache.cpp b/src/catalog/catalog_cache.cpp index 54f0e1a3d13..2c456868180 100644 --- a/src/catalog/catalog_cache.cpp +++ b/src/catalog/catalog_cache.cpp @@ -11,10 +11,12 @@ //===----------------------------------------------------------------------===// #include +#include #include "catalog/catalog_cache.h" #include "catalog/database_catalog.h" +#include "catalog/sequence_catalog.h" #include "common/logger.h" namespace peloton { @@ -157,5 +159,79 @@ std::shared_ptr CatalogCache::GetCachedIndexObject( return nullptr; } +/*@brief insert sequence catalog object into cache + * @param sequence_object + * @return false only if sequence already exists in cache or invalid + */ +bool CatalogCache::InsertSequenceObject( + std::shared_ptr sequence_object) { + if (!sequence_object || sequence_object->seq_oid == INVALID_OID) { + return false; // invalid object + } + + std::size_t hash_key = GetHashKey(sequence_object->seq_name, + sequence_object->db_oid); + + // check if already in cache + if (sequence_objects_cache.find(hash_key) != + sequence_objects_cache.end()) { + LOG_DEBUG("Sequence %s already exists in cache!", + sequence_object->seq_name.c_str()); + return false; + } + + sequence_objects_cache.insert( + std::make_pair(hash_key, sequence_object)); + return true; +} + +/*@brief evict sequence catalog object from cache + * @param sequence_name + * @param database_oid + * @return true if specified sequence is found and evicted; + * false if not found + */ +bool CatalogCache::EvictSequenceObject(const std::string & sequence_name, + oid_t database_oid) { + std::size_t hash_key = GetHashKey(sequence_name, database_oid); + + auto it = sequence_objects_cache.find(hash_key); + if (it == sequence_objects_cache.end()) { + return false; // sequence not found in cache + } + + auto sequence_object = it->second; + PELOTON_ASSERT(sequence_object); + sequence_objects_cache.erase(it); + return true; +} + +/*@brief get sequence catalog object from cache + * @param sequence_name + * @param database_oid + * @return sequence catalog object; if not found return object with invalid oid + */ +std::shared_ptr CatalogCache::GetSequenceObject( + const std::string & sequence_name, oid_t database_oid) { + std::size_t hash_key = GetHashKey(sequence_name, database_oid); + auto it = sequence_objects_cache.find(hash_key); + if (it == sequence_objects_cache.end()) { + return nullptr; + } + return it->second; +} + +/*@brief get the hash key given the sequence information + * @param sequence_name + * @param database_oid + * @return hash key + */ +std::size_t CatalogCache::GetHashKey(const std::string sequence_name, + oid_t database_oid) { + std::tuple key(sequence_name, database_oid); + boost::hash> key_hash; + return key_hash(key); +} + } // namespace catalog } // namespace peloton diff --git a/src/catalog/column_stats_catalog.cpp b/src/catalog/column_stats_catalog.cpp index bbe94340cdb..8d896b4ac90 100644 --- a/src/catalog/column_stats_catalog.cpp +++ b/src/catalog/column_stats_catalog.cpp @@ -45,12 +45,12 @@ ColumnStatsCatalog::ColumnStatsCatalog(concurrency::TransactionContext *txn) txn) { // unique key: (database_id, table_id, column_id) Catalog::GetInstance()->CreateIndex( - CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, COLUMN_STATS_CATALOG_NAME, + CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, CATALOG_SCHEMA_NAME, COLUMN_STATS_CATALOG_NAME, {0, 1, 2}, COLUMN_STATS_CATALOG_NAME "_skey0", true, IndexType::BWTREE, txn); // non-unique key: (database_id, table_id) Catalog::GetInstance()->CreateIndex( - CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, COLUMN_STATS_CATALOG_NAME, + CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, CATALOG_SCHEMA_NAME, COLUMN_STATS_CATALOG_NAME, {0, 1}, COLUMN_STATS_CATALOG_NAME "_skey1", false, IndexType::BWTREE, txn); } diff --git a/src/catalog/database_catalog.cpp b/src/catalog/database_catalog.cpp index fc0b81c64d0..08ebf65edef 100644 --- a/src/catalog/database_catalog.cpp +++ b/src/catalog/database_catalog.cpp @@ -141,28 +141,65 @@ std::shared_ptr DatabaseCatalogObject::GetTableObject( or all the way from storage (cached_only == false) * @param table_name table name of the requested table catalog object * @param schema_name schema name of the requested table catalog object + * @param session_namespace session namespace of the session that transaction running on. * @param cached_only if cached only, return nullptr on a cache miss * @return Shared pointer to the requested table catalog object */ std::shared_ptr DatabaseCatalogObject::GetTableObject( const std::string &table_name, const std::string &schema_name, + const std::string &session_namespace, bool cached_only) { - std::string key = schema_name + "." + table_name; - auto it = table_name_cache.find(key); - if (it != table_name_cache.end()) { - return it->second; - } + //no schema specified + if (schema_name.empty()) { + //search under temporary namespace + std::string key = session_namespace + "." + table_name; + auto it = table_name_cache.find(key); + if (it != table_name_cache.end()) return it->second; - if (cached_only) { - // cache miss return empty object - return nullptr; - } else { // cache miss get from pg_table auto pg_table = Catalog::GetInstance() - ->GetSystemCatalogs(database_oid) - ->GetTableCatalog(); - return pg_table->GetTableObject(table_name, schema_name, txn); + ->GetSystemCatalogs(database_oid) + ->GetTableCatalog(); + auto table_object = pg_table->GetTableObject(table_name, session_namespace, txn); + if (table_object == nullptr) { + //search under public namespace + return GetTableObjectHelper(table_name, DEFAULT_SCHEMA_NAME, cached_only); + } + return table_object; } + //search under a specific namespace + return GetTableObjectHelper(table_name, schema_name, cached_only); +} + +/* @brief helper to get table catalog object + * @param table_name table name of the requested table catalog object + * @param schema_name schema name of the requested table catalog object +<<<<<<< HEAD + * @param session_namespace the session namespace of the requested table catalog object +======= +>>>>>>> 03b45a2ef9dafd0e5a83a80deac32f845246425e + * @param cached_only if cached only, return nullptr on a cache miss + * @return Shared pointer to the requested table catalog object + */ +std::shared_ptr DatabaseCatalogObject::GetTableObjectHelper( + const std::string &table_name, const std::string &schema_name, + bool cached_only) { + std::string key = schema_name + "." + table_name; + auto it = table_name_cache.find(key); + if (it != table_name_cache.end()) { + return it->second; + } + + if (cached_only) { + // cache miss return empty object + return nullptr; + } else { + // cache miss get from pg_table + auto pg_table = Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetTableCatalog(); + return pg_table->GetTableObject(table_name, schema_name, txn); + } } /*@brief Get table catalog object from cache (cached_only == true), diff --git a/src/catalog/language_catalog.cpp b/src/catalog/language_catalog.cpp index ddcceb6d89d..ef272b1a6ea 100644 --- a/src/catalog/language_catalog.cpp +++ b/src/catalog/language_catalog.cpp @@ -40,7 +40,7 @@ LanguageCatalog::LanguageCatalog(concurrency::TransactionContext *txn) "lanname VARCHAR NOT NULL);", txn) { Catalog::GetInstance()->CreateIndex( - CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, LANGUAGE_CATALOG_NAME, {1}, + CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME,CATALOG_SCHEMA_NAME, LANGUAGE_CATALOG_NAME, {1}, LANGUAGE_CATALOG_NAME "_skey0", false, IndexType::BWTREE, txn); } diff --git a/src/catalog/proc_catalog.cpp b/src/catalog/proc_catalog.cpp index 6da75db67fc..1442a0fed42 100644 --- a/src/catalog/proc_catalog.cpp +++ b/src/catalog/proc_catalog.cpp @@ -56,7 +56,7 @@ ProcCatalog::ProcCatalog(concurrency::TransactionContext *txn) "prosrc VARCHAR NOT NULL);", txn) { Catalog::GetInstance()->CreateIndex( - CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, PROC_CATALOG_NAME, {1, 3}, + CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, CATALOG_SCHEMA_NAME, PROC_CATALOG_NAME, {1, 3}, PROC_CATALOG_NAME "_skey0", false, IndexType::BWTREE, txn); } diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp new file mode 100644 index 00000000000..89355120aff --- /dev/null +++ b/src/catalog/sequence_catalog.cpp @@ -0,0 +1,307 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence_catalog.h +// +// Identification: src/catalog/sequence_catalog.cpp +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include + +#include "catalog/sequence_catalog.h" + +#include "catalog/catalog.h" +#include "catalog/database_catalog.h" +#include "catalog/table_catalog.h" +#include "common/internal_types.h" +#include "storage/data_table.h" +#include "type/value_factory.h" +#include "function/functions.h" +#include "planner/update_plan.h" +#include "executor/update_executor.h" +#include "executor/executor_context.h" +#include "optimizer/optimizer.h" +#include "parser/postgresparser.h" + +namespace peloton { +namespace catalog { + +/* @brief Get the nextval of the sequence + * @return the next value of the sequence. + * @exception throws SequenceException if the sequence exceeds the upper/lower + * limit. + */ +int64_t SequenceCatalogObject::GetNextVal() { + int64_t result = seq_curr_val; + seq_prev_val = result; + if (seq_increment > 0) { + // Check to see whether the nextval is out of bound + if ((seq_max >= 0 && seq_curr_val > seq_max - seq_increment) || + (seq_max < 0 && seq_curr_val + seq_increment > seq_max)) { + if (!seq_cycle) { + throw SequenceException( + StringUtil::Format( + "nextval: reached maximum value of sequence %s (%ld)", seq_name.c_str(), seq_max)); + } + seq_curr_val = seq_min; + } else + seq_curr_val += seq_increment; + } else { + // Check to see whether the nextval is out of bound + if ((seq_min < 0 && seq_curr_val < seq_min - seq_increment) || + (seq_min >= 0 && seq_curr_val + seq_increment < seq_min)) { + if (!seq_cycle) { + throw SequenceException( + StringUtil::Format( + "nextval: reached minimum value of sequence %s (%ld)", seq_name.c_str(), seq_min)); + } + seq_curr_val = seq_max; + } else + seq_curr_val += seq_increment; + } + + Catalog::GetInstance()->GetSystemCatalogs(db_oid) + ->GetSequenceCatalog() + ->UpdateNextVal(seq_oid, seq_curr_val, txn_); + return result; +} + +SequenceCatalog::SequenceCatalog(const std::string &database_name, + concurrency::TransactionContext *txn) + : AbstractCatalog("CREATE TABLE " + database_name + + "." CATALOG_SCHEMA_NAME "." SEQUENCE_CATALOG_NAME + " (" + "oid INT NOT NULL PRIMARY KEY, " + "sqdboid INT NOT NULL, " + "sqname VARCHAR NOT NULL, " + "sqinc BIGINT NOT NULL, " + "sqmax BIGINT NOT NULL, " + "sqmin BIGINT NOT NULL, " + "sqstart BIGINT NOT NULL, " + "sqcycle BOOLEAN NOT NULL, " + "sqval BIGINT NOT NULL);", + txn) { + Catalog::GetInstance()->CreateIndex( + database_name, CATALOG_SCHEMA_NAME, CATALOG_SCHEMA_NAME, SEQUENCE_CATALOG_NAME, + {ColumnId::DATABSE_OID, ColumnId::SEQUENCE_NAME}, + SEQUENCE_CATALOG_NAME "_skey0", false, IndexType::BWTREE, txn); +} + +SequenceCatalog::~SequenceCatalog() {} + +/* @brief Insert the sequence by name. + * @param database_oid the databse_oid associated with the sequence + * @param sequence_name the name of the sequence + * @param seq_increment the increment per step of the sequence + * @param seq_max the max value of the sequence + * @param seq_min the min value of the sequence + * @param seq_start the start of the sequence + * @param seq_cycle whether the sequence cycles + * @param pool an instance of abstract pool + * @param txn current transaction + * @return ResultType::SUCCESS if the sequence exists, ResultType::FAILURE + * otherwise. + * @exception throws SequenceException if the sequence already exists. + */ +bool SequenceCatalog::InsertSequence(oid_t database_oid, + std::string sequence_name, + int64_t seq_increment, int64_t seq_max, + int64_t seq_min, int64_t seq_start, + bool seq_cycle, type::AbstractPool *pool, + concurrency::TransactionContext *txn) { + LOG_DEBUG("Insert Sequence Database Oid: %u", database_oid); + LOG_DEBUG("Insert Sequence Sequence Name: %s", sequence_name.c_str()); + + ValidateSequenceArguments(seq_increment, seq_max, seq_min, seq_start); + if (GetSequence(database_oid, sequence_name, txn) != nullptr) { + throw SequenceException( + StringUtil::Format("Sequence %s already exists!", + sequence_name.c_str())); + } + + std::unique_ptr tuple( + new storage::Tuple(catalog_table_->GetSchema(), true)); + + auto val0 = type::ValueFactory::GetIntegerValue(GetNextOid()); + auto val1 = type::ValueFactory::GetIntegerValue(database_oid); + auto val2 = type::ValueFactory::GetVarcharValue(sequence_name); + auto val3 = type::ValueFactory::GetBigIntValue(seq_increment); + auto val4 = type::ValueFactory::GetBigIntValue(seq_max); + auto val5 = type::ValueFactory::GetBigIntValue(seq_min); + auto val6 = type::ValueFactory::GetBigIntValue(seq_start); + auto val7 = type::ValueFactory::GetBooleanValue(seq_cycle); + // When insert value, seqval = seq_start + auto val8 = type::ValueFactory::GetBigIntValue(seq_start); + + tuple->SetValue(ColumnId::SEQUENCE_OID, val0, pool); + tuple->SetValue(ColumnId::DATABSE_OID, val1, pool); + tuple->SetValue(ColumnId::SEQUENCE_NAME, val2, pool); + tuple->SetValue(ColumnId::SEQUENCE_INC, val3, pool); + tuple->SetValue(ColumnId::SEQUENCE_MAX, val4, pool); + tuple->SetValue(ColumnId::SEQUENCE_MIN, val5, pool); + tuple->SetValue(ColumnId::SEQUENCE_START, val6, pool); + tuple->SetValue(ColumnId::SEQUENCE_CYCLE, val7, pool); + tuple->SetValue(ColumnId::SEQUENCE_VALUE, val8, pool); + + // Insert the tuple + return InsertTuple(std::move(tuple), txn); +} + +/* @brief Delete the sequence by name. + * @param database_name the database name associated with the sequence + * @param sequence_name the name of the sequence + * @param txn current transaction + * @return ResultType::SUCCESS if the sequence exists, throw exception + * otherwise. + */ +ResultType SequenceCatalog::DropSequence(const std::string &database_name, + const std::string &sequence_name, + concurrency::TransactionContext *txn) { + if (txn == nullptr) { + throw CatalogException("Transaction is invalid!"); + } + + auto database_object = + Catalog::GetInstance()->GetDatabaseObject(database_name, txn); + + oid_t database_oid = database_object->GetDatabaseOid(); + + oid_t sequence_oid = Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetSequenceCatalog() + ->GetSequenceOid(sequence_name, database_oid, txn); + if (sequence_oid == INVALID_OID) { + throw SequenceException( + StringUtil::Format("Sequence %s does not exist!", + sequence_name.c_str())); + } + + LOG_INFO("sequence %d will be deleted!", sequence_oid); + + DeleteSequenceByName(sequence_name, database_oid, txn); + EvictSequenceNameCurrValCache(sequence_name); + + return ResultType::SUCCESS; +} + +/* @brief Delete the sequence by name. The sequence is guaranteed to exist. + * @param database_oid the databse_oid associated with the sequence + * @param sequence_name the name of the sequence + * @param txn current transaction + * @return The result of DeleteWithIndexScan. + */ +bool SequenceCatalog::DeleteSequenceByName( + const std::string &sequence_name, oid_t database_oid, + concurrency::TransactionContext *txn) { + oid_t index_offset = IndexId::DBOID_SEQNAME_KEY; + std::vector values; + values.push_back(type::ValueFactory::GetIntegerValue(database_oid).Copy()); + values.push_back(type::ValueFactory::GetVarcharValue(sequence_name).Copy()); + + return DeleteWithIndexScan(index_offset, values, txn); +} + +/* @brief get sequence from pg_sequence table + * @param database_oid the databse_oid associated with the sequence + * @param sequence_name the name of the sequence + * @param txn current transaction + * @return a SequenceCatalogObject if the sequence is found, nullptr otherwise + */ +std::shared_ptr SequenceCatalog::GetSequence( + oid_t database_oid, const std::string &sequence_name, + concurrency::TransactionContext *txn) { + std::vector column_ids( + {ColumnId::SEQUENCE_OID, ColumnId::SEQUENCE_START, + ColumnId::SEQUENCE_INC, ColumnId::SEQUENCE_MAX, + ColumnId::SEQUENCE_MIN, ColumnId::SEQUENCE_CYCLE, + ColumnId::SEQUENCE_VALUE}); + oid_t index_offset = IndexId::DBOID_SEQNAME_KEY; + std::vector values; + values.push_back(type::ValueFactory::GetIntegerValue(database_oid).Copy()); + values.push_back(type::ValueFactory::GetVarcharValue(sequence_name).Copy()); + + // the result is a vector of executor::LogicalTile + auto result_tiles = + GetResultWithIndexScan(column_ids, index_offset, values, txn); + // careful! the result tile could be null! + if (result_tiles == nullptr || result_tiles->size() == 0) { + LOG_INFO("no sequence on database %d and %s", database_oid, + sequence_name.c_str()); + return std::shared_ptr(nullptr); + } else { + LOG_INFO("size of the result tiles = %lu", result_tiles->size()); + } + + PELOTON_ASSERT(result_tiles->size() == 1); + size_t tuple_count = (*result_tiles)[0]->GetTupleCount(); + PELOTON_ASSERT(tuple_count == 1); + (void) tuple_count; + auto new_sequence = std::make_shared( + (*result_tiles)[0]->GetValue(0, 0).GetAs(), + database_oid, + sequence_name, + (*result_tiles)[0]->GetValue(0, 1).GetAs(), + (*result_tiles)[0]->GetValue(0, 2).GetAs(), + (*result_tiles)[0]->GetValue(0, 3).GetAs(), + (*result_tiles)[0]->GetValue(0, 4).GetAs(), + (*result_tiles)[0]->GetValue(0, 5).GetAs(), + (*result_tiles)[0]->GetValue(0, 6).GetAs(), txn); + + return new_sequence; +} + +/* @brief update the next value of the sequence in the underlying storage + * @param sequence_oid the sequence_oid of the sequence + * @param nextval the nextval of the sequence + * @param txn current transaction + * @return the result of the transaction + */ +bool SequenceCatalog::UpdateNextVal(oid_t sequence_oid, int64_t nextval, + concurrency::TransactionContext *txn){ + std::vector update_columns({SequenceCatalog::ColumnId::SEQUENCE_VALUE}); + std::vector update_values; + update_values.push_back(type::ValueFactory::GetBigIntValue(nextval).Copy()); + std::vector scan_values; + scan_values.push_back(type::ValueFactory::GetIntegerValue(sequence_oid).Copy()); + oid_t index_offset = SequenceCatalog::IndexId::PRIMARY_KEY; + + return UpdateWithIndexScan(update_columns, update_values, scan_values, index_offset, txn); +} + +/* @brief get sequence oid from pg_sequence table given sequence_name and + * database_oid + * @param database_oid the databse_oid associated with the sequence + * @param sequence_name the name of the sequence + * @param txn current transaction + * @return the oid_t of the sequence if the sequence is found, INVALID_OID + * otherwise + */ +oid_t SequenceCatalog::GetSequenceOid(std::string sequence_name, + oid_t database_oid, + concurrency::TransactionContext *txn) { + std::vector column_ids({ColumnId::SEQUENCE_OID}); + oid_t index_offset = IndexId::DBOID_SEQNAME_KEY; + std::vector values; + values.push_back(type::ValueFactory::GetIntegerValue(database_oid).Copy()); + values.push_back(type::ValueFactory::GetVarcharValue(sequence_name).Copy()); + + // the result is a vector of executor::LogicalTile + auto result_tiles = + GetResultWithIndexScan(column_ids, index_offset, values, txn); + // careful! the result tile could be null! + if (result_tiles == nullptr || result_tiles->size() == 0) { + LOG_INFO("no sequence on database %d and %s", database_oid, + sequence_name.c_str()); + return INVALID_OID; + } + + PELOTON_ASSERT(result_tiles->size() == 1); + return (*result_tiles)[0]->GetValue(0, 0).GetAs(); +} + +} // namespace catalog +} // namespace peloton diff --git a/src/catalog/settings_catalog.cpp b/src/catalog/settings_catalog.cpp index bcdc518af24..fdb76bf3b32 100644 --- a/src/catalog/settings_catalog.cpp +++ b/src/catalog/settings_catalog.cpp @@ -43,7 +43,7 @@ SettingsCatalog::SettingsCatalog(concurrency::TransactionContext *txn) txn) { // Add secondary index here if necessary Catalog::GetInstance()->CreateIndex( - CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, SETTINGS_CATALOG_NAME, {0}, + CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, CATALOG_SCHEMA_NAME, SETTINGS_CATALOG_NAME, {0}, SETTINGS_CATALOG_NAME "_skey0", false, IndexType::BWTREE, txn); } diff --git a/src/catalog/system_catalogs.cpp b/src/catalog/system_catalogs.cpp index b1371ddd379..dedea74271b 100644 --- a/src/catalog/system_catalogs.cpp +++ b/src/catalog/system_catalogs.cpp @@ -30,6 +30,7 @@ SystemCatalogs::SystemCatalogs(storage::Database *database, type::AbstractPool *pool, concurrency::TransactionContext *txn) : pg_trigger_(nullptr), + pg_sequence_(nullptr), pg_table_metrics_(nullptr), pg_index_metrics_(nullptr), pg_query_metrics_(nullptr) { @@ -69,6 +70,7 @@ SystemCatalogs::~SystemCatalogs() { delete pg_attribute_; delete pg_namespace_; if (pg_trigger_) delete pg_trigger_; + if (pg_sequence_) delete pg_sequence_; // if (pg_proc) delete pg_proc; if (pg_table_metrics_) delete pg_table_metrics_; if (pg_index_metrics_) delete pg_index_metrics_; @@ -87,6 +89,10 @@ void SystemCatalogs::Bootstrap(const std::string &database_name, pg_trigger_ = new TriggerCatalog(database_name, txn); } + if (!pg_sequence_) { + pg_sequence_ = new SequenceCatalog(database_name, txn); + } + // if (!pg_proc) { // pg_proc = new ProcCatalog(database_name, txn); // } diff --git a/src/catalog/table_catalog.cpp b/src/catalog/table_catalog.cpp index 34ef723e366..44c17df52b9 100644 --- a/src/catalog/table_catalog.cpp +++ b/src/catalog/table_catalog.cpp @@ -489,7 +489,7 @@ std::shared_ptr TableCatalog::GetTableObject( auto database_object = txn->catalog_cache.GetDatabaseObject(database_oid); if (database_object) { auto table_object = - database_object->GetTableObject(table_name, schema_name, true); + database_object->GetTableObject(table_name, schema_name, std::string(), true); if (table_object) return table_object; } @@ -561,6 +561,24 @@ TableCatalog::GetTableObjects(concurrency::TransactionContext *txn) { return database_object->GetTableObjects(); } +/*@brief read table catalog objects from pg_table using schema_name + * @param schema_name the schema name we want to search + * @param txn TransactionContext + * @return table catalog objects + */ +std::vector> +TableCatalog::GetTableObjects(const std::string &schema_name, concurrency::TransactionContext *txn) { + //get all the table. + auto tables = GetTableObjects(txn); + std::vector> result; + for (auto it : tables) { + if (it.second->GetSchemaName() == schema_name) { + result.push_back(it.second); + } + } + return result; +} + /*@brief update version id column within pg_table * @param update_val the new(updated) version id * @param table_oid which table to be updated diff --git a/src/catalog/trigger_catalog.cpp b/src/catalog/trigger_catalog.cpp index 1474dd20d4c..faef138add7 100644 --- a/src/catalog/trigger_catalog.cpp +++ b/src/catalog/trigger_catalog.cpp @@ -38,17 +38,17 @@ TriggerCatalog::TriggerCatalog(const std::string &database_name, txn) { // Add secondary index here if necessary Catalog::GetInstance()->CreateIndex( - database_name, CATALOG_SCHEMA_NAME, TRIGGER_CATALOG_NAME, + database_name, CATALOG_SCHEMA_NAME, CATALOG_SCHEMA_NAME, TRIGGER_CATALOG_NAME, {ColumnId::TABLE_OID, ColumnId::TRIGGER_TYPE}, TRIGGER_CATALOG_NAME "_skey0", false, IndexType::BWTREE, txn); Catalog::GetInstance()->CreateIndex( - database_name, CATALOG_SCHEMA_NAME, TRIGGER_CATALOG_NAME, + database_name, CATALOG_SCHEMA_NAME, CATALOG_SCHEMA_NAME, TRIGGER_CATALOG_NAME, {ColumnId::TABLE_OID}, TRIGGER_CATALOG_NAME "_skey1", false, IndexType::BWTREE, txn); Catalog::GetInstance()->CreateIndex( - database_name, CATALOG_SCHEMA_NAME, TRIGGER_CATALOG_NAME, + database_name, CATALOG_SCHEMA_NAME, CATALOG_SCHEMA_NAME, TRIGGER_CATALOG_NAME, {ColumnId::TRIGGER_NAME, ColumnId::TABLE_OID}, TRIGGER_CATALOG_NAME "_skey2", false, IndexType::BWTREE, txn); } diff --git a/src/catalog/zone_map_catalog.cpp b/src/catalog/zone_map_catalog.cpp index ec59dd24d82..687cd3bc89c 100644 --- a/src/catalog/zone_map_catalog.cpp +++ b/src/catalog/zone_map_catalog.cpp @@ -45,7 +45,7 @@ ZoneMapCatalog::ZoneMapCatalog(concurrency::TransactionContext *txn) "type VARCHAR);", txn) { Catalog::GetInstance()->CreateIndex( - CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, ZONE_MAP_CATALOG_NAME, + CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, CATALOG_SCHEMA_NAME, ZONE_MAP_CATALOG_NAME, {0, 1, 2, 3}, ZONE_MAP_CATALOG_NAME "_skey0", true, IndexType::BWTREE, txn); } diff --git a/src/codegen/proxy/sequence_functions_proxy.cpp b/src/codegen/proxy/sequence_functions_proxy.cpp new file mode 100644 index 00000000000..79694a33773 --- /dev/null +++ b/src/codegen/proxy/sequence_functions_proxy.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence_functions_proxy.cpp +// +// Identification: src/codegen/proxy/sequence_functions_proxy.cpp +// +// Copyright (c) 2015-2017, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include "codegen/proxy/sequence_functions_proxy.h" + +#include "codegen/proxy/executor_context_proxy.h" + +namespace peloton { +namespace codegen { + +DEFINE_METHOD(peloton::function, SequenceFunctions, Nextval); +DEFINE_METHOD(peloton::function, SequenceFunctions, Currval); + +} // namespace codegen +} // namespace peloton diff --git a/src/codegen/type/bigint_type.cpp b/src/codegen/type/bigint_type.cpp index e20e3e0396f..8c2613d08ba 100644 --- a/src/codegen/type/bigint_type.cpp +++ b/src/codegen/type/bigint_type.cpp @@ -14,10 +14,12 @@ #include "codegen/lang/if.h" #include "codegen/value.h" +#include "codegen/proxy/sequence_functions_proxy.h" #include "codegen/proxy/values_runtime_proxy.h" #include "codegen/type/boolean_type.h" #include "codegen/type/decimal_type.h" #include "codegen/type/integer_type.h" +#include "codegen/type/varchar_type.h" #include "common/exception.h" #include "type/limits.h" #include "util/string_util.h" @@ -503,6 +505,47 @@ struct Modulo : public TypeSystem::BinaryOperatorHandleNull { } }; +// Nextval +struct Nextval : public TypeSystem::UnaryOperatorHandleNull { + bool SupportsType(const Type &type) const override { + return type.GetSqlType() == Varchar::Instance(); + } + + Type ResultType(UNUSED_ATTRIBUTE const Type &val_type) const override { + return BigInt::Instance(); + } + + Value Impl(CodeGen &codegen, const Value &val, + const TypeSystem::InvocationContext &ctx) const override { + llvm::Value *executor_ctx = ctx.executor_context; + llvm::Value *raw_ret = + codegen.Call(SequenceFunctionsProxy::Nextval, + {executor_ctx, val.GetValue()}); + return Value{BigInt::Instance(), raw_ret}; + } +}; + +// Currval +struct Currval : public TypeSystem::UnaryOperatorHandleNull { + bool SupportsType(const Type &type) const override { + return type.GetSqlType() == Varchar::Instance(); + } + + Type ResultType(UNUSED_ATTRIBUTE const Type &val_type) const override { + return BigInt::Instance(); + } + + Value Impl(CodeGen &codegen, const Value &val, + const TypeSystem::InvocationContext &ctx) const override { + llvm::Value *executor_ctx = ctx.executor_context; + llvm::Value *raw_ret = + codegen.Call(SequenceFunctionsProxy::Currval, + {executor_ctx, val.GetValue()}); + return Value{BigInt::Instance(), raw_ret}; + } +}; + + //////////////////////////////////////////////////////////////////////////////// /// /// Function tables @@ -538,12 +581,16 @@ Abs kAbsOp; Ceil kCeilOp; Floor kFloorOp; Sqrt kSqrt; +Nextval kNextval; +Currval kCurrval; std::vector kUnaryOperatorTable = { {OperatorId::Negation, kNegOp}, {OperatorId::Abs, kAbsOp}, {OperatorId::Ceil, kCeilOp}, {OperatorId::Floor, kFloorOp}, - {OperatorId::Sqrt, kSqrt}}; + {OperatorId::Sqrt, kSqrt}, + {OperatorId::Nextval, kNextval}, + {OperatorId::Currval, kCurrval}}; // Binary operations Add kAddOp; diff --git a/src/common/internal_types.cpp b/src/common/internal_types.cpp index 6d95bf1a35c..b4dfc84e793 100644 --- a/src/common/internal_types.cpp +++ b/src/common/internal_types.cpp @@ -329,6 +329,9 @@ std::string CreateTypeToString(CreateType type) { case CreateType::TRIGGER: { return "TRIGGER"; } + case CreateType::SEQUENCE: { + return "SEQUENCE"; + } case CreateType::SCHEMA: { return "SCHEMA"; } @@ -391,6 +394,9 @@ std::string DropTypeToString(DropType type) { case DropType::SCHEMA: { return "SCHEMA"; } + case DropType::SEQUENCE: { + return "SEQUENCE"; + } default: { throw ConversionException( StringUtil::Format("No string conversion for DropType value '%d'", @@ -416,6 +422,8 @@ DropType StringToDropType(const std::string &str) { return DropType::TRIGGER; } else if (upper_str == "SCHEMA") { return DropType::SCHEMA; + } else if (upper_str == "SEQUENCE") { + return DropType::SEQUENCE; } else { throw ConversionException(StringUtil::Format( "No DropType conversion from string '%s'", upper_str.c_str())); @@ -557,6 +565,8 @@ std::string QueryTypeToString(QueryType query_type) { return "CREATE TRIGGER"; case QueryType::QUERY_CREATE_SCHEMA: return "CREATE SCHEMA"; + case QueryType::QUERY_CREATE_SEQUENCE: + return "CREATE SEQUENCE"; case QueryType::QUERY_CREATE_VIEW: return "CREATE VIEW"; case QueryType::QUERY_DROP: @@ -618,6 +628,7 @@ QueryType StringToQueryType(const std::string &str) { {"CREATE TRIGGER", QueryType::QUERY_CREATE_TRIGGER}, {"CREATE SCHEMA", QueryType::QUERY_CREATE_SCHEMA}, {"CREATE VIEW", QueryType::QUERY_CREATE_VIEW}, + {"CREATE SEQUENCE", QueryType::QUERY_CREATE_SEQUENCE}, {"OTHER", QueryType::QUERY_OTHER}, }; std::unordered_map::iterator it = @@ -688,6 +699,9 @@ QueryType StatementTypeToQueryType(StatementType stmt_type, case parser::CreateStatement::CreateType::kView: query_type = QueryType::QUERY_CREATE_VIEW; break; + case parser::CreateStatement::CreateType::kSequence: + query_type = QueryType::QUERY_CREATE_SEQUENCE; + break; } break; } diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index 83e85c92c48..985e2b0164e 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -11,13 +11,13 @@ //===----------------------------------------------------------------------===// #include "executor/create_executor.h" - +#include "common/exception.h" #include "catalog/catalog.h" #include "catalog/foreign_key.h" #include "catalog/system_catalogs.h" +#include "catalog/sequence_catalog.h" #include "concurrency/transaction_context.h" #include "executor/executor_context.h" -#include "planner/create_plan.h" #include "storage/database.h" #include "storage/storage_manager.h" #include "type/value_factory.h" @@ -74,6 +74,12 @@ bool CreateExecutor::DExecute() { break; } + // if query was for creating sequence + case CreateType::SEQUENCE: { + result = CreateSequence(node); + break; + } + default: { std::string create_type = CreateTypeToString(node.GetCreateType()); LOG_ERROR("Not supported create type %s", create_type.c_str()); @@ -117,25 +123,40 @@ bool CreateExecutor::CreateTable(const planner::CreatePlan &node) { std::string table_name = node.GetTableName(); std::string schema_name = node.GetSchemaName(); std::string database_name = node.GetDatabaseName(); + std::string session_namespace = node.GetSessionNamespace(); std::unique_ptr schema(node.GetSchema()); + //check foreign key schema first + CheckForeignKeySchema(schema_name, database_name, session_namespace, node, current_txn); + ResultType result = catalog::Catalog::GetInstance()->CreateTable( database_name, schema_name, table_name, std::move(schema), current_txn); current_txn->SetResult(result); - + current_txn->SetCommitOption(node.GetCommitOption()); if (current_txn->GetResult() == ResultType::SUCCESS) { + //if created a temp table. + if (schema_name.find(TEMP_NAMESPACE_PREFIX) != std::string::npos) { + auto catalog = catalog::Catalog::GetInstance(); + //get the table object + auto table_object = catalog->GetTableObject(database_name, schema_name, session_namespace, + table_name, current_txn); + //record the table oid if we need to delete rows or drop the temp table. + if (node.GetCommitOption() == ONCOMMIT_DROP || node.GetCommitOption() == ONCOMMIT_DELETE_ROWS) { + current_txn->AddTempTableObject(table_object); + } + } LOG_TRACE("Creating table succeeded!"); // Add the foreign key constraint (or other multi-column constraints) if (node.GetForeignKeys().empty() == false) { int count = 1; auto catalog = catalog::Catalog::GetInstance(); - auto source_table = catalog->GetTableWithName(database_name, schema_name, + auto source_table = catalog->GetTableWithName(database_name, schema_name, session_namespace, table_name, current_txn); for (auto fk : node.GetForeignKeys()) { auto sink_table = catalog->GetTableWithName( - database_name, schema_name, fk.sink_table_name, current_txn); + database_name, fk.sink_table_schema, session_namespace, fk.sink_table_name, current_txn); // Source Column Offsets std::vector source_col_ids; for (auto col_name : fk.foreign_key_sources) { @@ -182,7 +203,7 @@ bool CreateExecutor::CreateTable(const planner::CreatePlan &node) { std::vector source_col_names = fk.foreign_key_sources; std::string index_name = table_name + "_FK_" + sink_table->GetName() + "_" + std::to_string(count); - catalog->CreateIndex(database_name, schema_name, table_name, + catalog->CreateIndex(database_name, schema_name, session_namespace, table_name, source_col_ids, index_name, false, IndexType::BWTREE, current_txn); count++; @@ -209,19 +230,48 @@ bool CreateExecutor::CreateTable(const planner::CreatePlan &node) { return (true); } +//check whether the foriegn key schema and the current schema are not only one in temp. +void CreateExecutor::CheckForeignKeySchema( + const std::string &schema_name, const std::string &database_name, + const std::string &session_namespace, const planner::CreatePlan &node, + concurrency::TransactionContext *txn) { + for (auto fk : node.GetForeignKeys()) { + auto catalog = catalog::Catalog::GetInstance(); + //get table obejct for use + auto sink_table_object = catalog->GetTableObject(database_name, fk.sink_table_schema, + session_namespace, fk.sink_table_name, txn); + std::string sink_table_schema = sink_table_object->GetSchemaName(); + //if target is under temp but current not. + if (schema_name.find(TEMP_NAMESPACE_PREFIX) == std::string::npos) { + if (sink_table_schema.find(TEMP_NAMESPACE_PREFIX) != std::string::npos) { + throw ConstraintException("ERROR: constraints on permanent tables may reference only permanent tables"); + } + } + + //if current is temp, but target is not + if (schema_name.find(TEMP_NAMESPACE_PREFIX) != std::string::npos) { + if (sink_table_schema.find(TEMP_NAMESPACE_PREFIX) == std::string::npos) { + throw ConstraintException("ERROR: constraints on temporary tables may reference only temporary tables"); + } + } + } +} + bool CreateExecutor::CreateIndex(const planner::CreatePlan &node) { auto txn = context_->GetTransaction(); std::string database_name = node.GetDatabaseName(); std::string schema_name = node.GetSchemaName(); std::string table_name = node.GetTableName(); std::string index_name = node.GetIndexName(); + std::string session_namespace = node.GetSessionNamespace(); bool unique_flag = node.IsUnique(); IndexType index_type = node.GetIndexType(); auto key_attrs = node.GetKeyAttrs(); ResultType result = catalog::Catalog::GetInstance()->CreateIndex( - database_name, schema_name, table_name, key_attrs, index_name, + database_name, schema_name, session_namespace, + table_name, key_attrs, index_name, unique_flag, index_type, txn); txn->SetResult(result); @@ -241,10 +291,11 @@ bool CreateExecutor::CreateTrigger(const planner::CreatePlan &node) { std::string schema_name = node.GetSchemaName(); std::string table_name = node.GetTableName(); std::string trigger_name = node.GetTriggerName(); + std::string session_namespace = node.GetSessionNamespace(); trigger::Trigger newTrigger(node); auto table_object = catalog::Catalog::GetInstance()->GetTableObject( - database_name, schema_name, table_name, txn); + database_name, schema_name, session_namespace, table_name, txn); // durable trigger: insert the information of this trigger in the trigger // catalog table @@ -268,7 +319,7 @@ bool CreateExecutor::CreateTrigger(const planner::CreatePlan &node) { // ask target table to update its trigger list variable storage::DataTable *target_table = catalog::Catalog::GetInstance()->GetTableWithName( - database_name, schema_name, table_name, txn); + database_name, schema_name, session_namespace, table_name, txn); target_table->UpdateTriggerListFromCatalog(txn); // hardcode SUCCESS result for txn @@ -281,5 +332,37 @@ bool CreateExecutor::CreateTrigger(const planner::CreatePlan &node) { return (true); } +bool CreateExecutor::CreateSequence(const planner::CreatePlan &node) { + auto txn = context_->GetTransaction(); + std::string database_name = node.GetDatabaseName(); + std::string sequence_name = node.GetSequenceName(); + + auto database_object = catalog::Catalog::GetInstance()->GetDatabaseObject( + database_name, txn); + + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetSequenceCatalog() + ->InsertSequence( + database_object->GetDatabaseOid(), sequence_name, + node.GetSequenceIncrement(), node.GetSequenceMaxValue(), + node.GetSequenceMinValue(), node.GetSequenceStart(), + node.GetSequenceCycle(), pool_.get(), txn); + + if (txn->GetResult() == ResultType::SUCCESS) { + LOG_DEBUG("Creating sequence succeeded!"); + } else if (txn->GetResult() == ResultType::FAILURE) { + LOG_DEBUG("Creating sequence failed!"); + } else { + LOG_DEBUG("Result is: %s", + ResultTypeToString(txn->GetResult()).c_str()); + } + + // Notice this action will always return true, since any exception + // will be handled in CreateSequence function in SequenceCatalog. + return (true); +} + + } // namespace executor } // namespace peloton diff --git a/src/executor/drop_executor.cpp b/src/executor/drop_executor.cpp index b9413366c2e..e8b16ef14e8 100644 --- a/src/executor/drop_executor.cpp +++ b/src/executor/drop_executor.cpp @@ -65,6 +65,10 @@ bool DropExecutor::DExecute() { result = DropIndex(node, current_txn); break; } + case DropType::SEQUENCE:{ + result = DropSequence(node, current_txn); + break; + } default: { throw NotImplementedException( StringUtil::Format("Drop type %d not supported yet.\n", dropType)); @@ -147,11 +151,12 @@ bool DropExecutor::DropTable(const planner::DropPlan &node, std::string database_name = node.GetDatabaseName(); std::string schema_name = node.GetSchemaName(); std::string table_name = node.GetTableName(); + std::string session_namespace = node.GetSessionNamespace(); if (node.IsMissing()) { try { auto table_object = catalog::Catalog::GetInstance()->GetTableObject( - database_name, schema_name, table_name, txn); + database_name, schema_name, session_namespace, table_name, txn); } catch (CatalogException &e) { LOG_TRACE("Table %s does not exist.", table_name.c_str()); return false; @@ -159,7 +164,7 @@ bool DropExecutor::DropTable(const planner::DropPlan &node, } ResultType result = catalog::Catalog::GetInstance()->DropTable( - database_name, schema_name, table_name, txn); + database_name, schema_name, session_namespace, table_name, txn); txn->SetResult(result); if (txn->GetResult() == ResultType::SUCCESS) { @@ -168,7 +173,7 @@ bool DropExecutor::DropTable(const planner::DropPlan &node, if (StatementCacheManager::GetStmtCacheManager().get()) { oid_t table_id = catalog::Catalog::GetInstance() - ->GetTableObject(database_name, schema_name, table_name, txn) + ->GetTableObject(database_name, schema_name, session_namespace, table_name, txn) ->GetTableOid(); StatementCacheManager::GetStmtCacheManager()->InvalidateTableOid( table_id); @@ -185,9 +190,10 @@ bool DropExecutor::DropTrigger(const planner::DropPlan &node, std::string schema_name = node.GetSchemaName(); std::string table_name = node.GetTableName(); std::string trigger_name = node.GetTriggerName(); + std::string session_namespace = node.GetSessionNamespace(); auto table_object = catalog::Catalog::GetInstance()->GetTableObject( - database_name, schema_name, table_name, txn); + database_name, schema_name, session_namespace, table_name, txn); // drop trigger ResultType result = catalog::Catalog::GetInstance() @@ -215,10 +221,40 @@ bool DropExecutor::DropTrigger(const planner::DropPlan &node, return false; } +bool DropExecutor::DropSequence(const planner::DropPlan &node, + concurrency::TransactionContext *txn) { + std::string database_name = node.GetDatabaseName(); + std::string sequence_name = node.GetSequenceName(); + auto database_object = catalog::Catalog::GetInstance()->GetDatabaseObject( + database_name, txn); + + // drop sequence + ResultType result = + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetSequenceCatalog() + ->DropSequence(database_name,sequence_name, txn); + txn->SetResult(result); + if (txn->GetResult() == ResultType::SUCCESS) { + LOG_DEBUG("Dropping sequence succeeded!"); + } else if (txn->GetResult() == ResultType::FAILURE && node.IsMissing()) { + txn->SetResult(ResultType::SUCCESS); + LOG_TRACE("Dropping Sequence Succeeded!"); + } else if (txn->GetResult() == ResultType::FAILURE && !node.IsMissing()) { + LOG_TRACE("Dropping Sequence Failed!"); + } else { + LOG_TRACE("Result is: %s", ResultTypeToString(txn->GetResult()).c_str()); + } + return false; +} + + + bool DropExecutor::DropIndex(const planner::DropPlan &node, concurrency::TransactionContext *txn) { std::string index_name = node.GetIndexName(); std::string schema_name = node.GetSchemaName(); + std::string session_namespace = node.GetSessionNamespace(); auto database_object = catalog::Catalog::GetInstance()->GetDatabaseObject( node.GetDatabaseName(), txn); if (database_object == nullptr) { @@ -228,10 +264,27 @@ bool DropExecutor::DropIndex(const planner::DropPlan &node, auto pg_index = catalog::Catalog::GetInstance() ->GetSystemCatalogs(database_object->GetDatabaseOid()) ->GetIndexCatalog(); - auto index_object = pg_index->GetIndexObject(index_name, schema_name, txn); - if (index_object == nullptr) { - throw CatalogException("Can't find index " + schema_name + "." + - index_name + " to drop"); + + std::shared_ptr index_object; + // if no schema name specified. + if (schema_name.empty()) { + // search under session_namespace + index_object = pg_index->GetIndexObject(index_name, session_namespace, txn); + if (index_object == nullptr) { + // search under public namespace if not under temp session + index_object = + pg_index->GetIndexObject(index_name, DEFAULT_SCHEMA_NAME, txn); + if (index_object == nullptr) { + throw CatalogException("Can't find index " + schema_name + "." + + index_name + " to drop"); + } + } + } else { + index_object = pg_index->GetIndexObject(index_name, schema_name, txn); + if (index_object == nullptr) { + throw CatalogException("Can't find index " + schema_name + "." + + index_name + " to drop"); + } } // invoke directly using oid ResultType result = catalog::Catalog::GetInstance()->DropIndex( diff --git a/src/executor/executor_context.cpp b/src/executor/executor_context.cpp index ae9281c13fe..b0b1e8baf6d 100644 --- a/src/executor/executor_context.cpp +++ b/src/executor/executor_context.cpp @@ -20,8 +20,11 @@ namespace peloton { namespace executor { ExecutorContext::ExecutorContext(concurrency::TransactionContext *transaction, - codegen::QueryParameters parameters) - : transaction_(transaction), parameters_(std::move(parameters)) {} + codegen::QueryParameters parameters, + const std::string default_database_name) + : transaction_(transaction), parameters_(std::move(parameters)), + default_database_name_(default_database_name) { +} concurrency::TransactionContext *ExecutorContext::GetTransaction() const { return transaction_; @@ -43,5 +46,9 @@ type::EphemeralPool *ExecutorContext::GetPool() { return pool_.get(); } +std::string ExecutorContext::GetDatabaseName() const { + return default_database_name_; +} + } // namespace executor } // namespace peloton diff --git a/src/executor/plan_executor.cpp b/src/executor/plan_executor.cpp index 104aff1351c..0fb90e193db 100644 --- a/src/executor/plan_executor.cpp +++ b/src/executor/plan_executor.cpp @@ -36,8 +36,8 @@ static void CompileAndExecutePlan( std::shared_ptr plan, concurrency::TransactionContext *txn, const std::vector ¶ms, - std::function &&)> - on_complete) { + std::function &&)> on_complete, + std::string default_database_name) { LOG_TRACE("Compiling and executing query ..."); // Perform binding @@ -51,7 +51,8 @@ static void CompileAndExecutePlan( std::unique_ptr executor_context( new executor::ExecutorContext(txn, - codegen::QueryParameters(*plan, params))); + codegen::QueryParameters(*plan, params), + default_database_name)); // Compile the query codegen::Query *query = codegen::QueryCache::Instance().Find(plan); @@ -87,12 +88,13 @@ static void InterpretPlan( const std::vector ¶ms, const std::vector &result_format, std::function &&)> - on_complete) { + on_complete, + std::string default_database_name) { executor::ExecutionResult result; std::vector values; std::unique_ptr executor_context( - new executor::ExecutorContext(txn, params)); + new executor::ExecutorContext(txn, params, default_database_name)); bool status; std::unique_ptr executor_tree( @@ -142,8 +144,8 @@ void PlanExecutor::ExecutePlan( concurrency::TransactionContext *txn, const std::vector ¶ms, const std::vector &result_format, - std::function &&)> - on_complete) { + std::function &&)> on_complete, + std::string default_database_name) { PELOTON_ASSERT(plan != nullptr && txn != nullptr); LOG_TRACE("PlanExecutor Start (Txn ID=%" PRId64 ")", txn->GetTransactionId()); @@ -152,9 +154,9 @@ void PlanExecutor::ExecutePlan( try { if (codegen_enabled && codegen::QueryCompiler::IsSupported(*plan)) { - CompileAndExecutePlan(plan, txn, params, on_complete); + CompileAndExecutePlan(plan, txn, params, on_complete, default_database_name); } else { - InterpretPlan(plan, txn, params, result_format, on_complete); + InterpretPlan(plan, txn, params, result_format, on_complete, default_database_name); } } catch (Exception &e) { ExecutionResult result; diff --git a/src/expression/function_expression.cpp b/src/expression/function_expression.cpp index 9f74f30e475..eef472e025f 100644 --- a/src/expression/function_expression.cpp +++ b/src/expression/function_expression.cpp @@ -42,13 +42,17 @@ expression::FunctionExpression::FunctionExpression( type::Value FunctionExpression::Evaluate( const AbstractTuple *tuple1, const AbstractTuple *tuple2, - UNUSED_ATTRIBUTE executor::ExecutorContext *context) const { + executor::ExecutorContext *context) const { std::vector child_values; PELOTON_ASSERT(func_.impl != nullptr); for (auto &child : children_) { child_values.push_back(child->Evaluate(tuple1, tuple2, context)); } + if (func_name_ == "nextval" || func_name_ == "currval") { + uint64_t ctx = (uint64_t)context; + child_values.push_back(type::ValueFactory::GetBigIntValue(ctx)); + } type::Value ret = func_.impl(child_values); diff --git a/src/function/old_engine_string_functions.cpp b/src/function/old_engine_string_functions.cpp index 8add85a1fe1..06fe8a7205d 100644 --- a/src/function/old_engine_string_functions.cpp +++ b/src/function/old_engine_string_functions.cpp @@ -18,7 +18,9 @@ #include "executor/executor_context.h" #include "function/string_functions.h" -#include "type/value_factory.h" +#include "catalog/catalog.h" +#include "catalog/database_catalog.h" +#include "concurrency/transaction_context.h" namespace peloton { namespace function { @@ -234,6 +236,5 @@ type::Value OldEngineStringFunctions::Lower( UNUSED_ATTRIBUTE const std::vector &args) { throw Exception{"Lower not implemented in old engine"}; } - } // namespace function } // namespace peloton diff --git a/src/function/sequence_functions.cpp b/src/function/sequence_functions.cpp new file mode 100644 index 00000000000..8b99d7df226 --- /dev/null +++ b/src/function/sequence_functions.cpp @@ -0,0 +1,140 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence_functions.cpp +// +// Identification: src/function/sequence_functions.cpp +// +// Copyright (c) 2015-2018, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include "function/sequence_functions.h" + +#include "common/macros.h" +#include "executor/executor_context.h" +#include "catalog/catalog.h" +#include "catalog/database_catalog.h" +#include "catalog/sequence_catalog.h" +#include "concurrency/transaction_context.h" +#include "concurrency/transaction_manager_factory.h" +#include "type/value_factory.h" + +namespace peloton { +namespace function { + +/*@brief The actual implementation to get the incremented value for the specified sequence + * @param sequence name + * @param executor context + * @return the next value for the sequence + * @exception the sequence does not exist + */ +uint32_t SequenceFunctions::Nextval(executor::ExecutorContext &ctx, + const char *sequence_name) { + PELOTON_ASSERT(sequence_name != nullptr); + concurrency::TransactionContext* txn = ctx.GetTransaction(); + // get the database oid for this transaction + oid_t database_oid = catalog::Catalog::GetInstance() + ->GetDatabaseObject(ctx.GetDatabaseName(), txn)->GetDatabaseOid(); + LOG_DEBUG("Get database oid: %u", database_oid); + + // initialize a new transaction for incrementing sequence value + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto mini_txn = txn_manager.BeginTransaction(); + + // evict the old cached copy of sequence + txn->catalog_cache.EvictSequenceObject(sequence_name,database_oid); + auto sequence_object = + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetSequenceCatalog() + ->GetSequence(database_oid, sequence_name, mini_txn); + + if (sequence_object != nullptr) { + uint32_t val = sequence_object->GetNextVal(); + int64_t curr_val = sequence_object->GetCurrVal(); + // insert the new copy of sequence into cache for future currval + txn->catalog_cache.InsertSequenceObject(sequence_object); + + auto ret = txn_manager.CommitTransaction(mini_txn); + if (ret != ResultType::SUCCESS) { + txn_manager.AbortTransaction(mini_txn); + return Nextval(ctx, sequence_name); + } + + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetSequenceCatalog() + ->InsertCurrValCache(txn->temp_session_name_, sequence_name, curr_val); + return val; + } else { + throw SequenceException( + StringUtil::Format("Sequence \"%s\" does not exist", sequence_name)); + } +} + +/*@brief The actual implementation to get the current value for the specified sequence + * @param sequence name + * @param executor context + * @return the current value of a sequence + * @exception either the sequence does not exist, or 'call nextval before currval' + */ +uint32_t SequenceFunctions::Currval(executor::ExecutorContext &ctx, + const char *sequence_name) { + PELOTON_ASSERT(sequence_name != nullptr); + concurrency::TransactionContext* txn = ctx.GetTransaction(); + // get the database oid for this transaction + oid_t database_oid = catalog::Catalog::GetInstance() + ->GetDatabaseObject(ctx.GetDatabaseName(), txn)->GetDatabaseOid(); + LOG_DEBUG("Get database oid: %u", database_oid); + + // get the sequence copy from cache + auto sequence_catalog = catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetSequenceCatalog(); + + if(sequence_catalog->CheckCachedCurrValExistence( + txn->temp_session_name_, std::string(sequence_name))) { + return sequence_catalog->GetCachedCurrVal( + txn->temp_session_name_, std::string(sequence_name)); + } else { + // get sequence from catalog + auto sequence_object = sequence_catalog + ->GetSequence(database_oid, sequence_name, txn); + if (sequence_object != nullptr) { + throw SequenceException( + StringUtil::Format("currval for sequence \"%s\" is undefined for this session", + sequence_name)); + } else { + // sequence does not exist + throw SequenceException( + StringUtil::Format("Sequence \"%s\" does not exist", sequence_name)); + } + } +} + +/*@brief The wrapper function to get the incremented value for the specified sequence + * @param sequence name + * @param executor context + * @return the result of executing NextVal + */ +type::Value SequenceFunctions::_Nextval(const std::vector &args) { + executor::ExecutorContext* ctx = (executor::ExecutorContext*)args[1].GetAs(); + uint32_t ret = SequenceFunctions::Nextval(*ctx, args[0].GetAs()); + return type::ValueFactory::GetIntegerValue(ret); +} + +/*@brief The wrapper function to get the current value for the specified sequence + * @param sequence name + * @param executor context + * @return the result of executing CurrVal + */ +type::Value SequenceFunctions::_Currval(const std::vector &args) { + executor::ExecutorContext* ctx = (executor::ExecutorContext*)args[1].GetAs(); + uint32_t ret = SequenceFunctions::Currval(*ctx, args[0].GetAs()); + return type::ValueFactory::GetIntegerValue(ret); +} + +} // namespace function +} // namespace peloton diff --git a/src/include/binder/bind_node_visitor.h b/src/include/binder/bind_node_visitor.h index 9ca09c68693..5042bda9502 100644 --- a/src/include/binder/bind_node_visitor.h +++ b/src/include/binder/bind_node_visitor.h @@ -44,7 +44,8 @@ namespace binder { class BindNodeVisitor : public SqlNodeVisitor { public: BindNodeVisitor(concurrency::TransactionContext *txn, - std::string default_database_name); + std::string default_database_name, + std::string session_namespace); void BindNameToNode(parser::SQLStatement *tree); void Visit(parser::SelectStatement *) override; @@ -86,6 +87,7 @@ class BindNodeVisitor : public SqlNodeVisitor { std::shared_ptr context_; concurrency::TransactionContext *txn_; std::string default_database_name_; + std::string session_namespace_; catalog::Catalog *catalog_; }; diff --git a/src/include/binder/binder_context.h b/src/include/binder/binder_context.h index 93aca140539..c3020ca9a83 100644 --- a/src/include/binder/binder_context.h +++ b/src/include/binder/binder_context.h @@ -51,6 +51,7 @@ class BinderContext { */ void AddRegularTable(parser::TableRef *table_ref, const std::string default_database_name, + const std::string session_namespace, concurrency::TransactionContext *txn); /** @@ -59,6 +60,7 @@ class BinderContext { */ void AddRegularTable(const std::string db_name, const std::string schema_name, std::string table_name, const std::string table_alias, + const std::string session_namespace, concurrency::TransactionContext *txn); /** diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h index cd19d7fe72b..e70d9f07788 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -104,6 +104,7 @@ class Catalog { // Create index for a table ResultType CreateIndex(const std::string &database_name, const std::string &schema_name, + const std::string &session_namespace, const std::string &table_name, const std::vector &key_attrs, const std::string &index_name, bool unique_keys, @@ -137,6 +138,7 @@ class Catalog { // Drop a table using table name ResultType DropTable(const std::string &database_name, const std::string &schema_name, + const std::string &session_namespace, const std::string &table_name, concurrency::TransactionContext *txn); // Drop a table, use this one in the future @@ -162,6 +164,7 @@ class Catalog { * */ storage::DataTable *GetTableWithName(const std::string &database_name, const std::string &schema_name, + const std::string &session_namespace, const std::string &table_name, concurrency::TransactionContext *txn); @@ -180,6 +183,7 @@ class Catalog { * */ std::shared_ptr GetTableObject( const std::string &database_name, const std::string &schema_name, + const std::string &session_namespace, const std::string &table_name, concurrency::TransactionContext *txn); std::shared_ptr GetTableObject( oid_t database_oid, oid_t table_oid, @@ -189,6 +193,18 @@ class Catalog { * Using database oid to get system catalog object */ std::shared_ptr GetSystemCatalogs(const oid_t database_oid); + + + /* + * Drop all the temporary tables created during a session + */ + void DropTempTables(const std::string &database_name, + const std::string &session_namespace, + concurrency::TransactionContext *txn); + + void RemoveCachedSequenceCurrVal(const std::string &database_name, + const std::string &temp_session_name_, + concurrency::TransactionContext *txn); //===--------------------------------------------------------------------===// // DEPRECATED FUNCTIONS //===--------------------------------------------------------------------===// diff --git a/src/include/catalog/catalog_cache.h b/src/include/catalog/catalog_cache.h index 5bde19760ad..b00ec7403c8 100644 --- a/src/include/catalog/catalog_cache.h +++ b/src/include/catalog/catalog_cache.h @@ -23,9 +23,14 @@ namespace planner { class PlanUtil; } // namespace planner +namespace function { +class SequenceFunctions; +} // namespace function + namespace catalog { class DatabaseCatalogObject; +class SequenceCatalogObject; class TableCatalogObject; class IndexCatalogObject; @@ -38,6 +43,8 @@ class CatalogCache { friend class TableCatalogObject; friend class IndexCatalogObject; friend class planner::PlanUtil; + friend class SequenceCatalogObject; + friend class function::SequenceFunctions; public: CatalogCache() {} @@ -60,11 +67,25 @@ class CatalogCache { bool EvictDatabaseObject(oid_t database_oid); bool EvictDatabaseObject(const std::string &database_name); + // sequence catalog cache interface + bool InsertSequenceObject( + std::shared_ptr sequence_object); + bool EvictSequenceObject(const std::string &sequence_name, + oid_t database_oid); + std::shared_ptr GetSequenceObject( + const std::string &sequence_name, oid_t database_oid); + std::size_t GetHashKey(std::string sequence_name, oid_t database_oid); + // cache for database catalog object std::unordered_map> database_objects_cache; std::unordered_map> database_name_cache; + + // cache for sequence catalog object + std::unordered_map> + sequence_objects_cache; + }; } // namespace catalog diff --git a/src/include/catalog/catalog_defaults.h b/src/include/catalog/catalog_defaults.h index 2cfcacbda70..d4dc6c18546 100644 --- a/src/include/catalog/catalog_defaults.h +++ b/src/include/catalog/catalog_defaults.h @@ -32,10 +32,11 @@ namespace catalog { #define TABLE_CATALOG_NAME "pg_table" #define INDEX_CATALOG_NAME "pg_index" #define COLUMN_CATALOG_NAME "pg_attribute" +#define SEQUENCE_CATALOG_NAME "pg_sequence" // Local oids from START_OID = 0 to START_OID + OID_OFFSET are reserved #define OID_OFFSET 100 -#define CATALOG_TABLES_COUNT 8 +#define CATALOG_TABLES_COUNT 9 // Oid mask for each type #define DATABASE_OID_MASK (static_cast(catalog::CatalogType::DATABASE)) @@ -45,6 +46,7 @@ namespace catalog { #define TRIGGER_OID_MASK (static_cast(catalog::CatalogType::TRIGGER)) #define LANGUAGE_OID_MASK (static_cast(catalog::CatalogType::LANGUAGE)) #define PROC_OID_MASK (static_cast(catalog::CatalogType::PROC)) +#define SEQUENCE_OID_MASK (static_cast(catalog::CatalogType::SEQUENCE)) // Reserved peloton database oid #define CATALOG_DATABASE_OID (0 | DATABASE_OID_MASK) @@ -54,7 +56,8 @@ namespace catalog { #define CATALOG_SCHEMA_OID (0 | SCHEMA_OID_MASK) #define DEFUALT_SCHEMA_OID (1 | SCHEMA_OID_MASK) #define CATALOG_SCHEMA_NAME "pg_catalog" -#define DEFUALT_SCHEMA_NAME "public" +#define DEFAULT_SCHEMA_NAME "public" +#define TEMP_NAMESPACE_PREFIX "pg_temp_" // Reserved pg_xxx table oid #define DATABASE_CATALOG_OID (0 | TABLE_OID_MASK) @@ -99,6 +102,7 @@ enum class CatalogType : uint32_t { TRIGGER = 6 << CATALOG_TYPE_OFFSET, LANGUAGE = 7 << CATALOG_TYPE_OFFSET, PROC = 8 << CATALOG_TYPE_OFFSET, + SEQUENCE = 9 << CATALOG_TYPE_OFFSET, // To be added }; diff --git a/src/include/catalog/database_catalog.h b/src/include/catalog/database_catalog.h index cc097414931..06f49387e05 100644 --- a/src/include/catalog/database_catalog.h +++ b/src/include/catalog/database_catalog.h @@ -50,6 +50,7 @@ class DatabaseCatalogObject { bool cached_only = false); std::shared_ptr GetTableObject( const std::string &table_name, const std::string &schema_name, + const std::string &session_namespace, bool cached_only = false); bool IsValidTableObjects() { @@ -82,6 +83,10 @@ class DatabaseCatalogObject { std::shared_ptr GetCachedIndexObject( const std::string &index_name, const std::string &schema_name); + //helper to get table object + std::shared_ptr GetTableObjectHelper( + const std::string &table_name, const std::string &schema_name, bool cached_only); + // cache for table name to oid translation std::unordered_map> table_objects_cache; diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h new file mode 100644 index 00000000000..e75ffb198b0 --- /dev/null +++ b/src/include/catalog/sequence_catalog.h @@ -0,0 +1,225 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence_catalog.h +// +// Identification: src/include/catalog/sequence_catalog.h +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// pg_trigger +// +// Schema: (column offset: column_name) +// 0: oid (pkey) +// 1: sqdboid : database_oid +// 2: sqname : sequence_name +// 3: sqinc : seq_increment +// 4: sqmax : seq_max +// 5: sqmin : seq_min +// 6: sqstart : seq_start +// 7: sqcycle : seq_cycle +// 7: sqval : seq_value +// +// Indexes: (index offset: indexed columns) +// 0: oid (primary key) +// 1: (sqdboid, sqname) (secondary key 0) +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include +#include +#include +#include + +#include "catalog/abstract_catalog.h" +#include "catalog/catalog_defaults.h" +#include "catalog/system_catalogs.h" + +namespace peloton { + +namespace concurrency { +class TransactionContext; +} + +namespace catalog { + +class SequenceCatalogObject { + public: + SequenceCatalogObject(oid_t seqoid, oid_t dboid, const std::string &name, + const int64_t seqstart, const int64_t seqincrement, + const int64_t seqmax, const int64_t seqmin, + const bool seqcycle, const int64_t seqval, + concurrency::TransactionContext *txn) + : seq_oid(seqoid), + db_oid(dboid), + seq_name(name), + seq_start(seqstart), + seq_increment(seqincrement), + seq_max(seqmax), + seq_min(seqmin), + seq_cycle(seqcycle), + txn_(txn), + seq_curr_val(seqval){}; + + oid_t seq_oid; + oid_t db_oid; + std::string seq_name; + int64_t seq_start; // Start value of the sequence + int64_t seq_increment; // Increment value of the sequence + int64_t seq_max; // Maximum value of the sequence + int64_t seq_min; // Minimum value of the sequence + int64_t seq_cache; // Cache size of the sequence + bool seq_cycle; // Whether the sequence cycles + concurrency::TransactionContext *txn_; + + int64_t seq_prev_val; + + int64_t GetNextVal(); + + int64_t GetCurrVal() { + return seq_prev_val; + }; + + void SetCurrVal(int64_t curr_val) { + seq_curr_val = curr_val; + }; // only visible for test! + void SetCycle(bool cycle) { seq_cycle = cycle; }; + + private: + int64_t seq_curr_val; +}; + +class SequenceCatalog : public AbstractCatalog { + public: + SequenceCatalog(const std::string &database_name, + concurrency::TransactionContext *txn); + ~SequenceCatalog(); + + //===--------------------------------------------------------------------===// + // write Related API + //===--------------------------------------------------------------------===// + bool InsertSequence(oid_t database_oid, std::string sequence_name, + int64_t seq_increment, int64_t seq_max, int64_t seq_min, + int64_t seq_start, bool seq_cycle, + type::AbstractPool *pool, + concurrency::TransactionContext *txn); + + ResultType DropSequence(const std::string &database_name, + const std::string &sequence_name, + concurrency::TransactionContext *txn); + + bool DeleteSequenceByName(const std::string &sequence_name, + oid_t database_oid, + concurrency::TransactionContext *txn); + + std::shared_ptr GetSequence( + oid_t database_oid, const std::string &sequence_name, + concurrency::TransactionContext *txn); + + oid_t GetSequenceOid(std::string sequence_name, oid_t database_oid, + concurrency::TransactionContext *txn); + + bool UpdateNextVal(oid_t sequence_oid, int64_t nextval, + concurrency::TransactionContext *txn); + + enum ColumnId { + SEQUENCE_OID = 0, + DATABSE_OID = 1, + SEQUENCE_NAME = 2, + SEQUENCE_INC = 3, + SEQUENCE_MAX = 4, + SEQUENCE_MIN = 5, + SEQUENCE_START = 6, + SEQUENCE_CYCLE = 7, + SEQUENCE_VALUE = 8 + }; + + enum IndexId { + PRIMARY_KEY = 0, + DBOID_SEQNAME_KEY = 1 + }; + + void InsertCurrValCache(std::string session_namespace_, std::string sequence_name, int64_t currval){ + std::tuple key(session_namespace_, sequence_name); + size_t hash_key = key_hash(key); + sequence_currval_cache[hash_key] = currval; + namespace_hash_lists[session_namespace_].push_back(hash_key); + sequence_name_hash_lists[sequence_name].push_back(hash_key); + } + + void EvictNamespaceCurrValCache(std::string session_namespace_){ + std::vector hash_keys = namespace_hash_lists[session_namespace_]; + for (size_t hash_key : hash_keys){ + sequence_currval_cache.erase(hash_key); + } + namespace_hash_lists.erase(session_namespace_); + } + + void EvictSequenceNameCurrValCache(std::string sequence_name){ + std::vector hash_keys = sequence_name_hash_lists[sequence_name]; + for (size_t hash_key : hash_keys){ + sequence_currval_cache.erase(hash_key); + } + sequence_name_hash_lists.erase(sequence_name); + } + + bool CheckCachedCurrValExistence(std::string session_namespace_, std::string sequence_name) { + std::tuple key(session_namespace_, sequence_name); + size_t hash_key = key_hash(key); + + if (sequence_currval_cache.find(hash_key) != sequence_currval_cache.end()) + return true; + + return false; + } + + int64_t GetCachedCurrVal(std::string session_namespace_, std::string sequence_name){ + std::tuple key(session_namespace_, sequence_name); + size_t hash_key = key_hash(key); + + return sequence_currval_cache.find(hash_key)->second; + } + + private: + oid_t GetNextOid() { return oid_++ | SEQUENCE_OID_MASK; } + + std::unordered_map sequence_currval_cache; + std::unordered_map> namespace_hash_lists; + std::unordered_map> sequence_name_hash_lists; + boost::hash> key_hash; + + void ValidateSequenceArguments(int64_t seq_increment, int64_t seq_max, + int64_t seq_min, int64_t seq_start) { + if (seq_min > seq_max) { + throw SequenceException( + StringUtil::Format( + "MINVALUE (%ld) must be no greater than MAXVALUE (%ld)", seq_min, seq_max)); + } + + if (seq_increment == 0) { + throw SequenceException( + StringUtil::Format("INCREMENT must not be zero")); + } + + if (seq_increment > 0 && seq_start < seq_min) { + throw SequenceException( + StringUtil::Format( + "START value (%ld) cannot be less than MINVALUE (%ld)", seq_start, seq_min)); + } + + if (seq_increment < 0 && seq_start > seq_max) { + throw SequenceException( + StringUtil::Format( + "START value (%ld) cannot be greater than MAXVALUE (%ld)", seq_start, seq_max)); + } + }; +}; + +} // namespace catalog +} // namespace peloton diff --git a/src/include/catalog/system_catalogs.h b/src/include/catalog/system_catalogs.h index 7791c019097..d8d8900480e 100644 --- a/src/include/catalog/system_catalogs.h +++ b/src/include/catalog/system_catalogs.h @@ -21,6 +21,7 @@ #include "catalog/table_catalog.h" #include "catalog/table_metrics_catalog.h" #include "catalog/trigger_catalog.h" +#include "catalog/sequence_catalog.h" namespace peloton { @@ -34,6 +35,7 @@ class SchemaCatalog; class TableCatalog; class IndexCatalog; class ColumnCatalog; +class SequenceCatalog; class SystemCatalogs { public: @@ -86,6 +88,13 @@ class SystemCatalogs { return pg_trigger_; } + SequenceCatalog *GetSequenceCatalog() { + if (!pg_sequence_) { + throw CatalogException("Sequence catalog catalog has not been initialized"); + } + return pg_sequence_; + } + TableMetricsCatalog *GetTableMetricsCatalog() { if (!pg_table_metrics_) { throw CatalogException("Table metrics catalog has not been initialized"); @@ -114,6 +123,8 @@ class SystemCatalogs { IndexCatalog *pg_index_; TriggerCatalog *pg_trigger_; + SequenceCatalog *pg_sequence_; + // ProcCatalog *pg_proc; TableMetricsCatalog *pg_table_metrics_; IndexMetricsCatalog *pg_index_metrics_; diff --git a/src/include/catalog/table_catalog.h b/src/include/catalog/table_catalog.h index 0dfc3f51fa9..e7bf3fbe0be 100644 --- a/src/include/catalog/table_catalog.h +++ b/src/include/catalog/table_catalog.h @@ -152,7 +152,8 @@ class TableCatalog : public AbstractCatalog { concurrency::TransactionContext *txn); std::unordered_map> GetTableObjects(concurrency::TransactionContext *txn); - + std::vector> + GetTableObjects(const std::string &schema_name, concurrency::TransactionContext *txn); std::unique_ptr InitializeSchema(); enum ColumnId { diff --git a/src/include/codegen/proxy/sequence_functions_proxy.h b/src/include/codegen/proxy/sequence_functions_proxy.h new file mode 100644 index 00000000000..222b6cf4fe2 --- /dev/null +++ b/src/include/codegen/proxy/sequence_functions_proxy.h @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// string_functions_proxy.h +// +// Identification: src/include/codegen/proxy/string_functions_proxy.h +// +// Copyright (c) 2015-2018, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "codegen/proxy/proxy.h" +#include "codegen/proxy/type_builder.h" +#include "function/sequence_functions.h" + +namespace peloton { +namespace codegen { + +PROXY(SequenceFunctions) { + DECLARE_METHOD(Nextval); + DECLARE_METHOD(Currval); +}; + +} // namespace codegen +} // namespace peloton diff --git a/src/include/codegen/type/varchar_type.h b/src/include/codegen/type/varchar_type.h index 796d493772a..ffaf76b8c43 100644 --- a/src/include/codegen/type/varchar_type.h +++ b/src/include/codegen/type/varchar_type.h @@ -50,4 +50,4 @@ class Varchar : public SqlType, public Singleton { } // namespace type } // namespace codegen -} // namespace peloton \ No newline at end of file +} // namespace peloton diff --git a/src/include/common/exception.h b/src/include/common/exception.h index 4c201891751..d8e82565da1 100644 --- a/src/include/common/exception.h +++ b/src/include/common/exception.h @@ -59,7 +59,8 @@ enum class ExceptionType { SETTINGS = 23, // settings related BINDER = 24, // binder related NETWORK = 25, // network related - OPTIMIZER = 26 // optimizer related + OPTIMIZER = 26, // optimizer related + SEQUENCE = 27 // sequence related }; class Exception : public std::runtime_error { @@ -76,9 +77,7 @@ class Exception : public std::runtime_error { "\nMessage :: " + message; } - std::string GetMessage() { - return exception_message_; - } + std::string GetMessage() { return exception_message_; } std::string ExceptionTypeToString(ExceptionType type) { switch (type) { @@ -132,6 +131,8 @@ class Exception : public std::runtime_error { return "Settings"; case ExceptionType::OPTIMIZER: return "Optimizer"; + case ExceptionType::SEQUENCE: + return "Sequence"; default: return "Unknown"; } @@ -467,4 +468,12 @@ class OptimizerException : public Exception { : Exception(ExceptionType::OPTIMIZER, msg) {} }; +class SequenceException : public Exception { + SequenceException() = delete; + + public: + SequenceException(std::string msg) + : Exception(ExceptionType::SEQUENCE, msg) {} +}; + } // namespace peloton diff --git a/src/include/common/internal_types.h b/src/include/common/internal_types.h index 17020512944..3648cc2001b 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -616,6 +616,7 @@ enum class CreateType { CONSTRAINT = 4, // constraint create type TRIGGER = 5, // trigger create type SCHEMA = 6, // schema create type + SEQUENCE = 7 // sequencce create type }; std::string CreateTypeToString(CreateType type); CreateType StringToCreateType(const std::string &str); @@ -632,7 +633,8 @@ enum class DropType { INDEX = 3, // index drop type CONSTRAINT = 4, // constraint drop type TRIGGER = 5, // trigger drop type - SCHEMA = 6, // trigger drop type + SCHEMA = 6, // schema drop type + SEQUENCE = 7, // sequence drop type }; std::string DropTypeToString(DropType type); DropType StringToDropType(const std::string &str); @@ -712,7 +714,9 @@ enum class QueryType { QUERY_CREATE_TRIGGER = 21, QUERY_CREATE_SCHEMA = 22, QUERY_CREATE_VIEW = 23, - QUERY_EXPLAIN = 24 + QUERY_EXPLAIN = 24, + QUERY_CREATE_SEQUENCE = 25, + QUERY_DROP_SEQUENCE = 26 }; std::string QueryTypeToString(QueryType query_type); QueryType StringToQueryType(std::string str); @@ -1094,6 +1098,8 @@ enum class OperatorId : uint32_t { DateTrunc, Like, Now, + Nextval, + Currval, // Add more operators here, before the last "Invalid" entry Invalid diff --git a/src/include/concurrency/transaction_context.h b/src/include/concurrency/transaction_context.h index 892149b510e..02de8c9720a 100644 --- a/src/include/concurrency/transaction_context.h +++ b/src/include/concurrency/transaction_context.h @@ -19,10 +19,12 @@ #include #include "catalog/catalog_cache.h" +#include "catalog/table_catalog.h" #include "common/exception.h" #include "common/item_pointer.h" #include "common/printable.h" #include "common/internal_types.h" +#include "parser/parsenodes.h" #define INTITIAL_RW_SET_SIZE 64 @@ -51,9 +53,9 @@ class TransactionContext : public Printable { TransactionContext(const size_t thread_id, const IsolationLevelType isolation, const cid_t &read_id, const cid_t &commit_id); - + TransactionContext(const size_t thread_id, const IsolationLevelType isolation, - const cid_t &read_id, const cid_t &commit_id, + const cid_t &read_id, const cid_t &commit_id, const size_t read_write_set_size); /** @@ -138,7 +140,7 @@ class TransactionContext : public Printable { * @param[in] epoch_id The epoch identifier */ inline void SetEpochId(const eid_t epoch_id) { epoch_id_ = epoch_id; } - + /** * @brief Sets the timestamp. * @@ -281,9 +283,43 @@ class TransactionContext : public Printable { return isolation_level_; } + /** + * @brief table_oid add table oid created in the transaction into table + * @param table_oid the temp table oid to be added + */ + inline void AddTempTableObject(std::shared_ptr table_object) { + temp_table_objects.push_back(table_object); + } + + /** + * @breif get temp table objects + * @return the temp table objects + */ + inline std::vector> GetTempTableObjects() { + return temp_table_objects; + } + + /** + * @brief set the commit option for create table + * @param the commit option + */ + inline void SetCommitOption(OnCommitAction commit_option) { + commit_option_ = commit_option; + } + + /*** + * @brief get the commit option + * @return the commit option + */ + inline OnCommitAction GetCommitOption() { + return commit_option_; + } + /** cache for table catalog objects */ catalog::CatalogCache catalog_cache; + std::string temp_session_name_; + private: //===--------------------------------------------------------------------===// // Data members @@ -326,8 +362,8 @@ class TransactionContext : public Printable { ReadWriteSet rw_set_; CreateDropSet rw_object_set_; - /** - * this set contains data location that needs to be gc'd in the transaction. + /** + * this set contains data location that needs to be gc'd in the transaction. */ std::shared_ptr gc_set_; std::shared_ptr gc_object_set_; @@ -341,6 +377,10 @@ class TransactionContext : public Printable { IsolationLevelType isolation_level_; std::unique_ptr on_commit_triggers_; + + //temp table oid. + std::vector> temp_table_objects; + OnCommitAction commit_option_; //what we do on commit? }; } // namespace concurrency diff --git a/src/include/executor/create_executor.h b/src/include/executor/create_executor.h index 19b29dd24aa..f96c9c95762 100644 --- a/src/include/executor/create_executor.h +++ b/src/include/executor/create_executor.h @@ -13,6 +13,8 @@ #pragma once #include "executor/abstract_executor.h" +#include "concurrency/transaction_context.h" +#include "planner/create_plan.h" namespace peloton { @@ -54,7 +56,13 @@ class CreateExecutor : public AbstractExecutor { bool CreateTrigger(const planner::CreatePlan &node); + bool CreateSequence(const planner::CreatePlan &node); + private: + void CheckForeignKeySchema( + const std::string &schema_name, const std::string &database_name, + const std::string &session_namespace, const planner::CreatePlan &node, + concurrency::TransactionContext *txn); ExecutorContext *context_; // Abstract Pool to hold strings diff --git a/src/include/executor/drop_executor.h b/src/include/executor/drop_executor.h index 4454ebe2b5d..8e792083518 100644 --- a/src/include/executor/drop_executor.h +++ b/src/include/executor/drop_executor.h @@ -59,6 +59,9 @@ class DropExecutor : public AbstractExecutor { bool DropIndex(const planner::DropPlan &node, concurrency::TransactionContext *txn); + + bool DropSequence(const planner::DropPlan &node, + concurrency::TransactionContext *txn); private: ExecutorContext *context_; diff --git a/src/include/executor/executor_context.h b/src/include/executor/executor_context.h index 79cfe5cd19b..0e02a3e6d2a 100644 --- a/src/include/executor/executor_context.h +++ b/src/include/executor/executor_context.h @@ -30,7 +30,8 @@ namespace executor { class ExecutorContext { public: explicit ExecutorContext(concurrency::TransactionContext *transaction, - codegen::QueryParameters parameters = {}); + codegen::QueryParameters parameters = {}, + std::string default_database_name = ""); DISALLOW_COPY_AND_MOVE(ExecutorContext); @@ -44,6 +45,8 @@ class ExecutorContext { type::EphemeralPool *GetPool(); + std::string GetDatabaseName() const; + // Number of processed tuples during execution uint32_t num_processed = 0; @@ -54,6 +57,8 @@ class ExecutorContext { codegen::QueryParameters parameters_; // Temporary memory pool for allocations done during execution std::unique_ptr pool_; + // Default database name + std::string default_database_name_; }; } // namespace executor diff --git a/src/include/executor/plan_executor.h b/src/include/executor/plan_executor.h index 49d32b98b71..f87cfa36f5a 100644 --- a/src/include/executor/plan_executor.h +++ b/src/include/executor/plan_executor.h @@ -61,7 +61,8 @@ class PlanExecutor { const std::vector ¶ms, const std::vector &result_format, std::function &&)> on_complete); + std::vector &&)> on_complete, + std::string default_database_name = ""); /* * @brief When a peloton node recvs a query plan, this function is invoked diff --git a/src/include/function/old_engine_string_functions.h b/src/include/function/old_engine_string_functions.h index 7603ac14fd0..d80f2e6c150 100644 --- a/src/include/function/old_engine_string_functions.h +++ b/src/include/function/old_engine_string_functions.h @@ -20,6 +20,7 @@ namespace peloton { namespace function { class OldEngineStringFunctions { + public: // ASCII code of the first character of the argument. static type::Value Ascii(const std::vector &args); diff --git a/src/include/function/sequence_functions.h b/src/include/function/sequence_functions.h new file mode 100644 index 00000000000..a91faf5dffd --- /dev/null +++ b/src/include/function/sequence_functions.h @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence_functions.h +// +// Identification: src/include/function/sequence_functions.h +// +// Copyright (c) 2015-2018, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include "type/value.h" + +namespace peloton { + +namespace executor { +class ExecutorContext; +} // namespace executor + +namespace function { + +class SequenceFunctions { + public: + + // Nextval will return the next value of the given sequence + static uint32_t Nextval(executor::ExecutorContext &ctx, const char *sequence_name); + + // Currval will return the current value of the given sequence + static uint32_t Currval(executor::ExecutorContext &ctx, const char *sequence_name); + + // Wrapper function used for AddBuiltin Functions + static type::Value _Nextval(const std::vector &args); + static type::Value _Currval(const std::vector &args); +}; + +} // namespace function +} // namespace peloton diff --git a/src/include/optimizer/abstract_optimizer.h b/src/include/optimizer/abstract_optimizer.h index 05a5aefc6b7..c171ea435c2 100644 --- a/src/include/optimizer/abstract_optimizer.h +++ b/src/include/optimizer/abstract_optimizer.h @@ -14,6 +14,7 @@ #include +#include "catalog/catalog_defaults.h" #include "common/internal_types.h" namespace peloton { @@ -53,7 +54,13 @@ class AbstractOptimizer { const std::unique_ptr &parse_tree, concurrency::TransactionContext *txn) = 0; + //set the namespace for the session + virtual inline void SetSessionNamespace(const std::string session_namespace) { + session_namespace_ = std::move(session_namespace); + } virtual void Reset(){}; + //session namespace + std::string session_namespace_ = DEFAULT_SCHEMA_NAME; }; } // namespace optimizer diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h index 82b1d4c9a05..84ce32d15d2 100644 --- a/src/include/optimizer/optimizer.h +++ b/src/include/optimizer/optimizer.h @@ -14,6 +14,7 @@ #include +#include "catalog/catalog.h" #include "optimizer/abstract_optimizer.h" #include "optimizer/property_set.h" #include "optimizer/optimizer_metadata.h" diff --git a/src/include/optimizer/query_to_operator_transformer.h b/src/include/optimizer/query_to_operator_transformer.h index 2ba6bc8e117..f850fd0e1ef 100644 --- a/src/include/optimizer/query_to_operator_transformer.h +++ b/src/include/optimizer/query_to_operator_transformer.h @@ -66,6 +66,14 @@ class QueryToOperatorTransformer : public SqlNodeVisitor { void Visit(expression::ComparisonExpression *expr) override; void Visit(expression::OperatorExpression *expr) override; + std::string GetSessionNamespace() const { + return session_namespace_; + } + + void SetSessionNamespace(const std::string session_namespace) { + session_namespace_ = std::move(session_namespace); + } + private: inline oid_t GetAndIncreaseGetId() { return get_id++; } @@ -137,6 +145,7 @@ class QueryToOperatorTransformer : public SqlNodeVisitor { * generate filter operator */ std::vector predicates_; + std::string session_namespace_; }; } // namespace optimizer diff --git a/src/include/parser/analyze_statement.h b/src/include/parser/analyze_statement.h index b0c5e5e6ea2..a075cbf98db 100644 --- a/src/include/parser/analyze_statement.h +++ b/src/include/parser/analyze_statement.h @@ -14,6 +14,7 @@ #include +#include "catalog/catalog_defaults.h" #include "common/logger.h" #include "common/sql_node_visitor.h" #include "parser/sql_statement.h" diff --git a/src/include/parser/copy_statement.h b/src/include/parser/copy_statement.h index 3af77a797c4..f970a1b9439 100644 --- a/src/include/parser/copy_statement.h +++ b/src/include/parser/copy_statement.h @@ -12,6 +12,7 @@ #pragma once +#include "catalog/catalog_defaults.h" #include "parser/sql_statement.h" #include "parser/table_ref.h" #include "expression/constant_value_expression.h" @@ -41,7 +42,6 @@ class CopyStatement : public SQLStatement { const std::string GetInfo() const override; std::unique_ptr cpy_table; - CopyType type; std::string file_path; diff --git a/src/include/parser/create_statement.h b/src/include/parser/create_statement.h index f83b24222ef..426bfaf46ea 100644 --- a/src/include/parser/create_statement.h +++ b/src/include/parser/create_statement.h @@ -13,11 +13,14 @@ #pragma once #include +#include + #include "common/internal_types.h" #include "common/sql_node_visitor.h" #include "expression/abstract_expression.h" #include "parser/select_statement.h" #include "parser/sql_statement.h" +#include "parser/parsenodes.h" namespace peloton { namespace parser { @@ -196,6 +199,7 @@ struct ColumnDefinition { std::unique_ptr check_expression = nullptr; std::string fk_sink_table_name; + std::string fk_sink_table_schema; std::vector primary_key; std::vector foreign_key_source; std::vector foreign_key_sink; @@ -215,12 +219,21 @@ struct ColumnDefinition { */ class CreateStatement : public TableRefStatement { public: - enum CreateType { kTable, kDatabase, kIndex, kTrigger, kSchema, kView }; + enum CreateType { + kTable, + kDatabase, + kIndex, + kTrigger, + kSchema, + kView, + kSequence + }; CreateStatement(CreateType type) : TableRefStatement(StatementType::CREATE), type(type), - if_not_exists(false){}; + if_not_exists(false), + is_temp_table(false){}; virtual ~CreateStatement() {} @@ -232,7 +245,7 @@ class CreateStatement : public TableRefStatement { CreateType type; bool if_not_exists; - + bool is_temp_table; std::vector> columns; std::vector> foreign_keys; @@ -245,6 +258,7 @@ class CreateStatement : public TableRefStatement { bool unique = false; + OnCommitAction commit_option; //what we do on commit? std::string trigger_name; std::vector trigger_funcname; std::vector trigger_args; @@ -252,6 +266,14 @@ class CreateStatement : public TableRefStatement { std::unique_ptr trigger_when; int16_t trigger_type; // information about row, timing, events, access by // pg_trigger + + // attributes related to sequences + std::string sequence_name; + int64_t seq_start = 1; + int64_t seq_increment = 1; + int64_t seq_max_value = LONG_MAX; + int64_t seq_min_value = 1; + bool seq_cycle = false; }; } // namespace parser diff --git a/src/include/parser/drop_statement.h b/src/include/parser/drop_statement.h index 9612ed5fe7e..4bb693af3b0 100644 --- a/src/include/parser/drop_statement.h +++ b/src/include/parser/drop_statement.h @@ -31,7 +31,8 @@ class DropStatement : public TableRefStatement { kIndex, kView, kPreparedStatement, - kTrigger + kTrigger, + kSequence }; DropStatement(EntityType type) @@ -81,6 +82,13 @@ class DropStatement : public TableRefStatement { std::string GetTriggerTableName() { return GetTableName(); } + std::string &GetSequenceName() { return sequence_name_; } + + void SetSequenceName(std::string &sequence_name) { + sequence_name_ = sequence_name; + } + void SetSequenceName(char *sequence_name) { sequence_name_ = sequence_name; } + virtual ~DropStatement() {} virtual void Accept(SqlNodeVisitor *v) override { v->Visit(this); } @@ -105,6 +113,9 @@ class DropStatement : public TableRefStatement { // drop trigger std::string trigger_name_; + + // drop sequence + std::string sequence_name_; }; } // namespace parser diff --git a/src/include/parser/parsenodes.h b/src/include/parser/parsenodes.h index bf818ff6b86..606e7cbdd38 100644 --- a/src/include/parser/parsenodes.h +++ b/src/include/parser/parsenodes.h @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +#pragma once + #include #include "nodes.h" @@ -730,6 +732,16 @@ typedef struct CreateSchemaStmt bool if_not_exists; /* just do nothing if schema already exists? */ } CreateSchemaStmt; +typedef struct CreateSeqStmt +{ + NodeTag type; + RangeVar *sequence; /* the sequence to create */ + List *options; + Oid ownerId; /* ID of owner, or InvalidOid for default */ + bool for_identity; + bool if_not_exists; /* just do nothing if it already exists? */ +} CreateSeqStmt; + typedef enum RoleSpecType { ROLESPEC_CSTRING, /* role name is stored as a C string */ diff --git a/src/include/parser/postgresparser.h b/src/include/parser/postgresparser.h index decd43d9ee7..56497e10225 100644 --- a/src/include/parser/postgresparser.h +++ b/src/include/parser/postgresparser.h @@ -118,8 +118,8 @@ class PostgresParser { static parser::TableRef *FromTransform(SelectStmt *root); // transform helper for select targets - static std::vector> - *TargetTransform(List *root); + static std::vector> * + TargetTransform(List *root); // transform helper for all expr nodes static expression::AbstractExpression *ExprTransform(Node *root); @@ -167,7 +167,8 @@ class PostgresParser { static parser::OrderDescription *OrderByTransform(List *order); // transform helper for table column definitions - static void ColumnDefTransform(ColumnDef* root, parser::CreateStatement* stmt); + static void ColumnDefTransform(ColumnDef *root, + parser::CreateStatement *stmt); // transform helper for create statements static parser::SQLStatement *CreateTransform(CreateStmt *root); @@ -195,7 +196,8 @@ class PostgresParser { * @param Postgres CreateDatabaseStmt parsenode * @return a peloton CreateStatement node */ - static parser::SQLStatement *CreateDatabaseTransform(CreateDatabaseStmt *root); + static parser::SQLStatement *CreateDatabaseTransform( + CreateDatabaseStmt *root); // transform helper for create schema statements static parser::SQLStatement *CreateSchemaTransform(CreateSchemaStmt *root); @@ -203,13 +205,15 @@ class PostgresParser { // transform helper for create view statements static parser::SQLStatement *CreateViewTransform(ViewStmt *root); + static parser::SQLStatement *CreateSequenceTransform(CreateSeqStmt *root); + // transform helper for column name (for insert statement) static std::vector *ColumnNameTransform(List *root); // transform helper for ListsTransform (insert multiple rows) static std::vector< - std::vector>> - *ValueListsTransform(List *root); + std::vector>> * + ValueListsTransform(List *root); // transform helper for insert statements static parser::SQLStatement *InsertTransform(InsertStmt *root); @@ -233,8 +237,8 @@ class PostgresParser { static parser::UpdateStatement *UpdateTransform(UpdateStmt *update_stmt); // transform helper for update statement - static std::vector> - *UpdateTargetTransform(List *root); + static std::vector> * + UpdateTargetTransform(List *root); // transform helper for drop statement static parser::DropStatement *DropTransform(DropStmt *root); @@ -253,6 +257,9 @@ class PostgresParser { // transform helper for drop trigger statement static parser::DropStatement *DropTriggerTransform(DropStmt *root); + // transform helper for drop sequence statement + static parser::DropStatement *DropSequenceTransform(DropStmt *root); + // transform helper for drop schema statement static parser::DropStatement *DropSchemaTransform(DropStmt *root); @@ -282,13 +289,20 @@ class PostgresParser { static parser::CopyStatement *CopyTransform(CopyStmt *root); // transform helper for analyze statement - static parser::AnalyzeStatement *VacuumTransform(VacuumStmt* root); + static parser::AnalyzeStatement *VacuumTransform(VacuumStmt *root); - static parser::VariableSetStatement *VariableSetTransform(VariableSetStmt* root); + static parser::VariableSetStatement *VariableSetTransform( + VariableSetStmt *root); // transform helper for subquery expressions static expression::AbstractExpression *SubqueryExprTransform(SubLink *node); + static void ParseSequenceParams(List *options, + parser::CreateStatement *result); + + static int64_t GetLongInDefElem(DefElem *defel) { + return (int64_t)((reinterpret_cast(defel->arg))->val.ival); + }; }; } // namespace parser diff --git a/src/include/parser/sql_statement.h b/src/include/parser/sql_statement.h index 012f4090cb9..42ae73fce42 100644 --- a/src/include/parser/sql_statement.h +++ b/src/include/parser/sql_statement.h @@ -45,6 +45,12 @@ class SQLStatement : public Printable { virtual StatementType GetType() const { return stmt_type; } + virtual inline void SetSessionNamespace(std::string session_namespace) { + session_namespace_ = std::move(session_namespace); + } + + virtual inline std::string GetSessionNamespace() const { return session_namespace_; } + // Get a string representation for debugging virtual const std::string GetInfo(int num_indent) const; @@ -58,6 +64,7 @@ class SQLStatement : public Printable { private: StatementType stmt_type; + std::string session_namespace_ = DEFAULT_SCHEMA_NAME; }; class TableRefStatement : public SQLStatement { @@ -71,9 +78,6 @@ class TableRefStatement : public SQLStatement { if (table_info_->database_name.empty()) table_info_->database_name = default_database_name; - // if schema name is not specified, then it's default value is "public" - if (table_info_->schema_name.empty()) - table_info_->schema_name = DEFUALT_SCHEMA_NAME; } virtual inline std::string GetTableName() const { diff --git a/src/include/parser/table_ref.h b/src/include/parser/table_ref.h index e3b4fab31d6..87340d18266 100644 --- a/src/include/parser/table_ref.h +++ b/src/include/parser/table_ref.h @@ -74,10 +74,6 @@ struct TableRef { if (table_info_->database_name.empty()) { table_info_->database_name = default_database_name; } - - if (table_info_->schema_name.empty()) { - table_info_->schema_name = DEFUALT_SCHEMA_NAME; - } } // Get the name of the table diff --git a/src/include/planner/analyze_plan.h b/src/include/planner/analyze_plan.h index b5b162c5d5e..82ab278fc5c 100644 --- a/src/include/planner/analyze_plan.h +++ b/src/include/planner/analyze_plan.h @@ -41,10 +41,12 @@ class AnalyzePlan : public AbstractPlan { explicit AnalyzePlan(storage::DataTable *table); explicit AnalyzePlan(std::string table_name, std::string schema_name, + std::string session_namespace, std::string database_name, concurrency::TransactionContext *txn); explicit AnalyzePlan(std::string table_name, std::string schema_name, + std::string session_namespace, std::string database_name, std::vector column_names, concurrency::TransactionContext *txn); diff --git a/src/include/planner/create_plan.h b/src/include/planner/create_plan.h index ecf6a0524fe..f27f23cc10c 100644 --- a/src/include/planner/create_plan.h +++ b/src/include/planner/create_plan.h @@ -12,8 +12,10 @@ #pragma once +#include "catalog/catalog_defaults.h" #include "parser/create_statement.h" #include "planner/abstract_plan.h" +#include "common/exception.h" namespace peloton { namespace catalog { @@ -42,6 +44,7 @@ struct ForeignKeyInfo { std::vector foreign_key_sources; std::vector foreign_key_sinks; std::string sink_table_name; + std::string sink_table_schema; std::string constraint_name; FKConstrActionType upd_action; FKConstrActionType del_action; @@ -78,6 +81,12 @@ class CreatePlan : public AbstractPlan { std::string GetSchemaName() const { return schema_name; } + std::string GetSessionNamespace() const { return session_namespace_; } + + void SetSessionNamespace(const std::string session_namespace) { + session_namespace_ = std::move(session_namespace); + } + std::string GetDatabaseName() const { return database_name; } catalog::Schema *GetSchema() const { return table_schema; } @@ -114,6 +123,15 @@ class CreatePlan : public AbstractPlan { int16_t GetTriggerType() const { return trigger_type; } + std::string GetSequenceName() const { return sequence_name; } + int64_t GetSequenceStart() const { return seq_start; }; + int64_t GetSequenceIncrement() const { return seq_increment; } + int64_t GetSequenceMaxValue() const { return seq_max_value; } + int64_t GetSequenceMinValue() const { return seq_min_value; } + int64_t GetSequenceCacheSize() const { return seq_cache; } + bool GetSequenceCycle() const { return seq_cycle; } + OnCommitAction GetCommitOption() const { return commit_option; } + protected: // This is a helper method for extracting foreign key information // and storing it in an internal struct. @@ -127,6 +145,9 @@ class CreatePlan : public AbstractPlan { // namespace Name std::string schema_name; + //session namespace; + std::string session_namespace_ = DEFAULT_SCHEMA_NAME; + // Database Name std::string database_name; @@ -149,6 +170,7 @@ class CreatePlan : public AbstractPlan { // UNIQUE INDEX flag bool unique; + OnCommitAction commit_option; //what we do on commit? // ColumnDefinition for multi-column constraints (including foreign key) std::vector foreign_keys; std::string trigger_name; @@ -159,6 +181,15 @@ class CreatePlan : public AbstractPlan { int16_t trigger_type; // information about row, timing, events, access by // pg_trigger + // information for sequences; + std::string sequence_name; + int64_t seq_start; + int64_t seq_increment; + int64_t seq_max_value; + int64_t seq_min_value; + int64_t seq_cache; // sequence cache size, not supported yet + bool seq_cycle; + private: DISALLOW_COPY_AND_MOVE(CreatePlan); }; diff --git a/src/include/planner/drop_plan.h b/src/include/planner/drop_plan.h index c5593680202..683d08e0812 100644 --- a/src/include/planner/drop_plan.h +++ b/src/include/planner/drop_plan.h @@ -12,6 +12,7 @@ #pragma once +#include "catalog/catalog_defaults.h" #include "concurrency/transaction_context.h" #include "planner/abstract_plan.h" @@ -57,6 +58,8 @@ class DropPlan : public AbstractPlan { std::string GetSchemaName() const { return schema_name; } std::string GetTriggerName() const { return trigger_name; } + + std::string GetSequenceName() const { return sequence_name; } std::string GetIndexName() const { return index_name; } @@ -64,6 +67,12 @@ class DropPlan : public AbstractPlan { bool IsMissing() const { return missing; } + std::string GetSessionNamespace() const { return session_namespace_; } + + void SetSessionNamespace(const std::string &session_namespace) { + session_namespace_ = std::move(session_namespace); + } + private: DropType drop_type = DropType::TABLE; @@ -76,7 +85,14 @@ class DropPlan : public AbstractPlan { // namespace Name std::string schema_name; + //session namespace + std::string session_namespace_ = DEFAULT_SCHEMA_NAME; + std::string trigger_name; + + // sequence name + std::string sequence_name; + std::string index_name; bool missing; diff --git a/src/include/traffic_cop/traffic_cop.h b/src/include/traffic_cop/traffic_cop.h index e324b87fe82..393f11b403b 100644 --- a/src/include/traffic_cop/traffic_cop.h +++ b/src/include/traffic_cop/traffic_cop.h @@ -145,6 +145,18 @@ class TrafficCop { default_database_name_ = std::move(default_database_name); } + //set the session namespace for this session. + void SetSessionNamespace(const std::string session_namespace) { + session_namespace_ = std::move(session_namespace); + //set the session namespace for the optimizer + optimizer_->SetSessionNamespace(session_namespace); + } + + //Used to drop all the temporary table created for this session + void DropTempTables(); + + void CreateTempSchema(); + // TODO: this member variable should be in statement_ after parser part // finished std::string query_; @@ -164,6 +176,9 @@ class TrafficCop { // Default database name std::string default_database_name_ = DEFAULT_DB_NAME; + // Default session namespace + std::string session_namespace_ = DEFAULT_SCHEMA_NAME; + int rows_affected_; // The optimizer used for this connection diff --git a/src/network/connection_handle.cpp b/src/network/connection_handle.cpp index e79564b5c4d..d08d7f279b9 100644 --- a/src/network/connection_handle.cpp +++ b/src/network/connection_handle.cpp @@ -13,6 +13,7 @@ #include #include +#include "catalog/catalog_defaults.h" #include "network/connection_dispatcher_task.h" #include "network/connection_handle.h" #include "network/peloton_server.h" @@ -163,6 +164,8 @@ ConnectionHandle::ConnectionHandle(int sock_fd, ConnectionHandlerTask *handler, struct event *event = static_cast(arg); event_active(event, EV_WRITE, 0); }, workpool_event); + //set the connection temporary namespace + traffic_cop_.SetSessionNamespace(TEMP_NAMESPACE_PREFIX + std::to_string(sock_fd)); } void ConnectionHandle::UpdateEventFlags(short flags) { @@ -557,7 +560,7 @@ Transition ConnectionHandle::CloseSocket() { SSL_free(conn_SSL_context); conn_SSL_context = nullptr; } - + traffic_cop_.DropTempTables(); peloton_close(sock_fd_); return Transition::NONE; diff --git a/src/network/postgres_protocol_handler.cpp b/src/network/postgres_protocol_handler.cpp index ffbb786b88e..e14f48c6217 100644 --- a/src/network/postgres_protocol_handler.cpp +++ b/src/network/postgres_protocol_handler.cpp @@ -1050,6 +1050,7 @@ ProcessResult PostgresProtocolHandler::ProcessStartupPacket( cmdline_options_[token] = value; if (token.compare("database") == 0) { traffic_cop_->SetDefaultDatabaseName(value); + traffic_cop_->CreateTempSchema(); } } @@ -1222,6 +1223,7 @@ void PostgresProtocolHandler::CompleteCommand(const QueryType &query_type, case QueryType::QUERY_CREATE_DB: case QueryType::QUERY_CREATE_INDEX: case QueryType::QUERY_CREATE_TRIGGER: + case QueryType::QUERY_CREATE_SEQUENCE: case QueryType::QUERY_PREPARE: break; default: diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index 62f813ec876..3a4c324b717 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -99,7 +99,7 @@ shared_ptr Optimizer::BuildPelotonPlanTree( } // TODO: support multi-statement queries auto parse_tree = parse_tree_list->GetStatement(0); - + parse_tree->SetSessionNamespace(session_namespace_); unique_ptr child_plan = nullptr; // Handle ddl statement @@ -147,30 +147,33 @@ unique_ptr Optimizer::HandleDDLStatement( switch (stmt_type) { case StatementType::DROP: { LOG_TRACE("Adding Drop plan..."); - unique_ptr drop_plan( - new planner::DropPlan((parser::DropStatement *)tree)); + planner::DropPlan* drop_plan_from_parser = new planner::DropPlan((parser::DropStatement *)tree); + drop_plan_from_parser->SetSessionNamespace(session_namespace_); + unique_ptr drop_plan(drop_plan_from_parser); ddl_plan = move(drop_plan); break; } case StatementType::CREATE: { LOG_TRACE("Adding Create plan..."); - + tree->SetSessionNamespace(session_namespace_); // This is adapted from the simple optimizer auto create_plan = new planner::CreatePlan((parser::CreateStatement *)tree); + //set create plan session namespace + create_plan->SetSessionNamespace(session_namespace_); std::unique_ptr child_CreatePlan(create_plan); ddl_plan = move(child_CreatePlan); if (create_plan->GetCreateType() == peloton::CreateType::INDEX) { auto create_stmt = (parser::CreateStatement *)tree; auto target_table = catalog::Catalog::GetInstance()->GetTableWithName( - create_stmt->GetDatabaseName(), create_stmt->GetSchemaName(), + create_stmt->GetDatabaseName(), create_stmt->GetSchemaName(), session_namespace_, create_stmt->GetTableName(), txn); std::vector column_ids; // use catalog object instead of schema to acquire metadata auto table_object = catalog::Catalog::GetInstance()->GetTableObject( - create_stmt->GetDatabaseName(), create_stmt->GetSchemaName(), + create_stmt->GetDatabaseName(), create_stmt->GetSchemaName(), session_namespace_, create_stmt->GetTableName(), txn); for (auto column_name : create_plan->GetIndexAttributes()) { auto column_object = table_object->GetColumnObject(column_name); @@ -209,8 +212,9 @@ unique_ptr Optimizer::HandleDDLStatement( } break; case StatementType::ANALYZE: { LOG_TRACE("Adding Analyze plan..."); + parser::AnalyzeStatement *analyze_parse_tree = static_cast(tree); unique_ptr analyze_plan(new planner::AnalyzePlan( - static_cast(tree), txn)); + analyze_parse_tree, txn)); ddl_plan = move(analyze_plan); break; } @@ -230,6 +234,7 @@ unique_ptr Optimizer::HandleDDLStatement( shared_ptr Optimizer::InsertQueryTree( parser::SQLStatement *tree, concurrency::TransactionContext *txn) { QueryToOperatorTransformer converter(txn); + converter.SetSessionNamespace(session_namespace_); shared_ptr initial = converter.ConvertToOpExpression(tree); shared_ptr gexpr; diff --git a/src/optimizer/query_to_operator_transformer.cpp b/src/optimizer/query_to_operator_transformer.cpp index ff75140d5f5..f6132b8ec76 100644 --- a/src/optimizer/query_to_operator_transformer.cpp +++ b/src/optimizer/query_to_operator_transformer.cpp @@ -215,7 +215,7 @@ void QueryToOperatorTransformer::Visit(parser::TableRef *node) { if (node->list.size() == 1) node = node->list.at(0).get(); std::shared_ptr target_table = catalog::Catalog::GetInstance()->GetTableObject( - node->GetDatabaseName(), node->GetSchemaName(), + node->GetDatabaseName(), node->GetSchemaName(), session_namespace_, node->GetTableName(), txn_); std::string table_alias = StringUtil::Lower(std::string(node->GetTableAlias())); @@ -234,7 +234,7 @@ void QueryToOperatorTransformer::Visit( void QueryToOperatorTransformer::Visit(parser::InsertStatement *op) { std::shared_ptr target_table = catalog::Catalog::GetInstance()->GetTableObject( - op->GetDatabaseName(), op->GetSchemaName(), op->GetTableName(), txn_); + op->GetDatabaseName(), op->GetSchemaName(), session_namespace_, op->GetTableName(), txn_); if (op->type == InsertType::SELECT) { auto insert_expr = std::make_shared( @@ -311,7 +311,7 @@ void QueryToOperatorTransformer::Visit(parser::InsertStatement *op) { void QueryToOperatorTransformer::Visit(parser::DeleteStatement *op) { auto target_table = catalog::Catalog::GetInstance()->GetTableObject( - op->GetDatabaseName(), op->GetSchemaName(), op->GetTableName(), txn_); + op->GetDatabaseName(), op->GetSchemaName(), session_namespace_, op->GetTableName(), txn_); std::shared_ptr table_scan; if (op->expr != nullptr) { std::vector predicates = @@ -337,7 +337,7 @@ void QueryToOperatorTransformer::Visit( UNUSED_ATTRIBUTE parser::TransactionStatement *op) {} void QueryToOperatorTransformer::Visit(parser::UpdateStatement *op) { auto target_table = catalog::Catalog::GetInstance()->GetTableObject( - op->table->GetDatabaseName(), op->table->GetSchemaName(), + op->table->GetDatabaseName(), op->table->GetSchemaName(), session_namespace_, op->table->GetTableName(), txn_); std::shared_ptr table_scan; diff --git a/src/optimizer/stats/tuple_samples_storage.cpp b/src/optimizer/stats/tuple_samples_storage.cpp index 9ae85256758..3d705a5b8f1 100644 --- a/src/optimizer/stats/tuple_samples_storage.cpp +++ b/src/optimizer/stats/tuple_samples_storage.cpp @@ -66,11 +66,12 @@ void TupleSamplesStorage::AddSamplesTable( auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); catalog->CreateTable(std::string(SAMPLES_DB_NAME), - std::string(DEFUALT_SCHEMA_NAME), samples_table_name, + std::string(DEFAULT_SCHEMA_NAME), samples_table_name, std::move(schema_ptr), txn, is_catalog); auto samples_table = catalog->GetTableWithName( - std::string(SAMPLES_DB_NAME), std::string(DEFUALT_SCHEMA_NAME), + std::string(SAMPLES_DB_NAME), std::string(DEFAULT_SCHEMA_NAME), + std::string(DEFAULT_SCHEMA_NAME), samples_table_name, txn); for (auto &tuple : sampled_tuples) { @@ -94,7 +95,8 @@ ResultType TupleSamplesStorage::DeleteSamplesTable( ResultType result = ResultType::FAILURE; try { result = catalog->DropTable(std::string(SAMPLES_DB_NAME), - std::string(DEFUALT_SCHEMA_NAME), + std::string(DEFAULT_SCHEMA_NAME), + std::string(DEFAULT_SCHEMA_NAME), samples_table_name, txn); } catch (CatalogException &e) { // Samples table does not exist, no need to drop @@ -187,7 +189,8 @@ TupleSamplesStorage::GetTupleSamples(oid_t database_id, oid_t table_id) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); auto data_table = catalog->GetTableWithName(std::string(SAMPLES_DB_NAME), - std::string(DEFUALT_SCHEMA_NAME), + std::string(DEFAULT_SCHEMA_NAME), + std::string(DEFAULT_SCHEMA_NAME), samples_table_name, txn); auto col_count = data_table->GetSchema()->GetColumnCount(); @@ -214,7 +217,8 @@ void TupleSamplesStorage::GetColumnSamples( auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); auto data_table = catalog->GetTableWithName(std::string(SAMPLES_DB_NAME), - std::string(DEFUALT_SCHEMA_NAME), + std::string(DEFAULT_SCHEMA_NAME), + std::string(DEFAULT_SCHEMA_NAME), samples_table_name, txn); std::vector column_ids({column_id}); diff --git a/src/optimizer/util.cpp b/src/optimizer/util.cpp index 0d01e35e8ac..4183f62c2bc 100644 --- a/src/optimizer/util.cpp +++ b/src/optimizer/util.cpp @@ -162,6 +162,7 @@ std::unique_ptr CreateCopyPlan( auto target_table = catalog::Catalog::GetInstance()->GetTableWithName( copy_stmt->cpy_table->GetDatabaseName(), copy_stmt->cpy_table->GetSchemaName(), + copy_stmt->GetSessionNamespace(), copy_stmt->cpy_table->GetTableName(), txn); txn_manager.CommitTransaction(txn); diff --git a/src/parser/create_statement.cpp b/src/parser/create_statement.cpp index 40be9a437fa..bfe014885b6 100644 --- a/src/parser/create_statement.cpp +++ b/src/parser/create_statement.cpp @@ -72,6 +72,12 @@ const std::string CreateStatement::GetInfo(int num_indent) const { << StringUtil::Format("View name: %s", view_name.c_str()); break; } + case CreateStatement::CreateType::kSequence: { + os << "Create type: Sequence" << std::endl; + os << StringUtil::Indent(num_indent + 1) + << StringUtil::Format("Sequence name: %s", sequence_name.c_str()); + break; + } } os << std::endl; diff --git a/src/parser/drop_statement.cpp b/src/parser/drop_statement.cpp index feb266f89f2..348ed48e8b5 100644 --- a/src/parser/drop_statement.cpp +++ b/src/parser/drop_statement.cpp @@ -66,6 +66,14 @@ const std::string DropStatement::GetInfo(int num_indent) const { << "Trigger name: " << trigger_name_; break; } + case kSequence: { + os << "DropType: Sequence\n"; + os << StringUtil::Indent(num_indent + 1) + << "Sequence database name: " << GetDatabaseName() << std::endl; + os << StringUtil::Indent(num_indent + 1) + << "Sequence name: " << sequence_name_; + break; + } } os << std::endl; os << StringUtil::Indent(num_indent + 1) diff --git a/src/parser/postgresparser.cpp b/src/parser/postgresparser.cpp index 797b77406b5..32ab2215a70 100644 --- a/src/parser/postgresparser.cpp +++ b/src/parser/postgresparser.cpp @@ -284,12 +284,10 @@ expression::AbstractExpression *PostgresParser::ColumnRefTransform( ->val.str)); } else { result = new expression::TupleValueExpression( - std::string( - (reinterpret_cast(fields->head->next->data.ptr_value)) - ->val.str), - std::string( - (reinterpret_cast(fields->head->data.ptr_value)) - ->val.str)); + std::string((reinterpret_cast( + fields->head->next->data.ptr_value))->val.str), + std::string((reinterpret_cast( + fields->head->data.ptr_value))->val.str)); } break; } @@ -488,9 +486,8 @@ expression::AbstractExpression *PostgresParser::TypeCastTransform( } TypeName *type_name = root->typeName; - char *name = - (reinterpret_cast(type_name->names->tail->data.ptr_value) - ->val.str); + char *name = (reinterpret_cast( + type_name->names->tail->data.ptr_value)->val.str); type::VarlenType temp(StringToTypeId("INVALID")); result = new expression::ConstantValueExpression( temp.CastAs(source_value, ColumnDefinition::StrToValueType(name))); @@ -556,8 +553,8 @@ expression::AbstractExpression *PostgresParser::FuncCallTransform( // This function takes in the whereClause part of a Postgres SelectStmt // parsenode and transfers it into the select_list of a Peloton SelectStatement. // It checks the type of each target and call the corresponding helpers. -std::vector> - *PostgresParser::TargetTransform(List *root) { +std::vector> * +PostgresParser::TargetTransform(List *root) { // Statement like 'SELECT;' cannot detect by postgres parser and would lead to // null list if (root == nullptr) { @@ -863,9 +860,8 @@ expression::AbstractExpression *PostgresParser::WhenTransform(Node *root) { void PostgresParser::ColumnDefTransform(ColumnDef *root, parser::CreateStatement *stmt) { TypeName *type_name = root->typeName; - char *name = - (reinterpret_cast(type_name->names->tail->data.ptr_value) - ->val.str); + char *name = (reinterpret_cast( + type_name->names->tail->data.ptr_value)->val.str); parser::ColumnDefinition *result = nullptr; parser::ColumnDefinition::DataType data_type = @@ -965,13 +961,23 @@ parser::SQLStatement *PostgresParser::CreateTransform(CreateStmt *root) { UNUSED_ATTRIBUTE CreateStmt *temp = root; parser::CreateStatement *result = new CreateStatement(CreateStatement::CreateType::kTable); + result->commit_option = root->oncommit; RangeVar *relation = root->relation; result->table_info_.reset(new parser::TableInfo()); + // relpersistence == 't' indicates that it's a temporary table. It's the + // result produced by postgresparser. + if (relation->relpersistence == 't') { + result->is_temp_table = true; + } if (relation->relname) { result->table_info_->table_name = relation->relname; } if (relation->schemaname) { + if(result->is_temp_table) { + throw ParserException(StringUtil::Format( + "Cannot create temp table with specified schema %s", relation->schemaname)); + } result->table_info_->schema_name = relation->schemaname; } if (relation->catalogname) { @@ -1017,6 +1023,10 @@ parser::SQLStatement *PostgresParser::CreateTransform(CreateStmt *root) { } // Update Reference Table col->fk_sink_table_name = constraint->pktable->relname; + if (constraint->pktable->schemaname) { + //added schenma name for fk_sink + col->fk_sink_table_schema = constraint->pktable->schemaname; + } // Action type col->foreign_key_delete_action = CharToActionType(constraint->fk_del_action); @@ -1056,9 +1066,8 @@ parser::FuncParameter *PostgresParser::FunctionParameterTransform( FunctionParameter *root) { parser::FuncParameter::DataType data_type; TypeName *type_name = root->argType; - char *name = - (reinterpret_cast(type_name->names->tail->data.ptr_value) - ->val.str); + char *name = (reinterpret_cast( + type_name->names->tail->data.ptr_value)->val.str); parser::FuncParameter *result = nullptr; // Transform parameter type @@ -1352,12 +1361,83 @@ parser::SQLStatement *PostgresParser::CreateViewTransform(ViewStmt *root) { return result; } +parser::SQLStatement *PostgresParser::CreateSequenceTransform( + CreateSeqStmt *root) { + parser::CreateStatement *result = + new parser::CreateStatement(CreateStatement::kSequence); + result->sequence_name = std::string(root->sequence->relname); + ParseSequenceParams(root->options, result); + return result; +} + +void PostgresParser::ParseSequenceParams(List *options, + parser::CreateStatement *result) { + DefElem *start_value = NULL; + DefElem *increment_by = NULL; + DefElem *max_value = NULL; + DefElem *min_value = NULL; + DefElem *is_cycled = NULL; + if (!options) return; + + ListCell *option; + for (option = options->head; option != NULL; option = lnext(option)) { + DefElem *defel = (DefElem *)lfirst(option); + + if (strcmp(defel->defname, "increment") == 0) { + if (increment_by) + throw ParserException( + "Redundant definition of increment in defining sequence"); + increment_by = defel; + result->seq_increment = GetLongInDefElem(increment_by); + } else if (strcmp(defel->defname, "start") == 0) { + if (start_value) + throw ParserException( + "Redundant definition of start in defining sequence"); + start_value = defel; + result->seq_start = GetLongInDefElem(start_value); + } else if (strcmp(defel->defname, "maxvalue") == 0) { + if (max_value) + throw ParserException( + "Redundant definition of max in defining sequence"); + max_value = defel; + result->seq_max_value = GetLongInDefElem(max_value); + } else if (strcmp(defel->defname, "minvalue") == 0) { + if (min_value) + throw ParserException( + "Redundant definition of min in defining sequence"); + min_value = defel; + result->seq_min_value = GetLongInDefElem(min_value); + } else if (strcmp(defel->defname, "cycle") == 0) { + if (is_cycled) + throw ParserException( + "Redundant definition of cycle in defining sequence"); + is_cycled = defel; + result->seq_cycle = (bool)GetLongInDefElem(is_cycled); + } + else + throw ParserException( + StringUtil::Format("option \"%s\" not recognized\n", defel->defname)); + } + + // manually set the start value for a sequence + if (!start_value) { + if(result->seq_increment < 0 && max_value){ + result->seq_start = result->seq_max_value; + } + else if (result->seq_increment > 0 && min_value){ + result->seq_start = result->seq_min_value; + } + } +} + parser::DropStatement *PostgresParser::DropTransform(DropStmt *root) { switch (root->removeType) { case ObjectType::OBJECT_TABLE: return DropTableTransform(root); case ObjectType::OBJECT_TRIGGER: return DropTriggerTransform(root); + case ObjectType::OBJECT_SEQUENCE: + return DropSequenceTransform(root); case ObjectType::OBJECT_INDEX: return DropIndexTransform(root); case ObjectType::OBJECT_SCHEMA: @@ -1431,6 +1511,16 @@ parser::DropStatement *PostgresParser::DropTriggerTransform(DropStmt *root) { return result; } +parser::DropStatement *PostgresParser::DropSequenceTransform(DropStmt *root) { + auto result = new DropStatement(DropStatement::EntityType::kSequence); + auto cell = root->objects->head; + auto list = reinterpret_cast(cell->data.ptr_value); + // first, set sequence name + result->SetSequenceName( + reinterpret_cast(list->tail->data.ptr_value)->val.str); + return result; +} + parser::DropStatement *PostgresParser::DropSchemaTransform(DropStmt *root) { auto result = new DropStatement(DropStatement::EntityType::kSchema); result->SetCascade(root->behavior == DropBehavior::DROP_CASCADE); @@ -1559,8 +1649,8 @@ std::vector *PostgresParser::ColumnNameTransform(List *root) { // parsenode and transfers it into Peloton AbstractExpression. // This is a vector pointer of vector pointers because one InsertStmt can insert // multiple tuples. -std::vector>> - *PostgresParser::ValueListsTransform(List *root) { +std::vector>> * +PostgresParser::ValueListsTransform(List *root) { auto result = new std::vector< std::vector>>(); @@ -1671,8 +1761,8 @@ parser::SQLStatement *PostgresParser::InsertTransform(InsertStmt *root) { result = new parser::InsertStatement(InsertType::VALUES); PELOTON_ASSERT(select_stmt->valuesLists != NULL); - std::vector>> - *insert_values = nullptr; + std::vector>> * + insert_values = nullptr; try { insert_values = ValueListsTransform(select_stmt->valuesLists); } catch (Exception e) { @@ -1807,6 +1897,9 @@ parser::SQLStatement *PostgresParser::NodeTransform(Node *stmt) { result = CreateSchemaTransform(reinterpret_cast(stmt)); break; + case T_CreateSeqStmt: + result = CreateSequenceTransform(reinterpret_cast(stmt)); + break; case T_ViewStmt: result = CreateViewTransform(reinterpret_cast(stmt)); break; @@ -1887,8 +1980,8 @@ parser::SQLStatementList *PostgresParser::ListTransform(List *root) { return result; } -std::vector> - *PostgresParser::UpdateTargetTransform(List *root) { +std::vector> * +PostgresParser::UpdateTargetTransform(List *root) { auto result = new std::vector>(); for (auto cell = root->head; cell != NULL; cell = cell->next) { auto update_clause = new UpdateClause(); @@ -1943,7 +2036,7 @@ parser::SQLStatementList *PostgresParser::ParseSQLString(const char *text) { } // DEBUG only. Comment this out in release mode - // print_pg_parse_tree(result.tree); + //print_pg_parse_tree(result.tree); parser::SQLStatementList *transform_result; try { transform_result = ListTransform(result.tree); diff --git a/src/planner/analyze_plan.cpp b/src/planner/analyze_plan.cpp index 5de53476b14..902a4b0eeaa 100644 --- a/src/planner/analyze_plan.cpp +++ b/src/planner/analyze_plan.cpp @@ -22,20 +22,22 @@ namespace planner { AnalyzePlan::AnalyzePlan(storage::DataTable *table) : target_table_(table) {} AnalyzePlan::AnalyzePlan(std::string table_name, std::string schema_name, + std::string session_namespace, std::string database_name, concurrency::TransactionContext *txn) : table_name_(table_name) { target_table_ = catalog::Catalog::GetInstance()->GetTableWithName( - database_name, schema_name, table_name, txn); + database_name, schema_name, session_namespace, table_name, txn); } AnalyzePlan::AnalyzePlan(std::string table_name, std::string schema_name, + std::string session_namespace, std::string database_name, std::vector column_names, concurrency::TransactionContext *txn) : table_name_(table_name), column_names_(column_names) { target_table_ = catalog::Catalog::GetInstance()->GetTableWithName( - database_name, schema_name, table_name, txn); + database_name, schema_name, session_namespace, table_name, txn); } AnalyzePlan::AnalyzePlan(parser::AnalyzeStatement *analyze_stmt, @@ -46,7 +48,7 @@ AnalyzePlan::AnalyzePlan(parser::AnalyzeStatement *analyze_stmt, column_names_.push_back((char *)name.c_str()); if (!table_name_.empty()) { target_table_ = catalog::Catalog::GetInstance()->GetTableWithName( - analyze_stmt->GetDatabaseName(), analyze_stmt->GetSchemaName(), + analyze_stmt->GetDatabaseName(), analyze_stmt->GetSchemaName(), analyze_stmt->GetSessionNamespace(), table_name_, txn); } } diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index 2a23a75abb4..0d66ae0875a 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "planner/create_plan.h" - #include "common/internal_types.h" #include "expression/abstract_expression.h" #include "expression/constant_value_expression.h" @@ -51,6 +50,15 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { case parser::CreateStatement::CreateType::kTable: { table_name = std::string(parse_tree->GetTableName()); schema_name = std::string(parse_tree->GetSchemaName()); + commit_option = parse_tree->commit_option; + //if schema name is not set. then set it to session namespace if temp + if(schema_name.empty()) { + if (parse_tree->is_temp_table) { + schema_name = parse_tree->GetSessionNamespace(); + } else { + schema_name = DEFAULT_SCHEMA_NAME; + } + } database_name = std::string(parse_tree->GetDatabaseName()); std::vector columns; std::vector column_constraints; @@ -205,6 +213,18 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { break; } + case parser::CreateStatement::CreateType::kSequence: { + create_type = CreateType::SEQUENCE; + database_name = std::string(parse_tree->GetDatabaseName()); + + sequence_name = parse_tree->sequence_name; + seq_start = parse_tree->seq_start; + seq_increment = parse_tree->seq_increment; + seq_max_value = parse_tree->seq_max_value; + seq_min_value = parse_tree->seq_min_value; + seq_cycle = parse_tree->seq_cycle; + break; + } default: LOG_ERROR("UNKNOWN CREATE TYPE"); // TODO Should we handle this here? @@ -228,6 +248,7 @@ void CreatePlan::ProcessForeignKeyConstraint( // Extract table names fkey_info.sink_table_name = col->fk_sink_table_name; + fkey_info.sink_table_schema = col->fk_sink_table_schema; // Extract delete and update actions fkey_info.upd_action = col->foreign_key_update_action; diff --git a/src/planner/drop_plan.cpp b/src/planner/drop_plan.cpp index 34240f85cad..21e92cfcc9a 100644 --- a/src/planner/drop_plan.cpp +++ b/src/planner/drop_plan.cpp @@ -64,6 +64,13 @@ DropPlan::DropPlan(parser::DropStatement *parse_tree) { drop_type = DropType::INDEX; break; } + case parser::DropStatement::EntityType::kSequence: { + database_name = parse_tree->GetDatabaseName(); + sequence_name = parse_tree->GetSequenceName(); + drop_type = DropType::SEQUENCE; + break; + } + default: { LOG_ERROR("Not supported Drop type"); } } } diff --git a/src/planner/plan_util.cpp b/src/planner/plan_util.cpp index cb013fb1531..867ed248839 100644 --- a/src/planner/plan_util.cpp +++ b/src/planner/plan_util.cpp @@ -37,7 +37,7 @@ const std::set PlanUtil::GetAffectedIndexes( catalog::CatalogCache &catalog_cache, const parser::SQLStatement &sql_stmt) { std::set index_oids; - std::string db_name, table_name, schema_name; + std::string db_name, table_name, schema_name, session_namespace; switch (sql_stmt.GetType()) { // For INSERT, DELETE, all indexes are affected case StatementType::INSERT: { @@ -46,18 +46,20 @@ const std::set PlanUtil::GetAffectedIndexes( db_name = insert_stmt.GetDatabaseName(); table_name = insert_stmt.GetTableName(); schema_name = insert_stmt.GetSchemaName(); + session_namespace = insert_stmt.GetSessionNamespace(); } PELOTON_FALLTHROUGH; case StatementType::DELETE: { - if (table_name.empty() || db_name.empty() || schema_name.empty()) { + if (table_name.empty() || db_name.empty() || (schema_name.empty() && session_namespace.empty())) { auto &delete_stmt = static_cast(sql_stmt); db_name = delete_stmt.GetDatabaseName(); table_name = delete_stmt.GetTableName(); schema_name = delete_stmt.GetSchemaName(); + session_namespace = delete_stmt.GetSessionNamespace(); } auto indexes_map = catalog_cache.GetDatabaseObject(db_name) - ->GetTableObject(table_name, schema_name) + ->GetTableObject(table_name, schema_name, session_namespace) ->GetIndexObjects(); for (auto &index : indexes_map) { index_oids.insert(index.first); @@ -69,8 +71,9 @@ const std::set PlanUtil::GetAffectedIndexes( db_name = update_stmt.table->GetDatabaseName(); table_name = update_stmt.table->GetTableName(); schema_name = update_stmt.table->GetSchemaName(); + session_namespace = update_stmt.GetSessionNamespace(); auto table_object = catalog_cache.GetDatabaseObject(db_name) - ->GetTableObject(table_name, schema_name); + ->GetTableObject(table_name, schema_name, session_namespace); auto &update_clauses = update_stmt.updates; std::set update_oids; diff --git a/src/traffic_cop/traffic_cop.cpp b/src/traffic_cop/traffic_cop.cpp index a87d99c0ac5..6506848fe32 100644 --- a/src/traffic_cop/traffic_cop.cpp +++ b/src/traffic_cop/traffic_cop.cpp @@ -105,6 +105,14 @@ ResultType TrafficCop::CommitQueryHelper() { // I will block following queries in that transaction until 'COMMIT' or // 'ROLLBACK' After receive 'COMMIT', see if it is rollback or really commit. if (curr_state.second != ResultType::ABORTED) { + //drop all the temp tables if chosen + if (txn->GetCommitOption() == ONCOMMIT_DROP) { + auto temp_table_objects = txn->GetTempTableObjects(); + for (auto iter = temp_table_objects.begin(); iter != temp_table_objects.end(); iter++) { + auto table_ptr = *iter; + catalog::Catalog::GetInstance()->DropTable(table_ptr->GetDatabaseOid(), table_ptr->GetTableOid(), txn); + } + } // txn committed return txn_manager.CommitTransaction(txn); } else { @@ -167,6 +175,7 @@ executor::ExecutionResult TrafficCop::ExecuteHelper( txn = txn_manager.BeginTransaction(thread_id); tcop_txn_state_.emplace(txn, ResultType::SUCCESS); } + txn->temp_session_name_ = session_namespace_; // skip if already aborted if (curr_state.second == ResultType::ABORTED) { @@ -191,9 +200,10 @@ executor::ExecutionResult TrafficCop::ExecuteHelper( }; auto &pool = threadpool::MonoQueuePool::GetInstance(); - pool.SubmitTask([plan, txn, ¶ms, &result_format, on_complete] { + std::string default_database_name = default_database_name_; + pool.SubmitTask([plan, txn, ¶ms, &result_format, on_complete, default_database_name] { executor::PlanExecutor::ExecutePlan(plan, txn, params, result_format, - on_complete); + on_complete, default_database_name); }); is_queuing_ = true; @@ -314,7 +324,7 @@ std::shared_ptr TrafficCop::PrepareStatement( try { // Run binder auto bind_node_visitor = binder::BindNodeVisitor( - tcop_txn_state_.top().first, default_database_name_); + tcop_txn_state_.top().first, default_database_name_, session_namespace_); bind_node_visitor.BindNameToNode( statement->GetStmtParseTreeList()->GetStatement(0)); auto plan = optimizer_->BuildPelotonPlanTree( @@ -382,7 +392,7 @@ bool TrafficCop::BindParamsForCachePlan( } // Run binder auto bind_node_visitor = binder::BindNodeVisitor(tcop_txn_state_.top().first, - default_database_name_); + default_database_name_, session_namespace_); std::vector param_values; for (const std::unique_ptr ¶m : @@ -420,7 +430,7 @@ void TrafficCop::GetTableColumns(parser::TableRef *from_table, auto columns = static_cast( catalog::Catalog::GetInstance()->GetTableWithName( - from_table->GetDatabaseName(), from_table->GetSchemaName(), + from_table->GetDatabaseName(), from_table->GetSchemaName(), session_namespace_, from_table->GetTableName(), GetCurrentTxnState().first)) ->GetSchema() ->GetColumns(); @@ -585,7 +595,7 @@ ResultType TrafficCop::ExecuteStatement( // TODO(Tianyi) Move Statement Replan into Statement's method // to increase coherence auto bind_node_visitor = binder::BindNodeVisitor( - tcop_txn_state_.top().first, default_database_name_); + tcop_txn_state_.top().first, default_database_name_, session_namespace_); bind_node_visitor.BindNameToNode( statement->GetStmtParseTreeList()->GetStatement(0)); auto plan = optimizer_->BuildPelotonPlanTree( @@ -609,5 +619,25 @@ ResultType TrafficCop::ExecuteStatement( } } +void TrafficCop::DropTempTables() { + // begin a transaction + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + //drop all the temp tables under this namespace + catalog::Catalog::GetInstance()->DropTempTables(default_database_name_, session_namespace_, txn); + //drop the schema + catalog::Catalog::GetInstance()->DropSchema(default_database_name_, session_namespace_, txn); + catalog::Catalog::GetInstance()->RemoveCachedSequenceCurrVal(default_database_name_, session_namespace_, txn); + txn_manager.CommitTransaction(txn); +} + +void TrafficCop::CreateTempSchema() { + // begin a transaction + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + catalog::Catalog::GetInstance()->CreateSchema(default_database_name_, session_namespace_, txn); + txn_manager.CommitTransaction(txn); +} + } // namespace tcop } // namespace peloton diff --git a/src/tuning/index_tuner.cpp b/src/tuning/index_tuner.cpp index ca96907e605..569be3524ec 100644 --- a/src/tuning/index_tuner.cpp +++ b/src/tuning/index_tuner.cpp @@ -598,7 +598,7 @@ void IndexTuner::BootstrapTPCC(const std::string &path) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); auto table = catalog->GetTableWithName( - database_name, std::string(DEFUALT_SCHEMA_NAME), table_name, txn); + database_name, std::string(DEFAULT_SCHEMA_NAME), std::string(DEFAULT_SCHEMA_NAME), table_name, txn); txn_manager.CommitTransaction(txn); PELOTON_ASSERT(table != nullptr); for (auto &sample : samples) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 94291523cdd..aa4244e6ed3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -47,7 +47,7 @@ set(TESTING_UTIL_TXN ${PROJECT_SOURCE_DIR}/test/concurrency/testing_trans set(TESTING_UTIL_STATS ${PROJECT_SOURCE_DIR}/test/statistics/testing_stats_util.cpp) set(TESTING_UTIL_SQL ${PROJECT_SOURCE_DIR}/test/sql/testing_sql_util.cpp) set(TESTING_UTIL_INDEX ${PROJECT_SOURCE_DIR}/test/index/testing_index_util.cpp) -set(TESTING_UTIL_CODEGEN ${PROJECT_SOURCE_DIR}/test/codegen/testing_codegen_util.cpp) +set(TESTING_UTIL_CODEGEN ${PROJECT_SOURCE_DIR}/test/codegen/testing_codegen_util.cpp function/sequence_functions_test.cpp) add_library(peloton-test-common EXCLUDE_FROM_ALL ${gmock_srcs} ${HARNESS} ${TESTING_UTIL_EXECUTOR} diff --git a/test/binder/binder_test.cpp b/test/binder/binder_test.cpp index b82df1ec72a..4ec339d96a2 100644 --- a/test/binder/binder_test.cpp +++ b/test/binder/binder_test.cpp @@ -81,7 +81,8 @@ void SetupTables(std::string database_name) { auto parse_tree_list = parser.BuildParseTree(sql); auto parse_tree = parse_tree_list->GetStatement(0); - auto bind_node_visitor = binder::BindNodeVisitor(txn, database_name); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, database_name, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); statement->SetPlanTree( @@ -113,8 +114,8 @@ TEST_F(BinderCorrectnessTest, SelectStatementTest) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); - unique_ptr binder( - new binder::BindNodeVisitor(txn, default_database_name)); + unique_ptr binder(new binder::BindNodeVisitor( + txn, default_database_name, DEFAULT_SCHEMA_NAME)); string selectSQL = "SELECT A.a1, B.b2 FROM A INNER JOIN b ON a.a1 = b.b1 " "WHERE a1 < 100 GROUP BY A.a1, B.b2 HAVING a1 > 50 " @@ -127,14 +128,12 @@ TEST_F(BinderCorrectnessTest, SelectStatementTest) { oid_t db_oid = catalog_ptr->GetDatabaseWithName(default_database_name, txn)->GetOid(); - oid_t tableA_oid = catalog_ptr - ->GetTableWithName(default_database_name, - DEFUALT_SCHEMA_NAME, "a", txn) - ->GetOid(); - oid_t tableB_oid = catalog_ptr - ->GetTableWithName(default_database_name, - DEFUALT_SCHEMA_NAME, "b", txn) - ->GetOid(); + oid_t tableA_oid = + catalog_ptr->GetTableWithName(default_database_name, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "a", txn)->GetOid(); + oid_t tableB_oid = + catalog_ptr->GetTableWithName(default_database_name, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "b", txn)->GetOid(); txn_manager.CommitTransaction(txn); // Check select_list @@ -192,7 +191,8 @@ TEST_F(BinderCorrectnessTest, SelectStatementTest) { LOG_INFO("Checking duplicate alias and table name."); txn = txn_manager.BeginTransaction(); - binder.reset(new binder::BindNodeVisitor(txn, default_database_name)); + binder.reset(new binder::BindNodeVisitor(txn, default_database_name, + DEFAULT_SCHEMA_NAME)); selectSQL = "SELECT * FROM A, B as A"; parse_tree = parser.BuildParseTree(selectSQL); selectStmt = dynamic_cast( @@ -208,7 +208,8 @@ TEST_F(BinderCorrectnessTest, SelectStatementTest) { txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - binder.reset(new binder::BindNodeVisitor(txn, default_database_name)); + binder.reset(new binder::BindNodeVisitor(txn, default_database_name, + DEFAULT_SCHEMA_NAME)); selectSQL = "SELECT * FROM A, A as AA where A.a1 = AA.a2"; parse_tree = parser.BuildParseTree(selectSQL); selectStmt = dynamic_cast( @@ -227,7 +228,8 @@ TEST_F(BinderCorrectnessTest, SelectStatementTest) { txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - binder.reset(new binder::BindNodeVisitor(txn, default_database_name)); + binder.reset(new binder::BindNodeVisitor(txn, default_database_name, + DEFAULT_SCHEMA_NAME)); selectSQL = "SELECT AA.a1, b2 FROM A as AA, B WHERE AA.a1 = B.b1"; parse_tree = parser.BuildParseTree(selectSQL); selectStmt = dynamic_cast( @@ -260,14 +262,13 @@ TEST_F(BinderCorrectnessTest, DeleteStatementTest) { auto txn = txn_manager.BeginTransaction(); oid_t db_oid = catalog_ptr->GetDatabaseWithName(default_database_name, txn)->GetOid(); - oid_t tableB_oid = catalog_ptr - ->GetTableWithName(default_database_name, - DEFUALT_SCHEMA_NAME, "b", txn) - ->GetOid(); + oid_t tableB_oid = + catalog_ptr->GetTableWithName(default_database_name, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "b", txn)->GetOid(); string deleteSQL = "DELETE FROM b WHERE 1 = b1 AND b2 = 'str'"; - unique_ptr binder( - new binder::BindNodeVisitor(txn, default_database_name)); + unique_ptr binder(new binder::BindNodeVisitor( + txn, default_database_name, DEFAULT_SCHEMA_NAME)); auto parse_tree = parser.BuildParseTree(deleteSQL); auto deleteStmt = dynamic_cast( @@ -302,8 +303,8 @@ TEST_F(BinderCorrectnessTest, BindDepthTest) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); - unique_ptr binder( - new binder::BindNodeVisitor(txn, default_database_name)); + unique_ptr binder(new binder::BindNodeVisitor( + txn, default_database_name, DEFAULT_SCHEMA_NAME)); string selectSQL = "SELECT A.a1 FROM A WHERE A.a1 IN (SELECT b1 FROM B WHERE b1 = 2 AND b2 " "> (SELECT a1 FROM A WHERE a2 > 0)) " @@ -351,8 +352,7 @@ TEST_F(BinderCorrectnessTest, BindDepthTest) { in_sub_expr_select_where_right->GetChild(1); auto in_sub_expr_select_where_right_sub_select = dynamic_cast( - in_sub_expr_select_where_right_sub) - ->GetSubSelect(); + in_sub_expr_select_where_right_sub)->GetSubSelect(); auto in_sub_expr_select_where_right_sub_select_where = in_sub_expr_select_where_right_sub_select->where_clause.get(); auto in_sub_expr_select_where_right_sub_select_ele = @@ -391,7 +391,7 @@ TEST_F(BinderCorrectnessTest, FunctionExpressionTest) { auto parse_tree = parser.BuildParseTree(function_sql); auto stmt = parse_tree->GetStatement(0); unique_ptr binder( - new binder::BindNodeVisitor(txn, DEFAULT_DB_NAME)); + new binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME)); EXPECT_THROW(binder->BindNameToNode(stmt), peloton::Exception); function_sql = "SELECT substr('test123', 2, 3)"; diff --git a/test/catalog/catalog_test.cpp b/test/catalog/catalog_test.cpp index 3e6b5e15872..af4ffa48fb5 100644 --- a/test/catalog/catalog_test.cpp +++ b/test/catalog/catalog_test.cpp @@ -43,9 +43,9 @@ TEST_F(CatalogTests, BootstrappingCatalog) { storage::Database *database = catalog->GetDatabaseWithName(CATALOG_DATABASE_NAME, txn); // Check database metric table - storage::DataTable *db_metric_table = - catalog->GetTableWithName(CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, - DATABASE_METRICS_CATALOG_NAME, txn); + storage::DataTable *db_metric_table = catalog->GetTableWithName( + CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + DATABASE_METRICS_CATALOG_NAME, txn); txn_manager.CommitTransaction(txn); EXPECT_NE(nullptr, database); EXPECT_NE(nullptr, db_metric_table); @@ -79,11 +79,11 @@ TEST_F(CatalogTests, CreatingTable) { new catalog::Schema({id_column, name_column})); catalog::Catalog::GetInstance()->CreateTable( - "emp_db", DEFUALT_SCHEMA_NAME, "emp_table", std::move(table_schema), txn); - catalog::Catalog::GetInstance()->CreateTable("emp_db", DEFUALT_SCHEMA_NAME, + "emp_db", DEFAULT_SCHEMA_NAME, "emp_table", std::move(table_schema), txn); + catalog::Catalog::GetInstance()->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, "department_table", std::move(table_schema_2), txn); - catalog::Catalog::GetInstance()->CreateTable("emp_db", DEFUALT_SCHEMA_NAME, + catalog::Catalog::GetInstance()->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, "salary_table", std::move(table_schema_3), txn); // insert random tuple into DATABASE_METRICS_CATALOG and check @@ -111,11 +111,12 @@ TEST_F(CatalogTests, CreatingTable) { EXPECT_EQ(1, param1.len); EXPECT_EQ('a', *param1.buf); // check colum object - EXPECT_EQ("name", catalog::Catalog::GetInstance() - ->GetTableObject("emp_db", DEFUALT_SCHEMA_NAME, - "department_table", txn) - ->GetColumnObject(1) - ->GetColumnName()); + EXPECT_EQ("name", + catalog::Catalog::GetInstance() + ->GetTableObject("emp_db", DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "department_table", txn) + ->GetColumnObject(1) + ->GetColumnName()); txn_manager.CommitTransaction(txn); } @@ -124,7 +125,8 @@ TEST_F(CatalogTests, TableObject) { auto txn = txn_manager.BeginTransaction(); auto table_object = catalog::Catalog::GetInstance()->GetTableObject( - "emp_db", DEFUALT_SCHEMA_NAME, "department_table", txn); + "emp_db", DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "department_table", + txn); auto index_objects = table_object->GetIndexObjects(); auto column_objects = table_object->GetColumnObjects(); @@ -158,7 +160,8 @@ TEST_F(CatalogTests, TableObject) { bool update_result = pg_table->UpdateVersionId(1, department_table_oid, txn); // get version id after update, invalidate old cache table_object = catalog::Catalog::GetInstance()->GetTableObject( - "emp_db", DEFUALT_SCHEMA_NAME, "department_table", txn); + "emp_db", DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "department_table", + txn); uint32_t version_oid = table_object->GetVersionId(); EXPECT_NE(department_table_oid, INVALID_OID); EXPECT_EQ(update_result, true); @@ -234,23 +237,24 @@ TEST_F(CatalogTests, DroppingTable) { auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); auto catalog = catalog::Catalog::GetInstance(); - // NOTE: everytime we create a database, there will be 8 catalog tables inside + // NOTE: everytime we create a database, there will be 9 catalog tables inside EXPECT_EQ( - 11, + 12, (int)catalog->GetDatabaseObject("emp_db", txn)->GetTableObjects().size()); auto database_object = catalog::Catalog::GetInstance()->GetDatabaseObject("emp_db", txn); EXPECT_NE(nullptr, database_object); - catalog::Catalog::GetInstance()->DropTable("emp_db", DEFUALT_SCHEMA_NAME, + catalog::Catalog::GetInstance()->DropTable("emp_db", DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "department_table", txn); database_object = catalog::Catalog::GetInstance()->GetDatabaseObject("emp_db", txn); EXPECT_NE(nullptr, database_object); - auto department_table_object = - database_object->GetTableObject("department_table", DEFUALT_SCHEMA_NAME); + auto department_table_object = database_object->GetTableObject( + "department_table", DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME); EXPECT_EQ( - 10, + 11, (int)catalog->GetDatabaseObject("emp_db", txn)->GetTableObjects().size()); txn_manager.CommitTransaction(txn); @@ -259,30 +263,32 @@ TEST_F(CatalogTests, DroppingTable) { // Try to drop again txn = txn_manager.BeginTransaction(); EXPECT_THROW(catalog::Catalog::GetInstance()->DropTable( - "emp_db", DEFUALT_SCHEMA_NAME, "department_table", txn), + "emp_db", DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn), CatalogException); // EXPECT_EQ( - 10, + 11, (int)catalog->GetDatabaseObject("emp_db", txn)->GetTableObjects().size()); txn_manager.CommitTransaction(txn); // Drop a table that does not exist txn = txn_manager.BeginTransaction(); EXPECT_THROW(catalog::Catalog::GetInstance()->DropTable( - "emp_db", DEFUALT_SCHEMA_NAME, "void_table", txn), + "emp_db", DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "void_table", txn), CatalogException); EXPECT_EQ( - 10, + 11, (int)catalog->GetDatabaseObject("emp_db", txn)->GetTableObjects().size()); txn_manager.CommitTransaction(txn); // Drop the other table txn = txn_manager.BeginTransaction(); - catalog::Catalog::GetInstance()->DropTable("emp_db", DEFUALT_SCHEMA_NAME, - "emp_table", txn); + catalog::Catalog::GetInstance()->DropTable( + "emp_db", DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "emp_table", txn); EXPECT_EQ( - 9, + 10, (int)catalog->GetDatabaseObject("emp_db", txn)->GetTableObjects().size()); txn_manager.CommitTransaction(txn); } diff --git a/test/catalog/constraints_test.cpp b/test/catalog/constraints_test.cpp index d37f4f7081e..dfd8b015a81 100644 --- a/test/catalog/constraints_test.cpp +++ b/test/catalog/constraints_test.cpp @@ -237,10 +237,10 @@ TEST_F(ConstraintsTests, UNIQUETest) { new catalog::Schema({column1, column2})); std::string table_name("TEST_TABLE"); catalog::Catalog::GetInstance()->CreateTable(DEFAULT_DB_NAME, - DEFUALT_SCHEMA_NAME, table_name, + DEFAULT_SCHEMA_NAME, table_name, std::move(table_schema), txn); storage::DataTable *table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, table_name, txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, table_name, txn); txn_manager.CommitTransaction(txn); // table->AddUNIQUEIndex(); diff --git a/test/catalog/psql_temp_table_test.cpp b/test/catalog/psql_temp_table_test.cpp new file mode 100644 index 00000000000..3d815635f21 --- /dev/null +++ b/test/catalog/psql_temp_table_test.cpp @@ -0,0 +1,410 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// psql_temp_table_test.cpp +// +// Identification: test/catalog/psql_temp_table_test.cpp +// +// Copyright (c) 2016-18, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include "common/harness.h" +#include "gtest/gtest.h" +#include "common/logger.h" +#include "network/peloton_server.h" +#include "network/protocol_handler_factory.h" +#include "util/string_util.h" +#include /* libpqxx is used to instantiate C++ client */ +#include "network/postgres_protocol_handler.h" +#include "network/connection_handle_factory.h" +#include "parser/postgresparser.h" +#include "concurrency/transaction_manager_factory.h" +#include "catalog/catalog.h" + +namespace peloton { +namespace test { + +//===--------------------------------------------------------------------===// +// Psql temporary table tests +//===--------------------------------------------------------------------===// + +class PsqlTempTableTests : public PelotonTest {}; + +/** + * Table visibility test - check: + * 1. a temp table makes the permanent table with the same name invisible + * 2. a temp table created by one session is invisible to another session + */ +void TableVisibilityTest(int port) { + LOG_INFO("Start TableVisibilityTest"); + + try { + pqxx::connection C1(StringUtil::Format( + "host=127.0.0.1 port=%d user=default_database sslmode=disable " + "application_name=psql", + port)); + + // Session 1 creates a permanent table, which has one tuple + LOG_INFO("Session 1 creates a permanent table"); + pqxx::work txn11(C1); + txn11.exec("DROP TABLE IF EXISTS employee;"); + txn11.exec("CREATE TABLE employee(id INT, name VARCHAR(100));"); + txn11.exec("INSERT INTO employee VALUES(1, 'trump');"); + + // Session 1 creates a temp table with the same name, which has 2 tuples + LOG_INFO("Session 1 creates a temp table"); + txn11.exec("CREATE TEMP TABLE employee(id INT, name VARCHAR(100));"); + txn11.exec("INSERT INTO employee VALUES(1, 'trump');"); + txn11.exec("INSERT INTO employee VALUES(2, 'trumpet');"); + txn11.commit(); + + // Temp table makes the permanent table invisible + LOG_INFO("Check: Temp table makes the permanent table invisible"); + pqxx::work txn12(C1); + pqxx::result R = txn12.exec("select * from employee;"); + EXPECT_EQ(R.size(), 2); + // However the permanent table is still visible if we explicitly specify + // the "public" namespace + LOG_INFO("Check: Permanent table is still visible given the namespace"); + R = txn12.exec("select * from public.employee;"); + EXPECT_EQ(R.size(), 1); + txn12.commit(); + + // Set up session 2 + // The table visible to session 2 should be the permanent table + LOG_INFO("Check: Permanent table is visible to session 2"); + pqxx::connection C2(StringUtil::Format( + "host=127.0.0.1 port=%d user=default_database sslmode=disable " + "application_name=psql", + port)); + pqxx::work txn21(C2); + R = txn21.exec("select * from employee;"); + EXPECT_EQ(R.size(), 1); + txn21.commit(); + + // Session 2 drops the permanent table + LOG_INFO("Session 2 drops the permanent table"); + pqxx::work txn22(C2); + txn22.exec("drop table employee;"); + txn22.commit(); + + // Now no table is visible to session 2. (The temp table created by + // session 1 is invisible.) + // Expect an exception: "Table [public.]employee is not found" + LOG_INFO("Check: No table is visible to session 2"); + pqxx::work txn23(C2); + try { + txn23.exec("select * from employee;"); + EXPECT_TRUE(false); + } catch (const std::exception &e) { + EXPECT_TRUE(strstr(e.what(), "employee is not found") != nullptr); + } + C2.disconnect(); + + // Session 1 can still see its temp table + LOG_INFO("Check: Session 1 can still see its temp table"); + pqxx::work txn13(C1); + R = txn13.exec("select * from employee;"); + EXPECT_EQ(R.size(), 2); + txn13.commit(); + + // Session 1 drops its temp table + LOG_INFO("Session 1 drops its temp table"); + pqxx::work txn14(C1); + txn14.exec("drop table employee;"); + txn14.commit(); + + // Now no table is visible to session 1 + // Expect an exception: "Table [public.]employee is not found" + LOG_INFO("Check: No table is visible to session 1"); + pqxx::work txn15(C1); + try { + txn15.exec("select * from employee;"); + EXPECT_TRUE(false); + } catch (const std::exception &e) { + EXPECT_TRUE(strstr(e.what(), "employee is not found") != nullptr); + } + C1.disconnect(); + LOG_INFO("Passed TableVisibilityTest"); + } catch (const std::exception &e) { + LOG_ERROR("[TableVisibilityTest] Exception occurred: %s", e.what()); + EXPECT_TRUE(false); + } +} + +/** + * Foreign key test - check foreign key constraints cannot be defined between + * temporary tables and permanent tables. + */ +void ForeignKeyTest(int port) { + LOG_INFO("Start ForeignKeyTest"); + + try { + // Set up connection + pqxx::connection C(StringUtil::Format( + "host=127.0.0.1 port=%d user=default_database sslmode=disable " + "application_name=psql", + port)); + + pqxx::work txn1(C); + // Create permanent table "student" + LOG_INFO("Create permanent table \"student\""); + txn1.exec("DROP TABLE IF EXISTS student;"); + txn1.exec("CREATE TABLE student(id INT PRIMARY KEY, name VARCHAR);"); + // Create temp table "course" + LOG_INFO("Create temp table \"course\""); + txn1.exec("DROP TABLE IF EXISTS course;"); + txn1.exec("CREATE TEMP TABLE course(id INT PRIMARY KEY, name VARCHAR);"); + txn1.commit(); + + // Check a permanent table cannot reference a temp table + LOG_INFO("Check: A permanent table cannot reference a temp table"); + pqxx::work txn2(C); + try { + txn2.exec( + "CREATE TABLE enroll(s_id INT, c_id INT, " + "CONSTRAINT FK_EnrollCourse FOREIGN KEY (c_id) " + "REFERENCES course(id)" // "course" is a temp table + ");"); + EXPECT_TRUE(false); + } catch (const std::exception &e) { + EXPECT_TRUE(strstr(e.what(), + "constraints on permanent tables may reference only " + "permanent tables") != nullptr); + } + + pqxx::work txn3(C); + try { + txn3.exec( + "CREATE TABLE enroll2(s_id INT, c_id INT, " + "CONSTRAINT FK_StudentEnroll FOREIGN KEY (s_id) " + "REFERENCES student(id), " + "CONSTRAINT FK_EnrollCourse FOREIGN KEY (c_id) " + "REFERENCES course(id)" // "course" is a temp table + ");"); + EXPECT_TRUE(false); + } catch (const std::exception &e) { + EXPECT_TRUE(strstr(e.what(), + "constraints on permanent tables may reference only " + "permanent tables") != nullptr); + } + + // Check a temp table cannot reference a permanent table + LOG_INFO("Check: A temp table cannot reference a permanent table"); + pqxx::work txn4(C); + try { + txn4.exec( + "CREATE TEMP TABLE enroll3(s_id INT, c_id INT, " + "CONSTRAINT FK_StudentEnroll FOREIGN KEY (s_id) " + "REFERENCES student(id)" // "student" is a permanent table + ");"); + EXPECT_TRUE(false); + } catch (const std::exception &e) { + EXPECT_TRUE(strstr(e.what(), + "constraints on temporary tables may reference only " + "temporary tables") != nullptr); + } + + pqxx::work txn5(C); + try { + txn5.exec( + "CREATE TEMP TABLE enroll4(s_id INT, c_id INT, " + "CONSTRAINT FK_StudentEnroll FOREIGN KEY (s_id) " + "REFERENCES student(id), " // "student" is a permanent table + "CONSTRAINT FK_EnrollCourse FOREIGN KEY (c_id) " + "REFERENCES course(id)" + ");"); + EXPECT_TRUE(false); + } catch (const std::exception &e) { + EXPECT_TRUE(strstr(e.what(), + "constraints on temporary tables may reference only " + "temporary tables") != nullptr); + } + + pqxx::work txn6(C); + // Create temp table "student" + LOG_INFO("Create temp table \"student\""); + txn6.exec("CREATE TEMP TABLE student(id INT PRIMARY KEY, name VARCHAR);"); + // Now the permanent table "student" becomes invisible. However, it can + // still + // be referenced as a foreign key by a permanent table by explicitly + // specifying the "public" namespace + LOG_INFO( + "Check: A hidden permanent table can be referenced by a given the " + "\"public\" namespace"); + txn6.exec( + "CREATE TABLE enroll5(s_id INT, c_id INT, " + "CONSTRAINT FK_StudentEnroll FOREIGN KEY (s_id) " + "REFERENCES public.student(id)" // note the "public." here + ");"); + txn6.commit(); + + C.disconnect(); + LOG_INFO("Passed ForeignKeyTest"); + } catch (const std::exception &e) { + LOG_ERROR("[ForeignKeyTest] Exception occurred: %s", e.what()); + EXPECT_TRUE(false); + } +} + +/** + * On-commit options test - check the options [ON COMMIT PRESERVE ROWS | + * DELETE ROWS | DROP] are handled correctly + */ +void OnCommitOptionsTest(int port) { + LOG_INFO("Start OnCommitOptionsTest"); + + try { + pqxx::connection C1(StringUtil::Format( + "host=127.0.0.1 port=%d user=default_database sslmode=disable " + "application_name=psql", + port)); + pqxx::work txn11(C1); + + // Begin a transaction + txn11.exec("BEGIN;"); + + LOG_INFO("Creating temp table with default on-commit option"); + // The default option is ON COMMIT PRESERVE ROWS + txn11.exec("DROP TABLE IF EXISTS employee1;"); + txn11.exec("CREATE TEMP TABLE employee1(id INT, name VARCHAR(100));"); + txn11.exec("INSERT INTO employee1 VALUES(1, 'trump');"); + + LOG_INFO("Creating temp table with \"ON COMMIT PRESERVE ROWS\""); + txn11.exec("DROP TABLE IF EXISTS employee2;"); + txn11.exec( + "CREATE TEMP TABLE employee2(id INT, name VARCHAR(100)) ON COMMIT " + "PRESERVE ROWS;"); + txn11.exec("INSERT INTO employee2 VALUES(1, 'trump');"); + txn11.exec("INSERT INTO employee2 VALUES(2, 'trumpet');"); + + LOG_INFO("Creating temp table with \"ON COMMIT DELETE ROWS\""); + txn11.exec("DROP TABLE IF EXISTS employee3;"); + txn11.exec( + "CREATE TEMP TABLE employee3(id INT, name VARCHAR(100)) ON COMMIT " + "DELETE ROWS;"); + txn11.exec("INSERT INTO employee3 VALUES(1, 'trump');"); + txn11.exec("INSERT INTO employee3 VALUES(2, 'trumpet');"); + txn11.exec("INSERT INTO employee3 VALUES(3, 'trumpette');"); + + LOG_INFO("Creating temp table with \"ON COMMIT DROP\""); + txn11.exec("DROP TABLE IF EXISTS employee4;"); + txn11.exec( + "CREATE TEMP TABLE employee4(id INT, name VARCHAR(100)) ON COMMIT " + "DROP;"); + + LOG_INFO("Check: all four tables have been created successfully"); + pqxx::result R = txn11.exec("select * from employee1;"); + EXPECT_EQ(R.size(), 1); + + R = txn11.exec("select * from employee2;"); + EXPECT_EQ(R.size(), 2); + + R = txn11.exec("select * from employee3;"); + EXPECT_EQ(R.size(), 3); + + R = txn11.exec("select * from employee4;"); + EXPECT_EQ(R.size(), 0); + + // Commit the transaction + txn11.exec("COMMIT;"); + + LOG_INFO( + "Check: all rows are preserved for the table created with default " + "on-commit option"); + R = txn11.exec("select * from employee1;"); + EXPECT_EQ(R.size(), 1); + + LOG_INFO( + "Check: all rows are preserved for the table created with \"ON COMMIT " + "PRESERVE ROWS\""); + R = txn11.exec("select * from employee2;"); + EXPECT_EQ(R.size(), 2); + + // Currently ON COMMIT DELETE ROWS is not supported. + // LOG_INFO( + // "Check: all rows are deleted for the table created with \"ON COMMIT " + // "DELETE ROWS\""); + // R = txn11.exec("select * from employee3;"); + // EXPECT_EQ(R.size(), 0); + txn11.commit(); + + LOG_INFO("Check: the table created with \"ON COMMIT DROP\" is dropped"); + pqxx::work txn12(C1); + try { + txn12.exec("select * from employee4;"); + EXPECT_TRUE(false); + } catch (const std::exception &e) { + EXPECT_TRUE(strstr(e.what(), "employee4 is not found") != nullptr); + } + + C1.disconnect(); + + pqxx::connection C2(StringUtil::Format( + "host=127.0.0.1 port=%d user=default_database sslmode=disable " + "application_name=psql", + port)); + + LOG_INFO("Check: all tables are dropped when the session is closed"); + pqxx::work txn21(C2); + try { + txn21.exec("select * from employee1;"); + EXPECT_TRUE(false); + } catch (const std::exception &e) { + EXPECT_TRUE(strstr(e.what(), "employee1 is not found") != nullptr); + } + + pqxx::work txn22(C2); + try { + txn22.exec("select * from employee2;"); + EXPECT_TRUE(false); + } catch (const std::exception &e) { + EXPECT_TRUE(strstr(e.what(), "employee2 is not found") != nullptr); + } + + pqxx::work txn23(C2); + try { + txn23.exec("select * from employee3;"); + EXPECT_TRUE(false); + } catch (const std::exception &e) { + EXPECT_TRUE(strstr(e.what(), "employee3 is not found") != nullptr); + } + + C2.disconnect(); + LOG_INFO("Passed OnCommitOptionsTest"); + } catch (const std::exception &e) { + LOG_ERROR("[OnCommitOptionsTest] Exception occurred: %s", e.what()); + EXPECT_TRUE(false); + } +} + +TEST_F(PsqlTempTableTests, PsqlTempTableTests) { + peloton::PelotonInit::Initialize(); + LOG_INFO("Server initialized"); + + peloton::network::PelotonServer server; + + int port = 15721; + try { + server.SetPort(port); + server.SetupServer(); + } catch (peloton::ConnectionException &exception) { + LOG_INFO("[LaunchServer] Exception when launching server"); + } + std::thread serverThread([&]() { server.ServerLoop(); }); + + TableVisibilityTest(port); + ForeignKeyTest(port); + OnCommitOptionsTest(port); + + server.Close(); + serverThread.join(); + LOG_INFO("Peloton is shutting down"); + peloton::PelotonInit::Shutdown(); + LOG_INFO("Peloton has shut down"); +} + +} // namespace test +} // namespace peloton \ No newline at end of file diff --git a/test/catalog/sequence_catalog_test.cpp b/test/catalog/sequence_catalog_test.cpp new file mode 100644 index 00000000000..10db84e1c14 --- /dev/null +++ b/test/catalog/sequence_catalog_test.cpp @@ -0,0 +1,334 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence_test.cpp +// +// Identification: test/sequence/sequence_test.cpp +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include "catalog/catalog.h" +#include "catalog/sequence_catalog.h" +#include "storage/abstract_table.h" +#include "common/harness.h" +#include "common/exception.h" +#include "executor/executors.h" +#include "parser/postgresparser.h" +#include "planner/create_plan.h" +#include "planner/insert_plan.h" +#include "concurrency/transaction_manager_factory.h" + +namespace peloton { +namespace test { + +class SequenceTests : public PelotonTest { + protected: + void CreateDatabaseHelper() { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + catalog::Catalog::GetInstance()->Bootstrap(); + catalog::Catalog::GetInstance()->CreateDatabase(DEFAULT_DB_NAME, txn); + txn_manager.CommitTransaction(txn); + } + + std::shared_ptr GetSequenceHelper( + std::string sequence_name, concurrency::TransactionContext *txn) { + // Check the effect of creation + oid_t database_oid = catalog::Catalog::GetInstance() + ->GetDatabaseWithName(DEFAULT_DB_NAME, txn) + ->GetOid(); + std::shared_ptr new_sequence = + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetSequenceCatalog() + ->GetSequence(database_oid, sequence_name, txn); + + return new_sequence; + } + + void CreateSequenceHelper(std::string query, + concurrency::TransactionContext *txn) { + auto parser = parser::PostgresParser::GetInstance(); + + std::unique_ptr stmt_list( + parser.BuildParseTree(query).release()); + EXPECT_TRUE(stmt_list->is_valid); + EXPECT_EQ(StatementType::CREATE, stmt_list->GetStatement(0)->GetType()); + auto create_sequence_stmt = + static_cast(stmt_list->GetStatement(0)); + + create_sequence_stmt->TryBindDatabaseName(DEFAULT_DB_NAME); + // Create plans + planner::CreatePlan plan(create_sequence_stmt); + + // plan type + EXPECT_EQ(CreateType::SEQUENCE, plan.GetCreateType()); + + // Execute the create sequence + std::unique_ptr context( + new executor::ExecutorContext(txn)); + executor::CreateExecutor createSequenceExecutor(&plan, context.get()); + createSequenceExecutor.Init(); + createSequenceExecutor.Execute(); + } + + void DropSequenceHelper(std::string query, + concurrency::TransactionContext *txn) { + auto parser = parser::PostgresParser::GetInstance(); + + std::unique_ptr stmt_list( + parser.BuildParseTree(query).release()); + EXPECT_TRUE(stmt_list->is_valid); + EXPECT_EQ(StatementType::DROP, stmt_list->GetStatement(0)->GetType()); + auto drop_sequence_stmt = + static_cast(stmt_list->GetStatement(0)); + + drop_sequence_stmt->TryBindDatabaseName(DEFAULT_DB_NAME); + // Drop plans + planner::DropPlan plan(drop_sequence_stmt); + + // Plan type + EXPECT_EQ(DropType::SEQUENCE, plan.GetDropType()); + + // Execute the drop sequence + std::unique_ptr context( + new executor::ExecutorContext(txn)); + executor::DropExecutor dropSequenceExecutor(&plan, context.get()); + dropSequenceExecutor.Init(); + dropSequenceExecutor.Execute(); + } +}; + +TEST_F(SequenceTests, BasicTest) { + CreateDatabaseHelper(); + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + + // Create statement + std::string query = + "CREATE SEQUENCE seq " + "INCREMENT BY 2 " + "MINVALUE 10 MAXVALUE 50 " + "START 10 CYCLE;"; + std::string name = "seq"; + + CreateSequenceHelper(query, txn); + std::shared_ptr new_sequence = + GetSequenceHelper(name, txn); + + EXPECT_EQ(name, new_sequence->seq_name); + EXPECT_EQ(2, new_sequence->seq_increment); + EXPECT_EQ(10, new_sequence->seq_min); + EXPECT_EQ(50, new_sequence->seq_max); + EXPECT_EQ(10, new_sequence->seq_start); + EXPECT_EQ(true, new_sequence->seq_cycle); + EXPECT_EQ(10, new_sequence->GetNextVal()); + EXPECT_EQ(10, new_sequence->GetCurrVal()); + + txn_manager.CommitTransaction(txn); +} + +TEST_F(SequenceTests, NoDuplicateTest) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + + // Create statement + std::string query = + "CREATE SEQUENCE seq " + "INCREMENT BY 2 " + "MINVALUE 10 MAXVALUE 50 " + "START 10 CYCLE;"; + std::string name = "seq"; + + // Expect exception + try { + CreateSequenceHelper(query, txn); + EXPECT_EQ(0, 1); + } catch (const SequenceException &expected) { + ASSERT_STREQ("Sequence seq already exists!", + expected.what()); + } + txn_manager.CommitTransaction(txn); +} + +TEST_F(SequenceTests, DropTest) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + + // Create statement + std::string query = + "CREATE SEQUENCE seq " + "INCREMENT BY 2 " + "MINVALUE 10 MAXVALUE 50 " + "START 10 CYCLE;"; + std::string name = "seq"; + + // Drop statement + std::string dropQuery = + "DROP SEQUENCE seq"; + + // Expect exception + try { + CreateSequenceHelper(query, txn); + EXPECT_EQ(0, 1); + } catch (const SequenceException &expected) { + ASSERT_STREQ("Sequence seq already exists!", + expected.what()); + } + + + DropSequenceHelper(dropQuery, txn); + try { + CreateSequenceHelper(query, txn); + EXPECT_EQ(1, 1); + } catch (const SequenceException &expected) { + ASSERT_STREQ("Sequence seq already exists!", + expected.what()); + } + + txn_manager.CommitTransaction(txn); +} + +TEST_F(SequenceTests, NextValPosIncrementFunctionalityTest) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + + std::string query = + "CREATE SEQUENCE seq1 " + "INCREMENT BY 1 " + "MINVALUE 10 MAXVALUE 50 " + "START 10 CYCLE;"; + std::string name = "seq1"; + + CreateSequenceHelper(query, txn); + std::shared_ptr new_sequence = + GetSequenceHelper(name, txn); + + int64_t nextVal = new_sequence->GetNextVal(); + EXPECT_EQ(10, nextVal); + nextVal = new_sequence->GetNextVal(); + EXPECT_EQ(11, nextVal); + + // test cycle + new_sequence->SetCurrVal(50); + nextVal = new_sequence->GetNextVal(); + nextVal = new_sequence->GetNextVal(); + EXPECT_EQ(10, nextVal); + + // test no cycle + new_sequence->SetCycle(false); + new_sequence->SetCurrVal(50); + + // Expect exception + try { + nextVal = new_sequence->GetNextVal(); + EXPECT_EQ(0, 1); + } catch (const SequenceException &expected) { + ASSERT_STREQ("nextval: reached maximum value of sequence seq1 (50)", expected.what()); + } + txn_manager.CommitTransaction(txn); +} + +TEST_F(SequenceTests, NextValNegIncrementFunctionalityTest) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + + std::string query = + "CREATE SEQUENCE seq2 " + "INCREMENT BY -1 " + "MINVALUE 10 MAXVALUE 50 " + "START 10 CYCLE;"; + std::string name = "seq2"; + + CreateSequenceHelper(query, txn); + std::shared_ptr new_sequence = + GetSequenceHelper(name, txn); + + // test cycle + int64_t nextVal = new_sequence->GetNextVal(); + EXPECT_EQ(10, nextVal); + nextVal = new_sequence->GetNextVal(); + EXPECT_EQ(50, nextVal); + + new_sequence->SetCurrVal(49); + nextVal = new_sequence->GetNextVal(); + nextVal = new_sequence->GetNextVal(); + EXPECT_EQ(48, nextVal); + + // test no cycle + new_sequence->SetCycle(false); + new_sequence->SetCurrVal(10); + + // Expect exception + try { + nextVal = new_sequence->GetNextVal(); + EXPECT_EQ(0, 1); + } catch (const SequenceException &expected) { + ASSERT_STREQ("nextval: reached minimum value of sequence seq2 (10)", expected.what()); + } + txn_manager.CommitTransaction(txn); +} + +TEST_F(SequenceTests, InvalidArgumentTest) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + + std::string query = + "CREATE SEQUENCE seq3 " + "INCREMENT BY -1 " + "MINVALUE 50 MAXVALUE 10 " + "START 10 CYCLE;"; + + try { + CreateSequenceHelper(query, txn); + EXPECT_EQ(0, 1); + } catch (const SequenceException &expected) { + ASSERT_STREQ("MINVALUE (50) must be no greater than MAXVALUE (10)", expected.what()); + } + + query = + "CREATE SEQUENCE seq3 " + "INCREMENT BY 0 " + "MINVALUE 10 MAXVALUE 50 " + "START 10 CYCLE;"; + + try { + CreateSequenceHelper(query, txn); + EXPECT_EQ(0, 1); + } catch (const SequenceException &expected) { + ASSERT_STREQ("INCREMENT must not be zero", expected.what()); + } + + query = + "CREATE SEQUENCE seq3 " + "INCREMENT BY 1 " + "MINVALUE 10 MAXVALUE 50 " + "START 8 CYCLE;"; + + try { + CreateSequenceHelper(query, txn); + EXPECT_EQ(0, 1); + } catch (const SequenceException &expected) { + ASSERT_STREQ("START value (8) cannot be less than MINVALUE (10)", expected.what()); + } + + query = + "CREATE SEQUENCE seq3 " + "INCREMENT BY -1 " + "MINVALUE 10 MAXVALUE 50 " + "START 60 CYCLE;"; + + try { + CreateSequenceHelper(query, txn); + EXPECT_EQ(0, 1); + } catch (const SequenceException &expected) { + ASSERT_STREQ("START value (60) cannot be greater than MAXVALUE (50)", expected.what()); + } + + txn_manager.CommitTransaction(txn); +} +} +} diff --git a/test/codegen/bloom_filter_test.cpp b/test/codegen/bloom_filter_test.cpp index bf9962ca834..810b0bf29f4 100644 --- a/test/codegen/bloom_filter_test.cpp +++ b/test/codegen/bloom_filter_test.cpp @@ -167,7 +167,7 @@ TEST_F(BloomFilterCodegenTest, FalsePositiveRateTest) { ASSERT_TRUE(code_context.Compile()); - typedef void (*ftype)(codegen::util::BloomFilter * bloom_filter, int *, int, + typedef void (*ftype)(codegen::util::BloomFilter *bloom_filter, int *, int, int *); ftype f = (ftype)code_context.GetRawFunctionPointer(func.GetFunction()); @@ -213,8 +213,9 @@ TEST_F(BloomFilterCodegenTest, PerformanceTest) { int curr_size = 0; std::vector numbers; std::unordered_set number_set; - auto *table1 = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, - table1_name, txn); + auto *table1 = + catalog->GetTableWithName(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, table1_name, txn); while (curr_size < table1_target_size) { // Find a unique random number int random; @@ -234,8 +235,9 @@ TEST_F(BloomFilterCodegenTest, PerformanceTest) { LOG_INFO("Finish populating test1"); // Load the inner table which contains twice tuples as the outer table - auto *table2 = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, - table2_name, txn); + auto *table2 = + catalog->GetTableWithName(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, table2_name, txn); unsigned outer_table_cardinality = numbers.size() * outer_to_inner_ratio; for (unsigned i = 0; i < outer_table_cardinality; i++) { int number; @@ -334,7 +336,7 @@ void BloomFilterCodegenTest::CreateTable(std::string table_name, int tuple_size, } auto *catalog = catalog::Catalog::GetInstance(); catalog->CreateTable( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, table_name, + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, table_name, std::unique_ptr(new catalog::Schema(cols)), txn); } diff --git a/test/codegen/table_scan_translator_test.cpp b/test/codegen/table_scan_translator_test.cpp index 881e24a6996..608a92bc24c 100644 --- a/test/codegen/table_scan_translator_test.cpp +++ b/test/codegen/table_scan_translator_test.cpp @@ -67,11 +67,12 @@ class TableScanTranslatorTest : public PelotonCodeGenTest { std::unique_ptr schema{new catalog::Schema(cols)}; // Insert table in catalog - catalog->CreateTable(test_db_name, DEFUALT_SCHEMA_NAME, all_cols_table_name, + catalog->CreateTable(test_db_name, DEFAULT_SCHEMA_NAME, all_cols_table_name, std::move(schema), txn); all_cols_table = catalog->GetTableWithName( - test_db_name, DEFUALT_SCHEMA_NAME, all_cols_table_name, txn); + test_db_name, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + all_cols_table_name, txn); auto *table_schema = all_cols_table->GetSchema(); // Insert one row where all columns are NULL @@ -150,8 +151,8 @@ TEST_F(TableScanTranslatorTest, AllColumnsScanWithNulls) { auto &tuple = buffer.GetOutputTuples()[0]; for (uint32_t i = 0; i < all_col_ids.size(); i++) { auto col_val = tuple.GetValue(i); - EXPECT_TRUE(col_val.IsNull()) - << "Result value: " << col_val.ToString() << ", expected NULL"; + EXPECT_TRUE(col_val.IsNull()) << "Result value: " << col_val.ToString() + << ", expected NULL"; } } diff --git a/test/codegen/testing_codegen_util.cpp b/test/codegen/testing_codegen_util.cpp index fe8f6c26440..7200a9c1f06 100644 --- a/test/codegen/testing_codegen_util.cpp +++ b/test/codegen/testing_codegen_util.cpp @@ -107,25 +107,23 @@ void PelotonCodeGenTest::CreateTestTables(concurrency::TransactionContext *txn, auto *catalog = catalog::Catalog::GetInstance(); for (int i = 0; i < 4; i++) { auto table_schema = CreateTestSchema(); - catalog->CreateTable(test_db_name, DEFUALT_SCHEMA_NAME, test_table_names[i], + catalog->CreateTable(test_db_name, DEFAULT_SCHEMA_NAME, test_table_names[i], std::move(table_schema), txn, false, tuples_per_tilegroup); - test_table_oids.push_back(catalog - ->GetTableObject(test_db_name, - DEFUALT_SCHEMA_NAME, - test_table_names[i], txn) - ->GetTableOid()); + test_table_oids.push_back( + catalog->GetTableObject(test_db_name, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, test_table_names[i], + txn)->GetTableOid()); } for (int i = 4; i < 5; i++) { auto table_schema = CreateTestSchema(true); - catalog->CreateTable(test_db_name, DEFUALT_SCHEMA_NAME, test_table_names[i], + catalog->CreateTable(test_db_name, DEFAULT_SCHEMA_NAME, test_table_names[i], std::move(table_schema), txn, false, tuples_per_tilegroup); - test_table_oids.push_back(catalog - ->GetTableObject(test_db_name, - DEFUALT_SCHEMA_NAME, - test_table_names[i], txn) - ->GetTableOid()); + test_table_oids.push_back( + catalog->GetTableObject(test_db_name, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, test_table_names[i], + txn)->GetTableOid()); } } @@ -138,9 +136,8 @@ void PelotonCodeGenTest::LoadTestTable(oid_t table_id, uint32_t num_rows, auto *table_schema = test_table.GetSchema(); size_t curr_size = test_table.GetTupleCount(); - auto col_val = [](uint32_t tuple_id, uint32_t col_id) { - return 10 * tuple_id + col_id; - }; + auto col_val = + [](uint32_t tuple_id, uint32_t col_id) { return 10 * tuple_id + col_id; }; const bool allocate = true; auto testing_pool = TestingHarness::GetInstance().GetTestingPool(); diff --git a/test/executor/copy_test.cpp b/test/executor/copy_test.cpp index 77c1c9eecc9..23e1e01e032 100644 --- a/test/executor/copy_test.cpp +++ b/test/executor/copy_test.cpp @@ -124,7 +124,8 @@ TEST_F(CopyTests, Copying) { LOG_TRACE("Binding parse tree..."); auto parse_tree = copy_stmt->GetStatement(0); - auto bind_node_visitor = binder::BindNodeVisitor(txn, db_name); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, db_name, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_TRACE("Binding parse tree completed!"); diff --git a/test/executor/create_index_test.cpp b/test/executor/create_index_test.cpp index 034eca553fa..c948464aa7b 100644 --- a/test/executor/create_index_test.cpp +++ b/test/executor/create_index_test.cpp @@ -83,7 +83,8 @@ TEST_F(CreateIndexTests, CreatingIndex) { LOG_INFO("Binding parse tree..."); auto parse_tree = create_stmt->GetStatement(0); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -134,7 +135,8 @@ TEST_F(CreateIndexTests, CreatingIndex) { LOG_INFO("Binding parse tree..."); parse_tree = insert_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -176,7 +178,8 @@ TEST_F(CreateIndexTests, CreatingIndex) { LOG_INFO("Binding parse tree..."); parse_tree = update_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -205,7 +208,8 @@ TEST_F(CreateIndexTests, CreatingIndex) { txn = txn_manager.BeginTransaction(); auto target_table_ = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); // Expected 2 , Primary key index + created index EXPECT_EQ(target_table_->GetIndexCount(), 2); diff --git a/test/executor/create_test.cpp b/test/executor/create_test.cpp index 0faede0508d..8de8b3c249b 100644 --- a/test/executor/create_test.cpp +++ b/test/executor/create_test.cpp @@ -99,7 +99,7 @@ TEST_F(CreateTests, CreatingTable) { new executor::ExecutorContext(txn)); // Create plans - planner::CreatePlan node("department_table", DEFUALT_SCHEMA_NAME, + planner::CreatePlan node("department_table", DEFAULT_SCHEMA_NAME, DEFAULT_DB_NAME, std::move(table_schema), CreateType::TABLE); @@ -141,7 +141,7 @@ TEST_F(CreateTests, CreatingUDFs) { new executor::ExecutorContext(txn)); // Create plans - planner::CreatePlan node("accounts", DEFUALT_SCHEMA_NAME, DEFAULT_DB_NAME, + planner::CreatePlan node("accounts", DEFAULT_SCHEMA_NAME, DEFAULT_DB_NAME, std::move(table_schema), CreateType::TABLE); // Create executer @@ -243,7 +243,7 @@ TEST_F(CreateTests, CreatingTrigger) { new executor::ExecutorContext(txn)); // Create plans - planner::CreatePlan node("accounts", DEFUALT_SCHEMA_NAME, DEFAULT_DB_NAME, + planner::CreatePlan node("accounts", DEFAULT_SCHEMA_NAME, DEFAULT_DB_NAME, std::move(table_schema), CreateType::TABLE); // Create executer @@ -299,15 +299,13 @@ TEST_F(CreateTests, CreatingTrigger) { EXPECT_EQ(ExpressionType::VALUE_TUPLE, left->GetExpressionType()); EXPECT_EQ("old", static_cast(left) ->GetTableName()); - EXPECT_EQ("balance", - static_cast(left) - ->GetColumnName()); + EXPECT_EQ("balance", static_cast( + left)->GetColumnName()); EXPECT_EQ(ExpressionType::VALUE_TUPLE, right->GetExpressionType()); EXPECT_EQ("new", static_cast(right) ->GetTableName()); - EXPECT_EQ("balance", - static_cast(right) - ->GetColumnName()); + EXPECT_EQ("balance", static_cast( + right)->GetColumnName()); // type (level, timing, event) auto trigger_type = plan.GetTriggerType(); // level @@ -333,7 +331,8 @@ TEST_F(CreateTests, CreatingTrigger) { // Check the effect of creation storage::DataTable *target_table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "accounts", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "accounts", + txn); txn_manager.CommitTransaction(txn); EXPECT_EQ(1, target_table->GetTriggerNumber()); trigger::Trigger *new_trigger = target_table->GetTriggerByIndex(0); @@ -373,7 +372,7 @@ TEST_F(CreateTests, CreatingTriggerWithoutWhen) { new executor::ExecutorContext(txn)); // Create plans - planner::CreatePlan node("accounts", DEFUALT_SCHEMA_NAME, DEFAULT_DB_NAME, + planner::CreatePlan node("accounts", DEFAULT_SCHEMA_NAME, DEFAULT_DB_NAME, std::move(table_schema), CreateType::TABLE); // Create executer @@ -421,7 +420,8 @@ TEST_F(CreateTests, CreatingTriggerWithoutWhen) { // Check the effect of creation storage::DataTable *target_table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "accounts", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "accounts", + txn); txn_manager.CommitTransaction(txn); EXPECT_EQ(1, target_table->GetTriggerNumber()); trigger::Trigger *new_trigger = target_table->GetTriggerByIndex(0); @@ -462,7 +462,7 @@ TEST_F(CreateTests, CreatingTriggerInCatalog) { new executor::ExecutorContext(txn)); // Create plans - planner::CreatePlan node("accounts", DEFUALT_SCHEMA_NAME, DEFAULT_DB_NAME, + planner::CreatePlan node("accounts", DEFAULT_SCHEMA_NAME, DEFAULT_DB_NAME, std::move(table_schema), CreateType::TABLE); // Create executer @@ -502,7 +502,8 @@ TEST_F(CreateTests, CreatingTriggerInCatalog) { // check whether the trigger catalog table contains this new trigger auto table_object = catalog::Catalog::GetInstance()->GetTableObject( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "accounts", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "accounts", + txn); auto trigger_list = catalog::Catalog::GetInstance() ->GetSystemCatalogs(table_object->GetDatabaseOid()) diff --git a/test/executor/delete_test.cpp b/test/executor/delete_test.cpp index f081b766720..4810ad66539 100644 --- a/test/executor/delete_test.cpp +++ b/test/executor/delete_test.cpp @@ -69,7 +69,8 @@ void ShowTable(std::string database_name, std::string table_name) { peloton_parser.BuildParseTree("SELECT * FROM " + table_name); auto parse_tree = select_stmt->GetStatement(0); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); statement->SetPlanTree(optimizer.BuildPelotonPlanTree(select_stmt, txn)); @@ -116,7 +117,7 @@ TEST_F(DeleteTests, VariousOperations) { new catalog::Schema({id_column, name_column})); std::unique_ptr context( new executor::ExecutorContext(txn)); - planner::CreatePlan node("department_table", DEFUALT_SCHEMA_NAME, + planner::CreatePlan node("department_table", DEFAULT_SCHEMA_NAME, DEFAULT_DB_NAME, std::move(table_schema), CreateType::TABLE); executor::CreateExecutor create_executor(&node, context.get()); @@ -125,7 +126,8 @@ TEST_F(DeleteTests, VariousOperations) { LOG_INFO("Table created!"); storage::DataTable *table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); @@ -147,7 +149,8 @@ TEST_F(DeleteTests, VariousOperations) { LOG_INFO("Binding parse tree..."); auto parse_tree = insert_stmt->GetStatement(0); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -191,7 +194,8 @@ TEST_F(DeleteTests, VariousOperations) { LOG_INFO("Binding parse tree..."); parse_tree = insert_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -232,7 +236,8 @@ TEST_F(DeleteTests, VariousOperations) { LOG_INFO("Binding parse tree..."); parse_tree = insert_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -273,7 +278,8 @@ TEST_F(DeleteTests, VariousOperations) { LOG_INFO("Binding parse tree..."); parse_tree = select_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -313,7 +319,8 @@ TEST_F(DeleteTests, VariousOperations) { LOG_INFO("Binding parse tree..."); parse_tree = delete_stmt_2->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -353,7 +360,8 @@ TEST_F(DeleteTests, VariousOperations) { LOG_INFO("Binding parse tree..."); parse_tree = delete_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); diff --git a/test/executor/drop_test.cpp b/test/executor/drop_test.cpp index 19e6c1293da..e277dd7dc4f 100644 --- a/test/executor/drop_test.cpp +++ b/test/executor/drop_test.cpp @@ -96,29 +96,29 @@ TEST_F(DropTests, DroppingTable) { txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - catalog->CreateTable(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", + catalog->CreateTable(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table", std::move(table_schema), txn); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - catalog->CreateTable(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table_2", + catalog->CreateTable(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table_2", std::move(table_schema2), txn); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - // NOTE: everytime we create a database, there will be 8 catalog tables inside + // NOTE: everytime we create a database, there will be 9 catalog tables inside EXPECT_EQ((int)catalog->GetDatabaseObject(TEST_DB_NAME, txn) ->GetTableObjects() .size(), - 10); + 11); // Now dropping the table using the executor - catalog->DropTable(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", - txn); + catalog->DropTable(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); EXPECT_EQ((int)catalog->GetDatabaseObject(TEST_DB_NAME, txn) ->GetTableObjects() .size(), - 9); + 10); // free the database just created catalog->DropDatabaseWithName(TEST_DB_NAME, txn); @@ -148,7 +148,7 @@ TEST_F(DropTests, DroppingTrigger) { txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - catalog->CreateTable(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", + catalog->CreateTable(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table", std::move(table_schema), txn); txn_manager.CommitTransaction(txn); @@ -180,7 +180,8 @@ TEST_F(DropTests, DroppingTrigger) { // Check the effect of creation storage::DataTable *target_table = catalog::Catalog::GetInstance()->GetTableWithName( - TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", txn); + TEST_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); txn_manager.CommitTransaction(txn); EXPECT_EQ(1, target_table->GetTriggerNumber()); trigger::Trigger *new_trigger = target_table->GetTriggerByIndex(0); @@ -212,9 +213,9 @@ TEST_F(DropTests, DroppingTrigger) { // Now dropping the table using the executer txn = txn_manager.BeginTransaction(); - catalog->DropTable(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", - txn); - EXPECT_EQ(8, (int)catalog::Catalog::GetInstance() + catalog->DropTable(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); + EXPECT_EQ(9, (int)catalog::Catalog::GetInstance() ->GetDatabaseObject(TEST_DB_NAME, txn) ->GetTableObjects() .size()); @@ -250,20 +251,21 @@ TEST_F(DropTests, DroppingIndexByName) { txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - catalog->CreateTable(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table_01", + catalog->CreateTable(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table_01", std::move(table_schema), txn); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); auto source_table = catalog->GetTableWithName( - TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table_01", txn); + TEST_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table_01", txn); 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"; - catalog->CreateIndex(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table_01", - source_col_ids, index_name1, false, IndexType::BWTREE, - txn); + catalog->CreateIndex(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table_01", source_col_ids, index_name1, + false, IndexType::BWTREE, txn); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); @@ -276,26 +278,26 @@ TEST_F(DropTests, DroppingIndexByName) { ->GetSystemCatalogs(database_object->GetDatabaseOid()) ->GetIndexCatalog(); auto index_object = - pg_index->GetIndexObject(index_name1, DEFUALT_SCHEMA_NAME, txn); + pg_index->GetIndexObject(index_name1, DEFAULT_SCHEMA_NAME, txn); EXPECT_NE(nullptr, index_object); // Check the effect of drop // Most major check in this test case // Now dropping the index using the DropIndex functionality catalog->DropIndex(database_object->GetDatabaseOid(), index_object->GetIndexOid(), txn); - EXPECT_EQ(pg_index->GetIndexObject(index_name1, DEFUALT_SCHEMA_NAME, txn), + EXPECT_EQ(pg_index->GetIndexObject(index_name1, DEFAULT_SCHEMA_NAME, txn), nullptr); txn_manager.CommitTransaction(txn); // Drop the table just created txn = txn_manager.BeginTransaction(); // Check the effect of drop index - EXPECT_EQ(pg_index->GetIndexObject(index_name1, DEFUALT_SCHEMA_NAME, txn), + EXPECT_EQ(pg_index->GetIndexObject(index_name1, DEFAULT_SCHEMA_NAME, txn), nullptr); // Now dropping the table - catalog->DropTable(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table_01", - txn); + catalog->DropTable(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table_01", txn); txn_manager.CommitTransaction(txn); // free the database just created diff --git a/test/executor/insert_test.cpp b/test/executor/insert_test.cpp index 4499eb6f53e..0ab246f3ea6 100644 --- a/test/executor/insert_test.cpp +++ b/test/executor/insert_test.cpp @@ -53,11 +53,12 @@ TEST_F(InsertTests, InsertRecord) { txn = txn_manager.BeginTransaction(); catalog::Catalog::GetInstance()->CreateTable( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "TEST_TABLE", + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, "TEST_TABLE", std::move(table_schema), txn); auto table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "TEST_TABLE", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "TEST_TABLE", + txn); txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); diff --git a/test/executor/update_test.cpp b/test/executor/update_test.cpp index f8f3c12d0a2..7e0b0f762c2 100644 --- a/test/executor/update_test.cpp +++ b/test/executor/update_test.cpp @@ -176,7 +176,7 @@ TEST_F(UpdateTests, UpdatingOld) { new catalog::Schema({id_column, manager_id_column, name_column})); std::unique_ptr context( new executor::ExecutorContext(txn)); - planner::CreatePlan node("department_table", DEFUALT_SCHEMA_NAME, + planner::CreatePlan node("department_table", DEFAULT_SCHEMA_NAME, DEFAULT_DB_NAME, std::move(table_schema), CreateType::TABLE); executor::CreateExecutor create_executor(&node, context.get()); @@ -185,8 +185,9 @@ TEST_F(UpdateTests, UpdatingOld) { LOG_INFO("Table created!"); - storage::DataTable *table = catalog->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", txn); + storage::DataTable *table = + catalog->GetTableWithName(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "department_table", txn); txn_manager.CommitTransaction(txn); // Inserting a tuple end-to-end @@ -211,7 +212,8 @@ TEST_F(UpdateTests, UpdatingOld) { LOG_INFO("Binding parse tree..."); auto parse_tree = insert_stmt->GetStatement(0); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -259,7 +261,8 @@ TEST_F(UpdateTests, UpdatingOld) { LOG_INFO("Binding parse tree..."); parse_tree = update_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -304,7 +307,8 @@ TEST_F(UpdateTests, UpdatingOld) { LOG_INFO("Binding parse tree..."); parse_tree = update_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -344,7 +348,8 @@ TEST_F(UpdateTests, UpdatingOld) { LOG_INFO("Binding parse tree..."); parse_tree = update_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); @@ -385,7 +390,8 @@ TEST_F(UpdateTests, UpdatingOld) { LOG_INFO("Binding parse tree..."); parse_tree = delete_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); LOG_INFO("Binding parse tree completed!"); diff --git a/test/function/sequence_functions_test.cpp b/test/function/sequence_functions_test.cpp new file mode 100644 index 00000000000..97425629b2e --- /dev/null +++ b/test/function/sequence_functions_test.cpp @@ -0,0 +1,112 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence_functions_test.cpp +// +// Identification: test/function/sequence_functions_test.cpp +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include "catalog/catalog.h" +#include "catalog/sequence_catalog.h" +#include "storage/abstract_table.h" +#include "common/harness.h" +#include "common/exception.h" +#include "executor/executors.h" +#include "parser/postgresparser.h" +#include "planner/create_plan.h" +#include "executor/executor_context.h" +#include "function/sequence_functions.h" +#include "concurrency/transaction_manager_factory.h" + +using ::testing::NotNull; +using ::testing::Return; + +namespace peloton { +namespace test { + +class SequenceFunctionsTests : public PelotonTest { + + protected: + void CreateDatabaseHelper() { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + catalog::Catalog::GetInstance()->Bootstrap(); + catalog::Catalog::GetInstance()->CreateDatabase(DEFAULT_DB_NAME, txn); + txn_manager.CommitTransaction(txn); + } + + void CreateSequenceHelper(std::string query, + concurrency::TransactionContext *txn) { + auto parser = parser::PostgresParser::GetInstance(); + + std::unique_ptr stmt_list( + parser.BuildParseTree(query).release()); + EXPECT_TRUE(stmt_list->is_valid); + EXPECT_EQ(StatementType::CREATE, stmt_list->GetStatement(0)->GetType()); + auto create_sequence_stmt = + static_cast(stmt_list->GetStatement(0)); + + create_sequence_stmt->TryBindDatabaseName(DEFAULT_DB_NAME); + // Create plans + planner::CreatePlan plan(create_sequence_stmt); + + // plan type + EXPECT_EQ(CreateType::SEQUENCE, plan.GetCreateType()); + + // Execute the create sequence + std::unique_ptr context( + new executor::ExecutorContext(txn, {}, DEFAULT_DB_NAME)); + executor::CreateExecutor createSequenceExecutor(&plan, context.get()); + createSequenceExecutor.Init(); + createSequenceExecutor.Execute(); + } + +}; +TEST_F(SequenceFunctionsTests, BasicTest) { + CreateDatabaseHelper(); + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + + // Create statement + std::string query = "CREATE SEQUENCE seq;"; + + CreateSequenceHelper(query, txn); + txn_manager.CommitTransaction(txn); +} + +TEST_F(SequenceFunctionsTests, FunctionsTest) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + std::unique_ptr context( + new executor::ExecutorContext(txn, {}, DEFAULT_DB_NAME)); + + // Expect exception + try { + function::SequenceFunctions::Currval(*(context.get()), "seq"); + EXPECT_EQ(0, 1); + } catch (const SequenceException &expected) { + ASSERT_STREQ("currval for sequence \"seq\" is undefined for this session", expected.what()); + } + + // Check nextval & currval functionality + auto res = function::SequenceFunctions::Nextval(*(context.get()), "seq"); + EXPECT_EQ(1, res); + + res = function::SequenceFunctions::Currval(*(context.get()), "seq"); + EXPECT_EQ(1, res); + + res = function::SequenceFunctions::Nextval(*(context.get()), "seq"); + EXPECT_EQ(2, res); + + txn_manager.CommitTransaction(txn); +} +} // namespace test +} // namespace peloton diff --git a/test/include/catalog/testing_constraints_util.h b/test/include/catalog/testing_constraints_util.h index 30a9b658223..a7be54f7787 100644 --- a/test/include/catalog/testing_constraints_util.h +++ b/test/include/catalog/testing_constraints_util.h @@ -132,14 +132,15 @@ class TestingConstraintsUtil { // Create table. txn = txn_manager.BeginTransaction(); auto result = - catalog->CreateTable(DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, table_name, + catalog->CreateTable(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, table_name, std::move(table_schema), txn, false); txn_manager.CommitTransaction(txn); EXPECT_EQ(ResultType::SUCCESS, result); txn = txn_manager.BeginTransaction(); - auto table = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, - table_name, txn); + auto table = + catalog->GetTableWithName(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, table_name, txn); txn_manager.CommitTransaction(txn); EXPECT_NE(nullptr, table); diff --git a/test/optimizer/old_optimizer_test.cpp b/test/optimizer/old_optimizer_test.cpp index 1069ab87909..1849965231c 100644 --- a/test/optimizer/old_optimizer_test.cpp +++ b/test/optimizer/old_optimizer_test.cpp @@ -75,7 +75,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { "dept_name TEXT);"); auto parse_tree = create_stmt->GetStatement(0); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); statement->SetPlanTree(optimizer.BuildPelotonPlanTree(create_stmt, txn)); @@ -117,7 +118,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { "(1,52,'hello_1');"); parse_tree = insert_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); statement->SetPlanTree(optimizer.BuildPelotonPlanTree(insert_stmt, txn)); @@ -149,7 +151,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { "CREATE INDEX saif ON department_table (student_id);"); parse_tree = update_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); statement->SetPlanTree(optimizer.BuildPelotonPlanTree(update_stmt, txn)); @@ -171,7 +174,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { txn = txn_manager.BeginTransaction(); auto target_table_ = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); // Expected 1 , Primary key index + created index EXPECT_EQ(target_table_->GetIndexCount(), 2); txn_manager.CommitTransaction(txn); @@ -186,7 +190,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { "UPDATE department_table SET dept_name = 'CS' WHERE student_id = 52"); parse_tree = update_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); auto update_plan = optimizer.BuildPelotonPlanTree(update_stmt, txn); @@ -203,7 +208,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { "UPDATE department_table SET dept_name = 'CS' WHERE dept_name = 'CS'"); parse_tree = update_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); update_plan = optimizer.BuildPelotonPlanTree(update_stmt, txn); @@ -219,7 +225,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { "DELETE FROM department_table WHERE student_id = 52"); parse_tree = delete_stmt->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); auto del_plan = optimizer.BuildPelotonPlanTree(delete_stmt, txn); @@ -237,7 +244,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { "DELETE FROM department_table WHERE dept_name = 'CS'"); parse_tree = delete_stmt_seq->GetStatement(0); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); auto del_plan_seq = optimizer.BuildPelotonPlanTree(delete_stmt_seq, txn); diff --git a/test/optimizer/operator_transformer_test.cpp b/test/optimizer/operator_transformer_test.cpp index f1d5229798c..75f1bd3c420 100644 --- a/test/optimizer/operator_transformer_test.cpp +++ b/test/optimizer/operator_transformer_test.cpp @@ -59,7 +59,7 @@ class OperatorTransformerTests : public PelotonTest { reinterpret_cast(stmt_list->GetStatement(0)); // Bind query - binder::BindNodeVisitor binder(txn, DEFAULT_DB_NAME); + binder::BindNodeVisitor binder(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); binder.BindNameToNode(stmt); QueryToOperatorTransformer transformer(txn); @@ -79,7 +79,7 @@ class OperatorTransformerTests : public PelotonTest { "SELECT %s FROM %s", true_predicates.c_str(), table_names.c_str()); auto parsed_stmt = peloton_parser.BuildParseTree(ref_query); auto ref_stmt = parsed_stmt->GetStatement(0); - binder::BindNodeVisitor binder(txn, DEFAULT_DB_NAME); + binder::BindNodeVisitor binder(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); binder.BindNameToNode(ref_stmt); auto ref_expr = ((parser::SelectStatement *)ref_stmt)->select_list.at(0).get(); diff --git a/test/optimizer/optimizer_test.cpp b/test/optimizer/optimizer_test.cpp index dae410999d6..161b568014f 100644 --- a/test/optimizer/optimizer_test.cpp +++ b/test/optimizer/optimizer_test.cpp @@ -96,7 +96,8 @@ TEST_F(OptimizerTests, HashJoinTest) { auto create_stmt = peloton_parser.BuildParseTree( "CREATE TABLE table_a(aid INT PRIMARY KEY,value INT);"); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(create_stmt->GetStatement(0)); statement->SetPlanTree(optimizer.BuildPelotonPlanTree(create_stmt, txn)); @@ -119,7 +120,7 @@ TEST_F(OptimizerTests, HashJoinTest) { LOG_INFO("Table Created"); traffic_cop.CommitQueryHelper(); - // NOTE: everytime we create a database, there will be 8 catalog tables inside + // NOTE: everytime we create a database, there will be 9 catalog tables inside txn = txn_manager.BeginTransaction(); EXPECT_EQ(catalog::Catalog::GetInstance() ->GetDatabaseWithName(DEFAULT_DB_NAME, txn) @@ -135,7 +136,8 @@ TEST_F(OptimizerTests, HashJoinTest) { create_stmt = peloton_parser.BuildParseTree( "CREATE TABLE table_b(bid INT PRIMARY KEY,value INT);"); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(create_stmt->GetStatement(0)); statement->SetPlanTree(optimizer.BuildPelotonPlanTree(create_stmt, txn)); @@ -171,7 +173,8 @@ TEST_F(OptimizerTests, HashJoinTest) { auto insert_stmt = peloton_parser.BuildParseTree( "INSERT INTO table_a(aid, value) VALUES (1, 1);"); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(insert_stmt->GetStatement(0)); statement->SetPlanTree(optimizer.BuildPelotonPlanTree(insert_stmt, txn)); @@ -201,7 +204,8 @@ TEST_F(OptimizerTests, HashJoinTest) { insert_stmt = peloton_parser.BuildParseTree( "INSERT INTO table_b(bid, value) VALUES (1, 2);"); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(insert_stmt->GetStatement(0)); statement->SetPlanTree(optimizer.BuildPelotonPlanTree(insert_stmt, txn)); @@ -230,7 +234,8 @@ TEST_F(OptimizerTests, HashJoinTest) { auto select_stmt = peloton_parser.BuildParseTree( "SELECT * FROM table_a INNER JOIN table_b ON aid = bid;"); - bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(select_stmt->GetStatement(0)); statement->SetPlanTree(optimizer.BuildPelotonPlanTree(select_stmt, txn)); @@ -271,7 +276,8 @@ TEST_F(OptimizerTests, PredicatePushDownTest) { optimizer::Optimizer optimizer; txn = txn_manager.BeginTransaction(); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(stmt->GetStatement(0)); auto plan = optimizer.BuildPelotonPlanTree(stmt, txn); @@ -323,10 +329,9 @@ TEST_F(OptimizerTests, PushFilterThroughJoinTest) { "SELECT * FROM test, test1 WHERE test.a = test1.a AND test1.b = 22"); auto parse_tree = stmt->GetStatement(0); auto predicates = std::vector(); - optimizer::util::SplitPredicates( - reinterpret_cast(parse_tree) - ->where_clause.get(), - predicates); + optimizer::util::SplitPredicates(reinterpret_cast( + parse_tree)->where_clause.get(), + predicates); optimizer::Optimizer optimizer; // Only include PushFilterThroughJoin rewrite rule @@ -335,7 +340,8 @@ TEST_F(OptimizerTests, PushFilterThroughJoinTest) { RewriteRuleSetName::PREDICATE_PUSH_DOWN, new PushFilterThroughJoin()); txn = txn_manager.BeginTransaction(); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); std::shared_ptr gexpr = @@ -405,10 +411,9 @@ TEST_F(OptimizerTests, PredicatePushDownRewriteTest) { "SELECT * FROM test, test1 WHERE test.a = test1.a AND test1.b = 22"); auto parse_tree = stmt->GetStatement(0); auto predicates = std::vector(); - optimizer::util::SplitPredicates( - reinterpret_cast(parse_tree) - ->where_clause.get(), - predicates); + optimizer::util::SplitPredicates(reinterpret_cast( + parse_tree)->where_clause.get(), + predicates); optimizer::Optimizer optimizer; // Only include PushFilterThroughJoin rewrite rule @@ -422,7 +427,8 @@ TEST_F(OptimizerTests, PredicatePushDownRewriteTest) { txn = txn_manager.BeginTransaction(); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); std::shared_ptr gexpr = diff --git a/test/optimizer/selectivity_test.cpp b/test/optimizer/selectivity_test.cpp index 0f5e4a9ab8c..9c903c170e1 100644 --- a/test/optimizer/selectivity_test.cpp +++ b/test/optimizer/selectivity_test.cpp @@ -72,8 +72,9 @@ TEST_F(SelectivityTests, RangeSelectivityTest) { txn = txn_manager.BeginTransaction(); auto catalog = catalog::Catalog::GetInstance(); auto database = catalog->GetDatabaseWithName(DEFAULT_DB_NAME, txn); - auto table = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, - TEST_TABLE_NAME, txn); + auto table = + catalog->GetTableWithName(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, TEST_TABLE_NAME, txn); txn_manager.CommitTransaction(txn); oid_t db_id = database->GetOid(); oid_t table_id = table->GetOid(); @@ -181,8 +182,9 @@ TEST_F(SelectivityTests, EqualSelectivityTest) { txn = txn_manager.BeginTransaction(); auto catalog = catalog::Catalog::GetInstance(); auto database = catalog->GetDatabaseWithName(DEFAULT_DB_NAME, txn); - auto table = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, - TEST_TABLE_NAME, txn); + auto table = + catalog->GetTableWithName(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, TEST_TABLE_NAME, txn); txn_manager.CommitTransaction(txn); oid_t db_id = database->GetOid(); oid_t table_id = table->GetOid(); diff --git a/test/optimizer/table_stats_collector_test.cpp b/test/optimizer/table_stats_collector_test.cpp index 7cafebe3e9e..e7f97ed0d46 100644 --- a/test/optimizer/table_stats_collector_test.cpp +++ b/test/optimizer/table_stats_collector_test.cpp @@ -60,8 +60,8 @@ TEST_F(TableStatsCollectorTests, SingleColumnTableTest) { } txn = txn_manager.BeginTransaction(); - auto table = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, - "test", txn); + auto table = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "test", txn); txn_manager.CommitTransaction(txn); TableStatsCollector stats{table}; stats.CollectColumnStats(); @@ -111,8 +111,8 @@ TEST_F(TableStatsCollectorTests, MultiColumnTableTest) { } txn = txn_manager.BeginTransaction(); - auto table = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, - "test", txn); + auto table = catalog->GetTableWithName(DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "test", txn); txn_manager.CommitTransaction(txn); TableStatsCollector stats{table}; stats.CollectColumnStats(); diff --git a/test/optimizer/tuple_samples_storage_test.cpp b/test/optimizer/tuple_samples_storage_test.cpp index 2103d63549c..104aa214c20 100644 --- a/test/optimizer/tuple_samples_storage_test.cpp +++ b/test/optimizer/tuple_samples_storage_test.cpp @@ -84,8 +84,9 @@ TEST_F(TupleSamplesStorageTests, AddSamplesTableTest) { tuple_samples_storage->GenerateSamplesTableName( data_table->GetDatabaseOid(), data_table->GetOid()); txn = txn_manager.BeginTransaction(); - storage::DataTable *samples_table = catalog->GetTableWithName( - SAMPLES_DB_NAME, DEFUALT_SCHEMA_NAME, samples_table_name, txn); + storage::DataTable *samples_table = + catalog->GetTableWithName(SAMPLES_DB_NAME, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, samples_table_name, txn); txn_manager.CommitTransaction(txn); EXPECT_TRUE(samples_table != nullptr); diff --git a/test/parser/parser_test.cpp b/test/parser/parser_test.cpp index 93abf1c497c..7b55acfe16f 100644 --- a/test/parser/parser_test.cpp +++ b/test/parser/parser_test.cpp @@ -65,6 +65,15 @@ TEST_F(ParserTests, BasicTest) { "CREATE TABLE students (name TEXT, student_number INTEGER, city TEXT, " "grade DOUBLE)"); + // CREATE temporary table + queries.push_back("CREATE TEMP TABLE t1(id INT);"); + queries.push_back("CREATE TEMPORARY TABLE t1(id INT);"); + queries.push_back("CREATE GLOBAL TEMP TABLE t1(id INT);"); + queries.push_back("CREATE LOCAL TEMP TABLE t1(id INT);"); + queries.push_back("CREATE TEMP TABLE t1(id INT) ON COMMIT PRESERVE ROWS;"); + queries.push_back("CREATE TEMP TABLE t1(id INT) ON COMMIT DELETE ROWS;"); + queries.push_back("CREATE TEMP TABLE t1(id INT) ON COMMIT DROP;"); + // Multiple statements queries.push_back( "CREATE TABLE students (name TEXT, student_number INTEGER); SELECT * " diff --git a/test/parser/postgresparser_test.cpp b/test/parser/postgresparser_test.cpp index 36910bdc9a9..94c591086b6 100644 --- a/test/parser/postgresparser_test.cpp +++ b/test/parser/postgresparser_test.cpp @@ -1,4 +1,5 @@ //===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// // // Peloton // @@ -588,8 +589,7 @@ TEST_F(PostgresParserTests, InsertTest) { CmpBool res = five.CompareEquals( ((expression::ConstantValueExpression *)insert_stmt->insert_values.at(1) .at(1) - .get()) - ->GetValue()); + .get())->GetValue()); EXPECT_EQ(CmpBool::CmpTrue, res); // LOG_TRACE("%d : %s", ++ii, stmt_list->GetInfo().c_str()); @@ -1021,15 +1021,13 @@ TEST_F(PostgresParserTests, CreateTriggerTest) { EXPECT_EQ(ExpressionType::VALUE_TUPLE, left->GetExpressionType()); EXPECT_EQ("old", static_cast(left) ->GetTableName()); - EXPECT_EQ("balance", - static_cast(left) - ->GetColumnName()); + EXPECT_EQ("balance", static_cast( + left)->GetColumnName()); EXPECT_EQ(ExpressionType::VALUE_TUPLE, right->GetExpressionType()); EXPECT_EQ("new", static_cast(right) ->GetTableName()); - EXPECT_EQ("balance", - static_cast(right) - ->GetColumnName()); + EXPECT_EQ("balance", static_cast( + right)->GetColumnName()); // level // the level is for each row EXPECT_TRUE(TRIGGER_FOR_ROW(create_trigger_stmt->trigger_type)); @@ -1068,6 +1066,55 @@ TEST_F(PostgresParserTests, DropTriggerTest) { EXPECT_EQ("films", drop_trigger_stmt->GetTriggerTableName()); } +TEST_F(PostgresParserTests, CreateSequenceTest) { + auto parser = parser::PostgresParser::GetInstance(); + + // missing AS, CACHE and OWNED BY. + std::string query = + "CREATE SEQUENCE seq " + "INCREMENT BY 2 " + "MINVALUE 10 " + "MAXVALUE 50 " + "CYCLE " + "START 10;"; + std::unique_ptr stmt_list( + parser.BuildParseTree(query).release()); + EXPECT_TRUE(stmt_list->is_valid); + EXPECT_EQ(StatementType::CREATE, stmt_list->GetStatement(0)->GetType()); + auto create_sequence_stmt = + static_cast(stmt_list->GetStatement(0)); + + // The following code checks the arguments in the create statement + // are identical to what is specified in the query. + + // create type + EXPECT_EQ(parser::CreateStatement::CreateType::kSequence, + create_sequence_stmt->type); + EXPECT_EQ(10, create_sequence_stmt->seq_start); + EXPECT_EQ(2, create_sequence_stmt->seq_increment); + EXPECT_EQ(50, create_sequence_stmt->seq_max_value); + EXPECT_EQ(10, create_sequence_stmt->seq_min_value); + EXPECT_EQ(true, create_sequence_stmt->seq_cycle); +} + +TEST_F(PostgresParserTests, DropSequenceTest) { + auto parser = parser::PostgresParser::GetInstance(); + std::string query = "DROP SEQUENCE seq;"; + std::unique_ptr stmt_list( + parser.BuildParseTree(query).release()); + EXPECT_TRUE(stmt_list->is_valid); + if (!stmt_list->is_valid) { + LOG_ERROR("Message: %s, line: %d, col: %d", stmt_list->parser_msg, + stmt_list->error_line, stmt_list->error_col); + } + EXPECT_EQ(StatementType::DROP, stmt_list->GetStatement(0)->GetType()); + auto drop_sequence_stmt = + static_cast(stmt_list->GetStatement(0)); + // drop type + EXPECT_EQ(parser::DropStatement::EntityType::kSequence, + drop_sequence_stmt->GetDropType()); +} + TEST_F(PostgresParserTests, FuncCallTest) { std::string query = "SELECT add(1,a), chr(99) FROM TEST WHERE FUN(b) > 2"; diff --git a/test/planner/plan_util_test.cpp b/test/planner/plan_util_test.cpp index 8455e98efac..152ac62339b 100644 --- a/test/planner/plan_util_test.cpp +++ b/test/planner/plan_util_test.cpp @@ -54,10 +54,11 @@ TEST_F(PlanUtilTests, GetAffectedIndexesTest) { txn_manager.CommitTransaction(txn); txn = txn_manager.BeginTransaction(); - catalog->CreateTable(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "test_table", + catalog->CreateTable(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, "test_table", std::move(table_schema), txn); - auto source_table = catalog->GetTableWithName( - TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "test_table", txn); + auto source_table = + catalog->GetTableWithName(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "test_table", txn); EXPECT_NE(source_table, nullptr); txn_manager.CommitTransaction(txn); @@ -67,16 +68,16 @@ TEST_F(PlanUtilTests, GetAffectedIndexesTest) { source_col_ids.push_back(col_id); // create index on 'id' - catalog->CreateIndex(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "test_table", - source_col_ids, "test_id_idx", false, IndexType::BWTREE, - txn); + catalog->CreateIndex(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "test_table", source_col_ids, "test_id_idx", false, + IndexType::BWTREE, txn); // create index on 'id' and 'first_name' col_id = source_table->GetSchema()->GetColumnID(fname_column.column_name); source_col_ids.push_back(col_id); - catalog->CreateIndex(TEST_DB_NAME, DEFUALT_SCHEMA_NAME, "test_table", - source_col_ids, "test_fname_idx", false, + catalog->CreateIndex(TEST_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "test_table", source_col_ids, "test_fname_idx", false, IndexType::BWTREE, txn); txn_manager.CommitTransaction(txn); @@ -90,8 +91,8 @@ TEST_F(PlanUtilTests, GetAffectedIndexesTest) { // And two indexes on following columns: // 1) id // 2) id and first_name - auto table_object = - db_object->GetTableObject("test_table", DEFUALT_SCHEMA_NAME); + auto table_object = db_object->GetTableObject( + "test_table", DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME); EXPECT_NE(table_object, nullptr); oid_t id_idx_oid = table_object->GetIndexObject("test_id_idx")->GetIndexOid(); oid_t fname_idx_oid = @@ -198,14 +199,15 @@ TEST_F(PlanUtilTests, GetIndexableColumnsTest) { new catalog::Schema({id_column, fname_column, lname_column})); txn = txn_manager.BeginTransaction(); - catalog->CreateTable(TEST_DB_COLUMNS, DEFUALT_SCHEMA_NAME, "test_table", + catalog->CreateTable(TEST_DB_COLUMNS, DEFAULT_SCHEMA_NAME, "test_table", std::move(table_schema), txn); txn_manager.CommitTransaction(txn); // Obtain ids for the table and columns txn = txn_manager.BeginTransaction(); - auto source_table = catalog->GetTableWithName( - TEST_DB_COLUMNS, DEFUALT_SCHEMA_NAME, "test_table", txn); + auto source_table = + catalog->GetTableWithName(TEST_DB_COLUMNS, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "test_table", txn); txn_manager.CommitTransaction(txn); oid_t table_id = source_table->GetOid(); @@ -228,14 +230,15 @@ TEST_F(PlanUtilTests, GetIndexableColumnsTest) { std::unique_ptr job_table_schema( new catalog::Schema({age_column, job_column, pid_column})); - catalog->CreateTable(TEST_DB_COLUMNS, DEFUALT_SCHEMA_NAME, "test_table_job", + catalog->CreateTable(TEST_DB_COLUMNS, DEFAULT_SCHEMA_NAME, "test_table_job", std::move(job_table_schema), txn); txn_manager.CommitTransaction(txn); // Obtain ids for the table and columns txn = txn_manager.BeginTransaction(); - auto source_table_job = catalog->GetTableWithName( - TEST_DB_COLUMNS, DEFUALT_SCHEMA_NAME, "test_table_job", txn); + auto source_table_job = + catalog->GetTableWithName(TEST_DB_COLUMNS, DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "test_table_job", txn); oid_t table_job_id = source_table_job->GetOid(); oid_t age_col_oid = source_table_job->GetSchema()->GetColumnID(age_column.column_name); @@ -258,7 +261,8 @@ TEST_F(PlanUtilTests, GetIndexableColumnsTest) { auto &peloton_parser = parser::PostgresParser::GetInstance(); auto sql_stmt_list = peloton_parser.BuildParseTree(query_string); auto sql_stmt = sql_stmt_list->GetStatement(0); - auto bind_node_visitor = binder::BindNodeVisitor(txn, TEST_DB_COLUMNS); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, TEST_DB_COLUMNS, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(sql_stmt); std::vector affected_cols_vector = planner::PlanUtil::GetIndexableColumns( diff --git a/test/planner/planner_equality_test.cpp b/test/planner/planner_equality_test.cpp index fe109bc9dff..849810b5ca4 100644 --- a/test/planner/planner_equality_test.cpp +++ b/test/planner/planner_equality_test.cpp @@ -66,7 +66,8 @@ class PlannerEqualityTest : public PelotonTest { auto parsed_stmt = peloton_parser.BuildParseTree(query); auto parse_tree = parsed_stmt->GetStatement(0); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parse_tree); auto return_value = optimizer->BuildPelotonPlanTree(parsed_stmt, txn); diff --git a/test/planner/planner_test.cpp b/test/planner/planner_test.cpp index 7b263bccd79..ef57c3357c9 100644 --- a/test/planner/planner_test.cpp +++ b/test/planner/planner_test.cpp @@ -85,7 +85,7 @@ TEST_F(PlannerTest, DeletePlanTestParameter) { std::unique_ptr table_schema( new catalog::Schema({id_column, name_column})); catalog::Catalog::GetInstance()->CreateTable( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table", std::move(table_schema), txn); txn_manager.CommitTransaction(txn); @@ -100,7 +100,8 @@ TEST_F(PlannerTest, DeletePlanTestParameter) { ExpressionType::COMPARE_EQUAL, tuple_expr, parameter_expr); auto target_table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); // Create delete plan std::unique_ptr delete_plan( @@ -149,7 +150,7 @@ TEST_F(PlannerTest, UpdatePlanTestParameter) { std::unique_ptr table_schema( new catalog::Schema({id_column, name_column})); catalog::Catalog::GetInstance()->CreateTable( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table", std::move(table_schema), txn); txn_manager.CommitTransaction(txn); @@ -159,7 +160,7 @@ TEST_F(PlannerTest, UpdatePlanTestParameter) { auto table_name = std::string("department_table"); auto database_name = DEFAULT_DB_NAME; auto target_table = catalog::Catalog::GetInstance()->GetTableWithName( - database_name, DEFUALT_SCHEMA_NAME, table_name, txn); + database_name, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, table_name, txn); auto schema = target_table->GetSchema(); TargetList tlist; @@ -246,7 +247,7 @@ TEST_F(PlannerTest, InsertPlanTestParameter) { std::unique_ptr table_schema( new catalog::Schema({id_column, name_column})); auto ret = catalog::Catalog::GetInstance()->CreateTable( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table", std::move(table_schema), txn); if (ret != ResultType::SUCCESS) LOG_TRACE("create table failed"); txn_manager.CommitTransaction(txn); @@ -276,7 +277,8 @@ TEST_F(PlannerTest, InsertPlanTestParameter) { std::unique_ptr(parameter_expr_2)); auto target_table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); std::unique_ptr insert_plan( new planner::InsertPlan(target_table, &insert_statement->columns, @@ -287,10 +289,9 @@ TEST_F(PlannerTest, InsertPlanTestParameter) { LOG_INFO("Binding values"); std::vector values; values.push_back(type::ValueFactory::GetIntegerValue(1).Copy()); - values.push_back( - type::ValueFactory::GetVarcharValue( - (std::string) "CS", TestingHarness::GetInstance().GetTestingPool()) - .Copy()); + values.push_back(type::ValueFactory::GetVarcharValue( + (std::string) "CS", + TestingHarness::GetInstance().GetTestingPool()).Copy()); LOG_INFO("Value 1: %s", values.at(0).GetInfo().c_str()); LOG_INFO("Value 2: %s", values.at(1).GetInfo().c_str()); // bind values to parameters in plan @@ -320,7 +321,7 @@ TEST_F(PlannerTest, InsertPlanTestParameterColumns) { std::unique_ptr table_schema( new catalog::Schema({id_column, name_column})); catalog::Catalog::GetInstance()->CreateTable( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, "department_table", std::move(table_schema), txn); txn_manager.CommitTransaction(txn); @@ -354,7 +355,8 @@ TEST_F(PlannerTest, InsertPlanTestParameterColumns) { std::unique_ptr(parameter_expr_2)); auto target_table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "department_table", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "department_table", txn); std::unique_ptr insert_plan( new planner::InsertPlan(target_table, &insert_statement->columns, @@ -364,10 +366,9 @@ TEST_F(PlannerTest, InsertPlanTestParameterColumns) { // VALUES(1, "CS") LOG_INFO("Binding values"); std::vector values; - values.push_back( - type::ValueFactory::GetVarcharValue( - (std::string) "CS", TestingHarness::GetInstance().GetTestingPool()) - .Copy()); + values.push_back(type::ValueFactory::GetVarcharValue( + (std::string) "CS", + TestingHarness::GetInstance().GetTestingPool()).Copy()); LOG_INFO("Value 1: %s", values.at(0).GetInfo().c_str()); // bind values to parameters in plan insert_plan->SetParameterValues(&values); diff --git a/test/sql/analyze_sql_test.cpp b/test/sql/analyze_sql_test.cpp index 16191ec000d..30bbfdf0f52 100644 --- a/test/sql/analyze_sql_test.cpp +++ b/test/sql/analyze_sql_test.cpp @@ -75,7 +75,8 @@ TEST_F(AnalyzeSQLTests, AnalyzeSingleTableTest) { auto catalog = catalog::Catalog::GetInstance(); storage::DataTable *db_column_stats_collector_table = catalog->GetTableWithName(CATALOG_DATABASE_NAME, CATALOG_SCHEMA_NAME, - COLUMN_STATS_CATALOG_NAME, txn); + DEFAULT_SCHEMA_NAME, COLUMN_STATS_CATALOG_NAME, + txn); EXPECT_NE(db_column_stats_collector_table, nullptr); EXPECT_EQ(db_column_stats_collector_table->GetTupleCount(), 4); diff --git a/test/sql/drop_sql_test.cpp b/test/sql/drop_sql_test.cpp index 64f6af5f001..0a375e50e6a 100644 --- a/test/sql/drop_sql_test.cpp +++ b/test/sql/drop_sql_test.cpp @@ -41,7 +41,7 @@ TEST_F(DropSQLTests, DropTableTest) { txn = txn_manager.BeginTransaction(); try { table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "test", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "test", txn); } catch (CatalogException &e) { table = nullptr; } @@ -77,7 +77,7 @@ TEST_F(DropSQLTests, DropTableTest) { txn = txn_manager.BeginTransaction(); try { table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "test", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "test", txn); } catch (CatalogException &e) { txn_manager.CommitTransaction(txn); table = nullptr; @@ -114,7 +114,7 @@ TEST_F(DropSQLTests, DropIndexTest) { std::shared_ptr index; txn = txn_manager.BeginTransaction(); try { - index = pg_index->GetIndexObject("idx", DEFUALT_SCHEMA_NAME, txn); + index = pg_index->GetIndexObject("idx", DEFAULT_SCHEMA_NAME, txn); } catch (CatalogException &e) { index = nullptr; @@ -128,7 +128,7 @@ TEST_F(DropSQLTests, DropIndexTest) { // Check if index is not in catalog txn = txn_manager.BeginTransaction(); - index = pg_index->GetIndexObject("idx", DEFUALT_SCHEMA_NAME, txn); + index = pg_index->GetIndexObject("idx", DEFAULT_SCHEMA_NAME, txn); EXPECT_EQ(index, nullptr); // Free the database just created diff --git a/test/sql/optimizer_sql_test.cpp b/test/sql/optimizer_sql_test.cpp index a81734c529d..735fbd4fae9 100644 --- a/test/sql/optimizer_sql_test.cpp +++ b/test/sql/optimizer_sql_test.cpp @@ -132,10 +132,9 @@ class OptimizerSQLTests : public PelotonTest { TEST_F(OptimizerSQLTests, SimpleSelectTest) { // Testing select star expression - TestUtil( - "SELECT * from test", - {"333", "22", "1", "2", "11", "0", "3", "33", "444", "4", "0", "555"}, - false); + TestUtil("SELECT * from test", {"333", "22", "1", "2", "11", "0", "3", "33", + "444", "4", "0", "555"}, + false); // Something wrong with column property. string query = "SELECT b from test order by c"; @@ -230,10 +229,9 @@ TEST_F(OptimizerSQLTests, SelectOrderByTest) { true); // Testing order by * expression - TestUtil( - "SELECT * from test order by a", - {"1", "22", "333", "2", "11", "0", "3", "33", "444", "4", "0", "555"}, - true); + TestUtil("SELECT * from test order by a", {"1", "22", "333", "2", "11", "0", + "3", "33", "444", "4", "0", "555"}, + true); } TEST_F(OptimizerSQLTests, SelectLimitTest) { @@ -332,7 +330,7 @@ TEST_F(OptimizerSQLTests, DDLSqlTest) { auto txn = txn_manager.BeginTransaction(); // using transaction to get table from catalog auto table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "test2", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "test2", txn); EXPECT_NE(nullptr, table); auto cols = table->GetSchema()->GetColumns(); EXPECT_EQ(3, cols.size()); @@ -354,7 +352,8 @@ TEST_F(OptimizerSQLTests, DDLSqlTest) { txn = txn_manager.BeginTransaction(); EXPECT_THROW(catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "test2", txn), + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + "test2", txn), peloton::Exception); txn_manager.CommitTransaction(txn); } @@ -613,14 +612,7 @@ TEST_F(OptimizerSQLTests, JoinTest) { "SELECT A.b, B.b FROM test1 as A, test1 as B " "WHERE A.a = B.a", { - "22", - "22", - "22", - "22", - "11", - "11", - "0", - "0", + "22", "22", "22", "22", "11", "11", "0", "0", }, false); diff --git a/test/sql/testing_sql_util.cpp b/test/sql/testing_sql_util.cpp index 220fa558686..df6cbc2ea2b 100644 --- a/test/sql/testing_sql_util.cpp +++ b/test/sql/testing_sql_util.cpp @@ -111,7 +111,8 @@ ResultType TestingSQLUtil::ExecuteSQLQueryWithOptimizer( auto parsed_stmt = peloton_parser.BuildParseTree(query); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parsed_stmt->GetStatement(0)); auto plan = optimizer->BuildPelotonPlanTree(parsed_stmt, txn); @@ -150,7 +151,8 @@ TestingSQLUtil::GeneratePlanWithOptimizer( auto parsed_stmt = peloton_parser.BuildParseTree(query); - auto bind_node_visitor = binder::BindNodeVisitor(txn, DEFAULT_DB_NAME); + auto bind_node_visitor = + binder::BindNodeVisitor(txn, DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME); bind_node_visitor.BindNameToNode(parsed_stmt->GetStatement(0)); auto return_value = optimizer->BuildPelotonPlanTree(parsed_stmt, txn); diff --git a/test/statistics/stats_test.cpp b/test/statistics/stats_test.cpp index a53775e67a6..8dc8721c59c 100644 --- a/test/statistics/stats_test.cpp +++ b/test/statistics/stats_test.cpp @@ -136,16 +136,16 @@ TEST_F(StatsTests, MultiThreadStatsTest) { std::unique_ptr table_schema( new catalog::Schema({id_column, name_column})); catalog->CreateDatabase("emp_db", txn); - catalog::Catalog::GetInstance()->CreateTable( - "emp_db", DEFUALT_SCHEMA_NAME, "department_table", - std::move(table_schema), txn); + catalog::Catalog::GetInstance()->CreateTable("emp_db", DEFAULT_SCHEMA_NAME, + "department_table", + std::move(table_schema), txn); // Create multiple stat worker threads int num_threads = 8; - storage::Database *database = - catalog->GetDatabaseWithName("emp_db", txn); - storage::DataTable *table = catalog->GetTableWithName( - "emp_db", DEFUALT_SCHEMA_NAME, "department_table", txn); + storage::Database *database = catalog->GetDatabaseWithName("emp_db", txn); + storage::DataTable *table = + catalog->GetTableWithName("emp_db", DEFAULT_SCHEMA_NAME, + DEFAULT_SCHEMA_NAME, "department_table", txn); txn_manager.CommitTransaction(txn); LaunchParallelTest(num_threads, TransactionTest, database, table); // Wait for aggregation to finish diff --git a/test/statistics/testing_stats_util.cpp b/test/statistics/testing_stats_util.cpp index 7b0f87852fe..5c087e4aba4 100644 --- a/test/statistics/testing_stats_util.cpp +++ b/test/statistics/testing_stats_util.cpp @@ -125,7 +125,7 @@ void TestingStatsUtil::CreateTable(bool has_primary_key) { auto txn = txn_manager.BeginTransaction(); std::unique_ptr context( new executor::ExecutorContext(txn)); - planner::CreatePlan node("department_table", DEFUALT_SCHEMA_NAME, "emp_db", + 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(); diff --git a/test/trigger/trigger_test.cpp b/test/trigger/trigger_test.cpp index ea22d4deca5..f3aa919ccaf 100644 --- a/test/trigger/trigger_test.cpp +++ b/test/trigger/trigger_test.cpp @@ -56,7 +56,7 @@ class TriggerTests : public PelotonTest { new executor::ExecutorContext(txn)); // Create plans - planner::CreatePlan node(table_name, DEFUALT_SCHEMA_NAME, DEFAULT_DB_NAME, + planner::CreatePlan node(table_name, DEFAULT_SCHEMA_NAME, DEFAULT_DB_NAME, std::move(table_schema), CreateType::TABLE); // Create executer @@ -73,7 +73,8 @@ class TriggerTests : public PelotonTest { auto txn = txn_manager.BeginTransaction(); auto table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, std::string(table_name), txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + std::string(table_name), txn); std::unique_ptr context( new executor::ExecutorContext(txn)); @@ -148,7 +149,8 @@ class TriggerTests : public PelotonTest { // Check the effect of creation storage::DataTable *target_table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, table_name, txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, + table_name, txn); txn_manager.CommitTransaction(txn); EXPECT_EQ(trigger_number, target_table->GetTriggerNumber()); trigger::Trigger *new_trigger = target_table->GetTriggerByIndex(0); @@ -276,7 +278,8 @@ TEST_F(TriggerTests, BeforeAndAfterRowInsertTriggers) { // Check the effect of creation storage::DataTable *target_table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "accounts", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "accounts", + txn); txn_manager.CommitTransaction(txn); EXPECT_EQ(1, target_table->GetTriggerNumber()); trigger::Trigger *new_trigger = target_table->GetTriggerByIndex(0); @@ -363,7 +366,8 @@ TEST_F(TriggerTests, AfterStatmentInsertTriggers) { // Check the effect of creation storage::DataTable *target_table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, "accounts", txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, "accounts", + txn); txn_manager.CommitTransaction(txn); EXPECT_EQ(1, target_table->GetTriggerNumber()); trigger::Trigger *new_trigger = target_table->GetTriggerByIndex(0); @@ -467,7 +471,8 @@ TEST_F(TriggerTests, OtherTypesTriggers) { auto txn = txn_manager.BeginTransaction(); storage::DataTable *target_table = catalog::Catalog::GetInstance()->GetTableWithName( - DEFAULT_DB_NAME, DEFUALT_SCHEMA_NAME, table_name, txn); + DEFAULT_DB_NAME, DEFAULT_SCHEMA_NAME, DEFAULT_SCHEMA_NAME, table_name, + txn); txn_manager.CommitTransaction(txn); trigger::TriggerList *new_trigger_list = target_table->GetTriggerList();