From 30d48acd6624e4fd8e6741bfbf7abb7dd1e879d0 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Thu, 22 Mar 2018 16:07:15 -0400 Subject: [PATCH 01/29] finish part of parser; need to add handler function in create_executor.cpp --- sequence_test.sql | 4 + src/common/internal_types.cpp | 6 ++ src/executor/create_executor.cpp | 7 ++ src/include/common/internal_types.h | 8 +- src/include/parser/create_statement.h | 12 ++- src/include/parser/parsenodes.h | 10 ++ src/include/parser/postgresparser.h | 7 ++ src/include/planner/create_plan.h | 19 +++- src/include/sequence/sequence.h | 72 +++++++++++++ src/parser/create_statement.cpp | 8 +- src/parser/postgresparser.cpp | 145 ++++++++++++++++++++++++++ src/planner/create_plan.cpp | 58 +++++++---- src/sequence/sequence.cpp | 43 ++++++++ 13 files changed, 372 insertions(+), 27 deletions(-) create mode 100644 sequence_test.sql create mode 100644 src/include/sequence/sequence.h create mode 100644 src/sequence/sequence.cpp diff --git a/sequence_test.sql b/sequence_test.sql new file mode 100644 index 00000000000..7f43710c01b --- /dev/null +++ b/sequence_test.sql @@ -0,0 +1,4 @@ +-- psql "sslmode=disable" -U postgres -h localhost -p 15721 +\c test; +-- currently not support AS, CACHE and OWNED BY. +CREATE SEQUENCE seq INCREMENT BY 2 MINVALUE 10 MAXVALUE 50 START 10 CYCLE; diff --git a/src/common/internal_types.cpp b/src/common/internal_types.cpp index b409a02195b..9db9954d689 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"; + } default: { throw ConversionException( StringUtil::Format("No string conversion for CreateType value '%d'", @@ -674,6 +677,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 7c90834f152..90ea47eff72 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -71,6 +71,13 @@ bool CreateExecutor::DExecute() { break; } + // if query was for creating sequence + case CreateType::SEQUENCE: { + LOG_DEBUG("in create executor: CreateType::SEQUENCE"); + throw NotImplementedException(StringUtil::Format("Sequence not implemented!")); + break; + } + default: { std::string create_type = CreateTypeToString(node.GetCreateType()); LOG_ERROR("Not supported create type %s", create_type.c_str()); diff --git a/src/include/common/internal_types.h b/src/include/common/internal_types.h index badc2738ac8..bb69307a40c 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -609,7 +609,8 @@ enum class CreateType { TABLE = 2, // table create type INDEX = 3, // index create type CONSTRAINT = 4, // constraint create type - TRIGGER = 5 // trigger create type + TRIGGER = 5, // trigger create type + SEQUENCE = 6 }; std::string CreateTypeToString(CreateType type); CreateType StringToCreateType(const std::string &str); @@ -701,7 +702,8 @@ enum class QueryType { QUERY_INVALID = 20, QUERY_CREATE_TRIGGER = 21, QUERY_CREATE_SCHEMA = 22, - QUERY_CREATE_VIEW = 23 + QUERY_CREATE_VIEW = 23, + QUERY_CREATE_SEQUENCE = 24 }; std::string QueryTypeToString(QueryType query_type); QueryType StringToQueryType(std::string str); @@ -1412,4 +1414,4 @@ enum class SSLLevel { SSL_VERIIFY = 2, }; -} // namespace peloton \ No newline at end of file +} // namespace peloton diff --git a/src/include/parser/create_statement.h b/src/include/parser/create_statement.h index 1abf45fa968..81945a5f646 100644 --- a/src/include/parser/create_statement.h +++ b/src/include/parser/create_statement.h @@ -215,7 +215,7 @@ 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), @@ -254,6 +254,16 @@ 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; + std::unique_ptr table; // deal with RangeVar + 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, probably won't be supported in this project + bool seq_cycle; }; } // namespace parser diff --git a/src/include/parser/parsenodes.h b/src/include/parser/parsenodes.h index 691879afebe..ebdacb4122c 100644 --- a/src/include/parser/parsenodes.h +++ b/src/include/parser/parsenodes.h @@ -717,6 +717,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 0a59e5704ad..0b733874ca9 100644 --- a/src/include/parser/postgresparser.h +++ b/src/include/parser/postgresparser.h @@ -203,6 +203,8 @@ 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); @@ -286,6 +288,11 @@ class PostgresParser { // transform helper for subquery expressions static expression::AbstractExpression *SubqueryExprTransform(SubLink *node); + static void parse_sequence_params(List* options, parser::CreateStatement* result); + + static int64_t get_long_in_defel(DefElem* defel){ + return (int64_t) ((reinterpret_cast(defel->arg))->val.ival); + }; }; } // namespace parser diff --git a/src/include/planner/create_plan.h b/src/include/planner/create_plan.h index e0e9f84add8..e784017d0ec 100644 --- a/src/include/planner/create_plan.h +++ b/src/include/planner/create_plan.h @@ -50,7 +50,7 @@ struct ForeignKeyInfo { class CreatePlan : public AbstractPlan { public: CreatePlan() = delete; - + // This construnctor is for Create Database Test used only explicit CreatePlan(std::string database_name, CreateType c_type); @@ -108,6 +108,14 @@ 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; } + protected: // This is a helper method for extracting foreign key information // and storing it in an internal struct. @@ -150,6 +158,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/sequence/sequence.h b/src/include/sequence/sequence.h new file mode 100644 index 00000000000..83591250a3a --- /dev/null +++ b/src/include/sequence/sequence.h @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence.h +// +// Identification: src/include/sequence/sequence.h +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "common/logger.h" +#include "planner/create_plan.h" +#include "storage/tuple.h" +#include "common/internal_types.h" + +namespace peloton { + +namespace concurrency { +class TransactionContext; +} + +namespace sequence { + +class Sequence; + +class SequenceData { + public: + int64 last_value; + int64 log_cnt; + bool is_called; +}; + +class Sequence { + public: + Sequence(const planner::CreatePlan &plan); + + Sequence(const std::string &name, + const int64 seqstart, const int64 seqincrement, + const int64 seqmax, const int64 seqmin, + const int64 seqcache, const bool seqcycle): + seq_name(name), + seqstart(seqstart), + seqincrement(seqincrement), + seqmax(seqmax), + seqmin(seqmin), + seqcache(seqcache), + seqcycle(seqcycle) + { + curr_val = seqstart; + } + + std::string seq_name; + int64 seqstart; // Start value of the sequence + int64 seqincrement; // Increment value of the sequence + int64 seqmax; // Maximum value of the sequence + int64 seqmin; // Minimum value of the sequence + int64 seqcache; // Cache size of the sequence + bool seqcycle; // Whether the sequence cycles + + int64 GetNextVal(); + + private: + int64 curr_val; +}; + + +} // namespace sequence +} // namespace peloton diff --git a/src/parser/create_statement.cpp b/src/parser/create_statement.cpp index dd52ee70433..7547f704f0a 100644 --- a/src/parser/create_statement.cpp +++ b/src/parser/create_statement.cpp @@ -70,6 +70,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; @@ -98,7 +104,7 @@ const std::string CreateStatement::GetInfo(int num_indent) const { << col->not_null << " primary : " << col->primary << " unique " << col->unique << " varlen " << col->varlen; } - os << std::endl; + os << std::endl; } } std::string info = os.str(); diff --git a/src/parser/postgresparser.cpp b/src/parser/postgresparser.cpp index 49474b2a942..c5267476ddc 100644 --- a/src/parser/postgresparser.cpp +++ b/src/parser/postgresparser.cpp @@ -1338,6 +1338,148 @@ parser::SQLStatement *PostgresParser::CreateViewTransform(ViewStmt *root) { return result; } +parser::SQLStatement *PostgresParser::CreateSequenceTransform(CreateSeqStmt *root){ + LOG_DEBUG("In create sequence transform"); + parser::CreateStatement *result = + new parser::CreateStatement(CreateStatement::kSequence); + result->sequence_name = std::string(root->sequence->relname); + LOG_DEBUG("New Sequence Name:%s\n", result->sequence_name.c_str()); + result->table.reset( + RangeVarTransform(reinterpret_cast(root->sequence))); + LOG_DEBUG("Before parse sequences"); + parse_sequence_params(root->options, result); + return result; +} + +void PostgresParser::parse_sequence_params(List* options, parser::CreateStatement* result){ + // DefElem *as_type = NULL; + DefElem *start_value = NULL; + // DefElem *restart_value = NULL; + DefElem *increment_by = NULL; + DefElem *max_value = NULL; + DefElem *min_value = NULL; + DefElem *cache_value = NULL; + DefElem *is_cycled = NULL; + // bool reset_max_value = false; + // bool reset_min_value = false; + if(!options) return; + + ListCell *option; + for (option = options->head; option != NULL; option = lnext(option)) + { + DefElem *defel = (DefElem *) lfirst(option); + + // if (strcmp(defel->defname, "as") == 0) + // { + // // if (as_type) + // // ereport(ERROR, + // // (errcode(ERRCODE_SYNTAX_ERROR), + // // errmsg("conflicting or redundant options"), + // // parser_errposition(pstate, defel->location))); + // as_type = defel; + // } + // else if (strcmp(defel->defname, "increment") == 0) + if (strcmp(defel->defname, "increment") == 0) + { + // if (increment_by) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + increment_by = defel; + result->seq_increment = get_long_in_defel(increment_by); + } + else if (strcmp(defel->defname, "start") == 0) + { + // if (start_value) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + start_value = defel; + result->seq_start = get_long_in_defel(start_value); + } + // else if (strcmp(defel->defname, "restart") == 0) + // { + // // if (restart_value) + // // ereport(ERROR, + // // (errcode(ERRCODE_SYNTAX_ERROR), + // // errmsg("conflicting or redundant options"), + // // parser_errposition(pstate, defel->location))); + // restart_value = defel; + // } + else if (strcmp(defel->defname, "maxvalue") == 0) + { + // if (max_value) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + max_value = defel; + result->seq_max_value = get_long_in_defel(max_value); + } + else if (strcmp(defel->defname, "minvalue") == 0) + { + // if (min_value) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + min_value = defel; + result->seq_min_value = get_long_in_defel(min_value); + } + else if (strcmp(defel->defname, "cache") == 0) + { + // if (cache_value) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + cache_value = defel; + result->seq_cache = get_long_in_defel(cache_value); + } + else if (strcmp(defel->defname, "cycle") == 0) + { + // if (is_cycled) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + is_cycled = defel; + result->seq_cycle = (bool) get_long_in_defel(is_cycled); + } + // TODO: support owned_by + // else if (strcmp(defel->defname, "owned_by") == 0) + // { + // // if (*owned_by) + // // ereport(ERROR, + // // (errcode(ERRCODE_SYNTAX_ERROR), + // // errmsg("conflicting or redundant options"), + // // parser_errposition(pstate, defel->location))); + // *owned_by = defGetQualifiedName(defel); + // } + // else if (strcmp(defel->defname, "sequence_name") == 0) + // { + /* + * The parser allows this, but it is only for identity columns, in + * which case it is filtered out in parse_utilcmd.c. We only get + * here if someone puts it into a CREATE SEQUENCE. + */ + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("invalid sequence option SEQUENCE NAME"), + // parser_errposition(pstate, defel->location))); + // } + else + // elog(ERROR, "option \"%s\" not recognized", + // defel->defname); + throw ParserException(StringUtil::Format( + "option \"%s\" not recognized\n", defel->defname)); + } + + //TODO: support type in sequence +} + parser::DropStatement *PostgresParser::DropTransform(DropStmt *root) { switch (root->removeType) { case ObjectType::OBJECT_TABLE: @@ -1748,6 +1890,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; diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index b19d8d534d8..20cf93d306e 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -56,37 +56,37 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) for (auto &col : parse_tree->columns) { type::TypeId val = col->GetValueType(col->type); - + LOG_TRACE("Column name: %s.%s; Is primary key: %d", table_name.c_str(), col->name.c_str(), col->primary); - + // Check main constraints if (col->primary) { catalog::Constraint constraint(ConstraintType::PRIMARY, "con_primary"); column_constraints.push_back(constraint); LOG_TRACE("Added a primary key constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); } - + if (col->not_null) { catalog::Constraint constraint(ConstraintType::NOTNULL, "con_not_null"); column_constraints.push_back(constraint); LOG_TRACE("Added a not-null constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); } - + if (col->unique) { catalog::Constraint constraint(ConstraintType::UNIQUE, "con_unique"); column_constraints.push_back(constraint); LOG_TRACE("Added a unique constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); } - + /* **************** */ - + // Add the default value if (col->default_value != nullptr) { // Referenced from insert_plan.cpp if (col->default_value->GetExpressionType() != ExpressionType::VALUE_PARAMETER) { expression::ConstantValueExpression *const_expr_elem = dynamic_cast(col->default_value.get()); - + catalog::Constraint constraint(ConstraintType::DEFAULT, "con_default"); type::Value v = const_expr_elem->GetValue(); constraint.addDefaultValue(v); @@ -95,17 +95,17 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) v.ToString().c_str(), table_name.c_str(), col->name.c_str()); } } - + // Check expression constraint // Currently only supports simple boolean forms like (a > 0) if (col->check_expression != nullptr) { // TODO: more expression types need to be supported if (col->check_expression->GetValueType() == type::TypeId::BOOLEAN) { catalog::Constraint constraint(ConstraintType::CHECK, "con_check"); - + const expression::ConstantValueExpression *const_expr_elem = dynamic_cast(col->check_expression->GetChild(1)); - + type::Value tmp_value = const_expr_elem->GetValue(); constraint.AddCheck(std::move(col->check_expression->GetExpressionType()), std::move(tmp_value)); column_constraints.push_back(constraint); @@ -113,17 +113,17 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) table_name.c_str(), col->name.c_str()); } } - + auto column = catalog::Column(val, type::Type::GetTypeSize(val), std::string(col->name), false); if (!column.IsInlined()) { column.SetLength(col->varlen); } - + for (auto con : column_constraints) { column.AddConstraint(con); } - + column_constraints.clear(); columns.push_back(column); } @@ -141,17 +141,17 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) // This is a fix for a bug where // The vector* items gets deleted when passed // To the Executor. - + std::vector index_attrs_holder; - + for (auto &attr : parse_tree->index_attrs) { index_attrs_holder.push_back(attr); } - + index_attrs = index_attrs_holder; - + index_type = parse_tree->index_type; - + unique = parse_tree->unique; break; } @@ -160,14 +160,14 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) trigger_name = std::string(parse_tree->trigger_name); table_name = std::string(parse_tree->GetTableName()); database_name = std::string(parse_tree->GetDatabaseName()); - + if (parse_tree->trigger_when) { trigger_when.reset(parse_tree->trigger_when->Copy()); } else { trigger_when.reset(); } trigger_type = parse_tree->trigger_type; - + for (auto &s : parse_tree->trigger_funcname) { trigger_funcname.push_back(s); } @@ -180,12 +180,28 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) break; } + case parser::CreateStatement::CreateType::kSequence: { + LOG_DEBUG("CreatePlan: Create Sequence"); + create_type = CreateType::SEQUENCE; + table_name = parse_tree->table->table_info_->table_name; + database_name = parse_tree->table->table_info_->database_name; + + 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_cache = parse_tree->seq_cache; + seq_cycle = parse_tree->seq_cycle; + + break; + } default: LOG_ERROR("UNKNOWN CREATE TYPE"); //TODO Should we handle this here? break; } - + // TODO check type CreateType::kDatabase } diff --git a/src/sequence/sequence.cpp b/src/sequence/sequence.cpp new file mode 100644 index 00000000000..de7e2da050a --- /dev/null +++ b/src/sequence/sequence.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence.cpp +// +// Identification: src/sequence/sequence.cpp +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "common/logger.h" +#include "planner/create_plan.h" +#include "storage/tuple.h" +#include "common/internal_types.h" + +namespace peloton { +namespace sequence { + +class Sequence { + Sequence(const planner::CreatePlan &plan){ + seq_name = plan.GetSequenceName(); + seqstart = plan.GetSequenceStart(); // Start value of the sequence + seqincrement = plan.GetSequenceIncrement(); // Increment value of the sequence + seqmax = plan.GetSequenceMaxValue(); // Maximum value of the sequence + seqmin = plan.GetSequenceMinValue(); // Minimum value of the sequence + seqcache = plan.GetSequenceCacheSize(); // Cache size of the sequence + seqcycle = plan.GetSequenceCycle(); // Whether the sequence cycles + + curr_val = seq_start; + } + + int64 GetNextVal(){ + return 0; + } +}; + + +} // namespace sequence +} // namespace peloton From 086b49382bab0159be92ed7ec28256ba03727796 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Thu, 22 Mar 2018 16:07:15 -0400 Subject: [PATCH 02/29] finish part of parser; need to add handler function in create_executor.cpp --- sequence_test.sql | 4 + src/common/internal_types.cpp | 6 ++ src/executor/create_executor.cpp | 7 ++ src/include/common/internal_types.h | 8 +- src/include/parser/create_statement.h | 12 ++- src/include/parser/parsenodes.h | 10 ++ src/include/parser/postgresparser.h | 7 ++ src/include/planner/create_plan.h | 19 +++- src/include/sequence/sequence.h | 72 +++++++++++++ src/parser/create_statement.cpp | 8 +- src/parser/postgresparser.cpp | 145 ++++++++++++++++++++++++++ src/planner/create_plan.cpp | 58 +++++++---- src/sequence/sequence.cpp | 43 ++++++++ 13 files changed, 372 insertions(+), 27 deletions(-) create mode 100644 sequence_test.sql create mode 100644 src/include/sequence/sequence.h create mode 100644 src/sequence/sequence.cpp diff --git a/sequence_test.sql b/sequence_test.sql new file mode 100644 index 00000000000..7f43710c01b --- /dev/null +++ b/sequence_test.sql @@ -0,0 +1,4 @@ +-- psql "sslmode=disable" -U postgres -h localhost -p 15721 +\c test; +-- currently not support AS, CACHE and OWNED BY. +CREATE SEQUENCE seq INCREMENT BY 2 MINVALUE 10 MAXVALUE 50 START 10 CYCLE; diff --git a/src/common/internal_types.cpp b/src/common/internal_types.cpp index b409a02195b..9db9954d689 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"; + } default: { throw ConversionException( StringUtil::Format("No string conversion for CreateType value '%d'", @@ -674,6 +677,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 7c90834f152..90ea47eff72 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -71,6 +71,13 @@ bool CreateExecutor::DExecute() { break; } + // if query was for creating sequence + case CreateType::SEQUENCE: { + LOG_DEBUG("in create executor: CreateType::SEQUENCE"); + throw NotImplementedException(StringUtil::Format("Sequence not implemented!")); + break; + } + default: { std::string create_type = CreateTypeToString(node.GetCreateType()); LOG_ERROR("Not supported create type %s", create_type.c_str()); diff --git a/src/include/common/internal_types.h b/src/include/common/internal_types.h index badc2738ac8..bb69307a40c 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -609,7 +609,8 @@ enum class CreateType { TABLE = 2, // table create type INDEX = 3, // index create type CONSTRAINT = 4, // constraint create type - TRIGGER = 5 // trigger create type + TRIGGER = 5, // trigger create type + SEQUENCE = 6 }; std::string CreateTypeToString(CreateType type); CreateType StringToCreateType(const std::string &str); @@ -701,7 +702,8 @@ enum class QueryType { QUERY_INVALID = 20, QUERY_CREATE_TRIGGER = 21, QUERY_CREATE_SCHEMA = 22, - QUERY_CREATE_VIEW = 23 + QUERY_CREATE_VIEW = 23, + QUERY_CREATE_SEQUENCE = 24 }; std::string QueryTypeToString(QueryType query_type); QueryType StringToQueryType(std::string str); @@ -1412,4 +1414,4 @@ enum class SSLLevel { SSL_VERIIFY = 2, }; -} // namespace peloton \ No newline at end of file +} // namespace peloton diff --git a/src/include/parser/create_statement.h b/src/include/parser/create_statement.h index 1abf45fa968..81945a5f646 100644 --- a/src/include/parser/create_statement.h +++ b/src/include/parser/create_statement.h @@ -215,7 +215,7 @@ 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), @@ -254,6 +254,16 @@ 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; + std::unique_ptr table; // deal with RangeVar + 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, probably won't be supported in this project + bool seq_cycle; }; } // namespace parser diff --git a/src/include/parser/parsenodes.h b/src/include/parser/parsenodes.h index 691879afebe..ebdacb4122c 100644 --- a/src/include/parser/parsenodes.h +++ b/src/include/parser/parsenodes.h @@ -717,6 +717,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 0a59e5704ad..0b733874ca9 100644 --- a/src/include/parser/postgresparser.h +++ b/src/include/parser/postgresparser.h @@ -203,6 +203,8 @@ 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); @@ -286,6 +288,11 @@ class PostgresParser { // transform helper for subquery expressions static expression::AbstractExpression *SubqueryExprTransform(SubLink *node); + static void parse_sequence_params(List* options, parser::CreateStatement* result); + + static int64_t get_long_in_defel(DefElem* defel){ + return (int64_t) ((reinterpret_cast(defel->arg))->val.ival); + }; }; } // namespace parser diff --git a/src/include/planner/create_plan.h b/src/include/planner/create_plan.h index e0e9f84add8..e784017d0ec 100644 --- a/src/include/planner/create_plan.h +++ b/src/include/planner/create_plan.h @@ -50,7 +50,7 @@ struct ForeignKeyInfo { class CreatePlan : public AbstractPlan { public: CreatePlan() = delete; - + // This construnctor is for Create Database Test used only explicit CreatePlan(std::string database_name, CreateType c_type); @@ -108,6 +108,14 @@ 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; } + protected: // This is a helper method for extracting foreign key information // and storing it in an internal struct. @@ -150,6 +158,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/sequence/sequence.h b/src/include/sequence/sequence.h new file mode 100644 index 00000000000..83591250a3a --- /dev/null +++ b/src/include/sequence/sequence.h @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence.h +// +// Identification: src/include/sequence/sequence.h +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "common/logger.h" +#include "planner/create_plan.h" +#include "storage/tuple.h" +#include "common/internal_types.h" + +namespace peloton { + +namespace concurrency { +class TransactionContext; +} + +namespace sequence { + +class Sequence; + +class SequenceData { + public: + int64 last_value; + int64 log_cnt; + bool is_called; +}; + +class Sequence { + public: + Sequence(const planner::CreatePlan &plan); + + Sequence(const std::string &name, + const int64 seqstart, const int64 seqincrement, + const int64 seqmax, const int64 seqmin, + const int64 seqcache, const bool seqcycle): + seq_name(name), + seqstart(seqstart), + seqincrement(seqincrement), + seqmax(seqmax), + seqmin(seqmin), + seqcache(seqcache), + seqcycle(seqcycle) + { + curr_val = seqstart; + } + + std::string seq_name; + int64 seqstart; // Start value of the sequence + int64 seqincrement; // Increment value of the sequence + int64 seqmax; // Maximum value of the sequence + int64 seqmin; // Minimum value of the sequence + int64 seqcache; // Cache size of the sequence + bool seqcycle; // Whether the sequence cycles + + int64 GetNextVal(); + + private: + int64 curr_val; +}; + + +} // namespace sequence +} // namespace peloton diff --git a/src/parser/create_statement.cpp b/src/parser/create_statement.cpp index dd52ee70433..7547f704f0a 100644 --- a/src/parser/create_statement.cpp +++ b/src/parser/create_statement.cpp @@ -70,6 +70,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; @@ -98,7 +104,7 @@ const std::string CreateStatement::GetInfo(int num_indent) const { << col->not_null << " primary : " << col->primary << " unique " << col->unique << " varlen " << col->varlen; } - os << std::endl; + os << std::endl; } } std::string info = os.str(); diff --git a/src/parser/postgresparser.cpp b/src/parser/postgresparser.cpp index 49474b2a942..c5267476ddc 100644 --- a/src/parser/postgresparser.cpp +++ b/src/parser/postgresparser.cpp @@ -1338,6 +1338,148 @@ parser::SQLStatement *PostgresParser::CreateViewTransform(ViewStmt *root) { return result; } +parser::SQLStatement *PostgresParser::CreateSequenceTransform(CreateSeqStmt *root){ + LOG_DEBUG("In create sequence transform"); + parser::CreateStatement *result = + new parser::CreateStatement(CreateStatement::kSequence); + result->sequence_name = std::string(root->sequence->relname); + LOG_DEBUG("New Sequence Name:%s\n", result->sequence_name.c_str()); + result->table.reset( + RangeVarTransform(reinterpret_cast(root->sequence))); + LOG_DEBUG("Before parse sequences"); + parse_sequence_params(root->options, result); + return result; +} + +void PostgresParser::parse_sequence_params(List* options, parser::CreateStatement* result){ + // DefElem *as_type = NULL; + DefElem *start_value = NULL; + // DefElem *restart_value = NULL; + DefElem *increment_by = NULL; + DefElem *max_value = NULL; + DefElem *min_value = NULL; + DefElem *cache_value = NULL; + DefElem *is_cycled = NULL; + // bool reset_max_value = false; + // bool reset_min_value = false; + if(!options) return; + + ListCell *option; + for (option = options->head; option != NULL; option = lnext(option)) + { + DefElem *defel = (DefElem *) lfirst(option); + + // if (strcmp(defel->defname, "as") == 0) + // { + // // if (as_type) + // // ereport(ERROR, + // // (errcode(ERRCODE_SYNTAX_ERROR), + // // errmsg("conflicting or redundant options"), + // // parser_errposition(pstate, defel->location))); + // as_type = defel; + // } + // else if (strcmp(defel->defname, "increment") == 0) + if (strcmp(defel->defname, "increment") == 0) + { + // if (increment_by) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + increment_by = defel; + result->seq_increment = get_long_in_defel(increment_by); + } + else if (strcmp(defel->defname, "start") == 0) + { + // if (start_value) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + start_value = defel; + result->seq_start = get_long_in_defel(start_value); + } + // else if (strcmp(defel->defname, "restart") == 0) + // { + // // if (restart_value) + // // ereport(ERROR, + // // (errcode(ERRCODE_SYNTAX_ERROR), + // // errmsg("conflicting or redundant options"), + // // parser_errposition(pstate, defel->location))); + // restart_value = defel; + // } + else if (strcmp(defel->defname, "maxvalue") == 0) + { + // if (max_value) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + max_value = defel; + result->seq_max_value = get_long_in_defel(max_value); + } + else if (strcmp(defel->defname, "minvalue") == 0) + { + // if (min_value) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + min_value = defel; + result->seq_min_value = get_long_in_defel(min_value); + } + else if (strcmp(defel->defname, "cache") == 0) + { + // if (cache_value) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + cache_value = defel; + result->seq_cache = get_long_in_defel(cache_value); + } + else if (strcmp(defel->defname, "cycle") == 0) + { + // if (is_cycled) + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("conflicting or redundant options"), + // parser_errposition(pstate, defel->location))); + is_cycled = defel; + result->seq_cycle = (bool) get_long_in_defel(is_cycled); + } + // TODO: support owned_by + // else if (strcmp(defel->defname, "owned_by") == 0) + // { + // // if (*owned_by) + // // ereport(ERROR, + // // (errcode(ERRCODE_SYNTAX_ERROR), + // // errmsg("conflicting or redundant options"), + // // parser_errposition(pstate, defel->location))); + // *owned_by = defGetQualifiedName(defel); + // } + // else if (strcmp(defel->defname, "sequence_name") == 0) + // { + /* + * The parser allows this, but it is only for identity columns, in + * which case it is filtered out in parse_utilcmd.c. We only get + * here if someone puts it into a CREATE SEQUENCE. + */ + // ereport(ERROR, + // (errcode(ERRCODE_SYNTAX_ERROR), + // errmsg("invalid sequence option SEQUENCE NAME"), + // parser_errposition(pstate, defel->location))); + // } + else + // elog(ERROR, "option \"%s\" not recognized", + // defel->defname); + throw ParserException(StringUtil::Format( + "option \"%s\" not recognized\n", defel->defname)); + } + + //TODO: support type in sequence +} + parser::DropStatement *PostgresParser::DropTransform(DropStmt *root) { switch (root->removeType) { case ObjectType::OBJECT_TABLE: @@ -1748,6 +1890,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; diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index b19d8d534d8..20cf93d306e 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -56,37 +56,37 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) for (auto &col : parse_tree->columns) { type::TypeId val = col->GetValueType(col->type); - + LOG_TRACE("Column name: %s.%s; Is primary key: %d", table_name.c_str(), col->name.c_str(), col->primary); - + // Check main constraints if (col->primary) { catalog::Constraint constraint(ConstraintType::PRIMARY, "con_primary"); column_constraints.push_back(constraint); LOG_TRACE("Added a primary key constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); } - + if (col->not_null) { catalog::Constraint constraint(ConstraintType::NOTNULL, "con_not_null"); column_constraints.push_back(constraint); LOG_TRACE("Added a not-null constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); } - + if (col->unique) { catalog::Constraint constraint(ConstraintType::UNIQUE, "con_unique"); column_constraints.push_back(constraint); LOG_TRACE("Added a unique constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); } - + /* **************** */ - + // Add the default value if (col->default_value != nullptr) { // Referenced from insert_plan.cpp if (col->default_value->GetExpressionType() != ExpressionType::VALUE_PARAMETER) { expression::ConstantValueExpression *const_expr_elem = dynamic_cast(col->default_value.get()); - + catalog::Constraint constraint(ConstraintType::DEFAULT, "con_default"); type::Value v = const_expr_elem->GetValue(); constraint.addDefaultValue(v); @@ -95,17 +95,17 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) v.ToString().c_str(), table_name.c_str(), col->name.c_str()); } } - + // Check expression constraint // Currently only supports simple boolean forms like (a > 0) if (col->check_expression != nullptr) { // TODO: more expression types need to be supported if (col->check_expression->GetValueType() == type::TypeId::BOOLEAN) { catalog::Constraint constraint(ConstraintType::CHECK, "con_check"); - + const expression::ConstantValueExpression *const_expr_elem = dynamic_cast(col->check_expression->GetChild(1)); - + type::Value tmp_value = const_expr_elem->GetValue(); constraint.AddCheck(std::move(col->check_expression->GetExpressionType()), std::move(tmp_value)); column_constraints.push_back(constraint); @@ -113,17 +113,17 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) table_name.c_str(), col->name.c_str()); } } - + auto column = catalog::Column(val, type::Type::GetTypeSize(val), std::string(col->name), false); if (!column.IsInlined()) { column.SetLength(col->varlen); } - + for (auto con : column_constraints) { column.AddConstraint(con); } - + column_constraints.clear(); columns.push_back(column); } @@ -141,17 +141,17 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) // This is a fix for a bug where // The vector* items gets deleted when passed // To the Executor. - + std::vector index_attrs_holder; - + for (auto &attr : parse_tree->index_attrs) { index_attrs_holder.push_back(attr); } - + index_attrs = index_attrs_holder; - + index_type = parse_tree->index_type; - + unique = parse_tree->unique; break; } @@ -160,14 +160,14 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) trigger_name = std::string(parse_tree->trigger_name); table_name = std::string(parse_tree->GetTableName()); database_name = std::string(parse_tree->GetDatabaseName()); - + if (parse_tree->trigger_when) { trigger_when.reset(parse_tree->trigger_when->Copy()); } else { trigger_when.reset(); } trigger_type = parse_tree->trigger_type; - + for (auto &s : parse_tree->trigger_funcname) { trigger_funcname.push_back(s); } @@ -180,12 +180,28 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) break; } + case parser::CreateStatement::CreateType::kSequence: { + LOG_DEBUG("CreatePlan: Create Sequence"); + create_type = CreateType::SEQUENCE; + table_name = parse_tree->table->table_info_->table_name; + database_name = parse_tree->table->table_info_->database_name; + + 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_cache = parse_tree->seq_cache; + seq_cycle = parse_tree->seq_cycle; + + break; + } default: LOG_ERROR("UNKNOWN CREATE TYPE"); //TODO Should we handle this here? break; } - + // TODO check type CreateType::kDatabase } diff --git a/src/sequence/sequence.cpp b/src/sequence/sequence.cpp new file mode 100644 index 00000000000..de7e2da050a --- /dev/null +++ b/src/sequence/sequence.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence.cpp +// +// Identification: src/sequence/sequence.cpp +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "common/logger.h" +#include "planner/create_plan.h" +#include "storage/tuple.h" +#include "common/internal_types.h" + +namespace peloton { +namespace sequence { + +class Sequence { + Sequence(const planner::CreatePlan &plan){ + seq_name = plan.GetSequenceName(); + seqstart = plan.GetSequenceStart(); // Start value of the sequence + seqincrement = plan.GetSequenceIncrement(); // Increment value of the sequence + seqmax = plan.GetSequenceMaxValue(); // Maximum value of the sequence + seqmin = plan.GetSequenceMinValue(); // Minimum value of the sequence + seqcache = plan.GetSequenceCacheSize(); // Cache size of the sequence + seqcycle = plan.GetSequenceCycle(); // Whether the sequence cycles + + curr_val = seq_start; + } + + int64 GetNextVal(){ + return 0; + } +}; + + +} // namespace sequence +} // namespace peloton From 28b702ecf3507bc0081c2322b9efa30517bac502 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Tue, 27 Mar 2018 20:35:36 -0400 Subject: [PATCH 03/29] add postgresql parser test for sequences --- src/include/sequence/sequence.h | 30 ++++++++-------------- src/sequence/sequence.cpp | 13 +++------- test/parser/postgresparser_test.cpp | 40 +++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/src/include/sequence/sequence.h b/src/include/sequence/sequence.h index 83591250a3a..fd70f6d72e3 100644 --- a/src/include/sequence/sequence.h +++ b/src/include/sequence/sequence.h @@ -24,24 +24,14 @@ class TransactionContext; } namespace sequence { - -class Sequence; - -class SequenceData { - public: - int64 last_value; - int64 log_cnt; - bool is_called; -}; - class Sequence { public: Sequence(const planner::CreatePlan &plan); Sequence(const std::string &name, - const int64 seqstart, const int64 seqincrement, - const int64 seqmax, const int64 seqmin, - const int64 seqcache, const bool seqcycle): + const int64_t seqstart, const int64_t seqincrement, + const int64_t seqmax, const int64_t seqmin, + const int64_t seqcache, const bool seqcycle): seq_name(name), seqstart(seqstart), seqincrement(seqincrement), @@ -54,17 +44,17 @@ class Sequence { } std::string seq_name; - int64 seqstart; // Start value of the sequence - int64 seqincrement; // Increment value of the sequence - int64 seqmax; // Maximum value of the sequence - int64 seqmin; // Minimum value of the sequence - int64 seqcache; // Cache size of the sequence + int64_t seqstart; // Start value of the sequence + int64_t seqincrement; // Increment value of the sequence + int64_t seqmax; // Maximum value of the sequence + int64_t seqmin; // Minimum value of the sequence + int64_t seqcache; // Cache size of the sequence bool seqcycle; // Whether the sequence cycles - int64 GetNextVal(); + int64_t GetNextVal(); private: - int64 curr_val; + int64_t curr_val; }; diff --git a/src/sequence/sequence.cpp b/src/sequence/sequence.cpp index de7e2da050a..472c5c36bfb 100644 --- a/src/sequence/sequence.cpp +++ b/src/sequence/sequence.cpp @@ -10,18 +10,15 @@ // //===----------------------------------------------------------------------===// -#pragma once - #include "common/logger.h" #include "planner/create_plan.h" #include "storage/tuple.h" #include "common/internal_types.h" +#include "sequence/sequence.h" namespace peloton { namespace sequence { - -class Sequence { - Sequence(const planner::CreatePlan &plan){ + Sequence::Sequence(const planner::CreatePlan &plan) { seq_name = plan.GetSequenceName(); seqstart = plan.GetSequenceStart(); // Start value of the sequence seqincrement = plan.GetSequenceIncrement(); // Increment value of the sequence @@ -30,14 +27,12 @@ class Sequence { seqcache = plan.GetSequenceCacheSize(); // Cache size of the sequence seqcycle = plan.GetSequenceCycle(); // Whether the sequence cycles - curr_val = seq_start; + curr_val = seqstart; } - int64 GetNextVal(){ + int64_t GetNextVal(){ return 0; } -}; - } // namespace sequence } // namespace peloton diff --git a/test/parser/postgresparser_test.cpp b/test/parser/postgresparser_test.cpp index f36780bc9a3..f75250c11c3 100644 --- a/test/parser/postgresparser_test.cpp +++ b/test/parser/postgresparser_test.cpp @@ -1068,6 +1068,46 @@ 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); + 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::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, FuncCallTest) { std::string query = "SELECT add(1,a), chr(99) FROM TEST WHERE FUN(b) > 2"; From ddb3dd7f0f12f593f2c488eaadd868a08c276d59 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Tue, 27 Mar 2018 21:18:23 -0400 Subject: [PATCH 04/29] remove AS in sequencce --- src/parser/postgresparser.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/parser/postgresparser.cpp b/src/parser/postgresparser.cpp index c5267476ddc..dddb43ee19c 100644 --- a/src/parser/postgresparser.cpp +++ b/src/parser/postgresparser.cpp @@ -1352,7 +1352,6 @@ parser::SQLStatement *PostgresParser::CreateSequenceTransform(CreateSeqStmt *roo } void PostgresParser::parse_sequence_params(List* options, parser::CreateStatement* result){ - // DefElem *as_type = NULL; DefElem *start_value = NULL; // DefElem *restart_value = NULL; DefElem *increment_by = NULL; @@ -1369,16 +1368,6 @@ void PostgresParser::parse_sequence_params(List* options, parser::CreateStatemen { DefElem *defel = (DefElem *) lfirst(option); - // if (strcmp(defel->defname, "as") == 0) - // { - // // if (as_type) - // // ereport(ERROR, - // // (errcode(ERRCODE_SYNTAX_ERROR), - // // errmsg("conflicting or redundant options"), - // // parser_errposition(pstate, defel->location))); - // as_type = defel; - // } - // else if (strcmp(defel->defname, "increment") == 0) if (strcmp(defel->defname, "increment") == 0) { // if (increment_by) From 26230e3e002a1aff4886771a30dbc93271139aa3 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Tue, 27 Mar 2018 22:43:19 -0400 Subject: [PATCH 05/29] add exception for redefined parser --- src/parser/postgresparser.cpp | 44 ++++++++++------------------------- 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/src/parser/postgresparser.cpp b/src/parser/postgresparser.cpp index dddb43ee19c..598fb98ad98 100644 --- a/src/parser/postgresparser.cpp +++ b/src/parser/postgresparser.cpp @@ -1370,21 +1370,15 @@ void PostgresParser::parse_sequence_params(List* options, parser::CreateStatemen if (strcmp(defel->defname, "increment") == 0) { - // if (increment_by) - // ereport(ERROR, - // (errcode(ERRCODE_SYNTAX_ERROR), - // errmsg("conflicting or redundant options"), - // parser_errposition(pstate, defel->location))); + if (increment_by) + throw ParserException("Redundant definition of increment in defining sequence"); increment_by = defel; result->seq_increment = get_long_in_defel(increment_by); } else if (strcmp(defel->defname, "start") == 0) { - // if (start_value) - // ereport(ERROR, - // (errcode(ERRCODE_SYNTAX_ERROR), - // errmsg("conflicting or redundant options"), - // parser_errposition(pstate, defel->location))); + if (start_value) + throw ParserException("Redundant definition of start in defining sequence"); start_value = defel; result->seq_start = get_long_in_defel(start_value); } @@ -1399,41 +1393,29 @@ void PostgresParser::parse_sequence_params(List* options, parser::CreateStatemen // } else if (strcmp(defel->defname, "maxvalue") == 0) { - // if (max_value) - // ereport(ERROR, - // (errcode(ERRCODE_SYNTAX_ERROR), - // errmsg("conflicting or redundant options"), - // parser_errposition(pstate, defel->location))); + if (max_value) + throw ParserException("Redundant definition of max in defining sequence"); max_value = defel; result->seq_max_value = get_long_in_defel(max_value); } else if (strcmp(defel->defname, "minvalue") == 0) { - // if (min_value) - // ereport(ERROR, - // (errcode(ERRCODE_SYNTAX_ERROR), - // errmsg("conflicting or redundant options"), - // parser_errposition(pstate, defel->location))); + if (min_value) + throw ParserException("Redundant definition of min in defining sequence"); min_value = defel; result->seq_min_value = get_long_in_defel(min_value); } else if (strcmp(defel->defname, "cache") == 0) { - // if (cache_value) - // ereport(ERROR, - // (errcode(ERRCODE_SYNTAX_ERROR), - // errmsg("conflicting or redundant options"), - // parser_errposition(pstate, defel->location))); + if (cache_value) + throw ParserException("Redundant definition of cache in defining sequence"); cache_value = defel; result->seq_cache = get_long_in_defel(cache_value); } else if (strcmp(defel->defname, "cycle") == 0) { - // if (is_cycled) - // ereport(ERROR, - // (errcode(ERRCODE_SYNTAX_ERROR), - // errmsg("conflicting or redundant options"), - // parser_errposition(pstate, defel->location))); + if (is_cycled) + throw ParserException("Redundant definition of cycle in defining sequence"); is_cycled = defel; result->seq_cycle = (bool) get_long_in_defel(is_cycled); } @@ -1460,8 +1442,6 @@ void PostgresParser::parse_sequence_params(List* options, parser::CreateStatemen // parser_errposition(pstate, defel->location))); // } else - // elog(ERROR, "option \"%s\" not recognized", - // defel->defname); throw ParserException(StringUtil::Format( "option \"%s\" not recognized\n", defel->defname)); } From b27305609511f06c38d74b4722971f54fc36db8b Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Sat, 31 Mar 2018 16:54:28 -0400 Subject: [PATCH 06/29] finish compiling create sequence --- src/catalog/sequence_catalog.cpp | 200 +++++++++++++++++++++++++ src/executor/create_executor.cpp | 32 +++- src/include/catalog/catalog_defaults.h | 2 + src/include/catalog/sequence_catalog.h | 96 ++++++++++++ src/include/common/exception.h | 13 +- src/include/executor/create_executor.h | 2 + src/include/parser/create_statement.h | 12 +- src/include/sequence/sequence.h | 37 ++--- src/sequence/sequence.cpp | 59 ++++++-- 9 files changed, 413 insertions(+), 40 deletions(-) create mode 100644 src/catalog/sequence_catalog.cpp create mode 100644 src/include/catalog/sequence_catalog.h diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp new file mode 100644 index 00000000000..e0b99415ef4 --- /dev/null +++ b/src/catalog/sequence_catalog.cpp @@ -0,0 +1,200 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// sequence_catalog.h +// +// Identification: src/catalog/sequence_catalog.cpp +// +// Copyright (c) 2015-17, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#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" + +namespace peloton { +namespace catalog { + +SequenceCatalog &SequenceCatalog::GetInstance(concurrency::TransactionContext *txn) { + static SequenceCatalog sequence_catalog{txn}; + return sequence_catalog; +} + +SequenceCatalog::SequenceCatalog(concurrency::TransactionContext *txn) + : AbstractCatalog("CREATE TABLE " CATALOG_DATABASE_NAME + "." SEQUENCE_CATALOG_NAME + " (" + "oid INT NOT NULL PRIMARY KEY, " + "sqdboid INT NOT NULL, " + "sqname VARCHAR NOT NULL, " + "sqinc INT NOT NULL, " + "sqmax INT NOT NULL, " + "sqmin INT NOT NULL, " + "sqstart INT NOT NULL, " + "sqcycle BOOLEAN NOT NULL, " + "sqval INT NOT NULL);", + txn) { + Catalog::GetInstance()->CreateIndex( + CATALOG_DATABASE_NAME, SEQUENCE_CATALOG_NAME, + {ColumnId::DATABSE_OID, ColumnId::SEQUENCE_NAME}, + SEQUENCE_CATALOG_NAME "_skey0", true, IndexType::BWTREE, txn); +} + +SequenceCatalog::~SequenceCatalog() {} + +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){ + 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::GetIntegerValue(seq_increment); + auto val4 = type::ValueFactory::GetIntegerValue(seq_max); + auto val5 = type::ValueFactory::GetIntegerValue(seq_min); + auto val6 = type::ValueFactory::GetIntegerValue(seq_start); + auto val7 = type::ValueFactory::GetBooleanValue(seq_cycle); + // When insert value, seqval = seq_start + auto val8 = type::ValueFactory::GetIntegerValue(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, val7, pool); + + // Insert the tuple + return InsertTuple(std::move(tuple), txn); +} + +ResultType SequenceCatalog::DropSequence(const std::string &database_name, + const std::string &sequence_name, + concurrency::TransactionContext *txn) { + if (txn == nullptr) { + LOG_TRACE("Do not have transaction to drop sequence: %s", + table_name.c_str()); + return ResultType::FAILURE; + } + + auto database_object = + Catalog::GetInstance()->GetDatabaseObject(database_name, txn); + + oid_t sequence_oid = SequenceCatalog::GetInstance().GetSequenceOid( + sequence_name, database_object->GetDatabaseOid(), txn); + if (sequence_oid == INVALID_OID) { + LOG_TRACE("Cannot find sequence %s to drop!", sequence_name.c_str()); + return ResultType::FAILURE; + } + + LOG_INFO("trigger %d will be deleted!", sequence_oid); + + bool delete_success = + DeleteSequenceByName(sequence_name, database_object->GetDatabaseOid(), txn); + if (delete_success) { + // might need to do sth. else after implementing insert + return ResultType::SUCCESS; + } + + LOG_DEBUG("Failed to delete sequence"); + return ResultType::FAILURE; +} + +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); +} + +std::unique_ptr SequenceCatalog::GetSequence( + oid_t database_oid, const std::string &sequence_name, concurrency::TransactionContext *txn){ + std::vector column_ids( + {ColumnId::SEQUENCE_NAME,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); + // carefull! the result tile could be null! + if (result_tiles == nullptr) { + LOG_INFO("no trigger on sequence %d and %s", database_oid, sequence_name.c_str()); + return std::unique_ptr(nullptr); + } else { + LOG_INFO("size of the result tiles = %lu", result_tiles->size()); + } + + PL_ASSERT(result_tiles->size() == 1); + for (unsigned int i = 0; i < result_tiles->size(); i++) { + size_t tuple_count = (*result_tiles)[i]->GetTupleCount(); + for (size_t j = 0; j < tuple_count; j++) { + // create a new trigger instance + std::unique_ptr new_sequence = + std::make_unique( + (*result_tiles)[i]->GetValue(j, 0).ToString(), + (*result_tiles)[i]->GetValue(j, 1).GetAs(), + (*result_tiles)[i]->GetValue(j, 2).GetAs(), + (*result_tiles)[i]->GetValue(j, 3).GetAs(), + (*result_tiles)[i]->GetValue(j, 4).GetAs(), + (*result_tiles)[i]->GetValue(j, 5).GetAs(), + (*result_tiles)[i]->GetValue(j, 6).GetAs()); + + return new_sequence; + } + } + + return std::unique_ptr(nullptr); +} + +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); + // carefull! the result tile could be null! + if (result_tiles == nullptr) { + LOG_INFO("no trigger on sequence %d and %s", database_oid, sequence_name.c_str()); + return INVALID_OID; + } + + PL_ASSERT(result_tiles->size() == 1); + oid_t result; + for (unsigned int i = 0; i < result_tiles->size(); i++) { + result = (*result_tiles)[i]->GetValue(0, 0).GetAs(); + } + + return result; +} + +} // namespace catalog +} // namespace peloton diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index 90ea47eff72..b00c4594225 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -14,6 +14,7 @@ #include "catalog/catalog.h" #include "catalog/foreign_key.h" +#include "catalog/sequence_catalog.h" #include "catalog/trigger_catalog.h" #include "catalog/database_catalog.h" #include "catalog/table_catalog.h" @@ -73,8 +74,7 @@ bool CreateExecutor::DExecute() { // if query was for creating sequence case CreateType::SEQUENCE: { - LOG_DEBUG("in create executor: CreateType::SEQUENCE"); - throw NotImplementedException(StringUtil::Format("Sequence not implemented!")); + result = CreateSequence(node); break; } @@ -94,7 +94,6 @@ bool CreateExecutor::DExecute() { } bool CreateExecutor::CreateDatabase(const planner::CreatePlan &node) { - auto txn = context_->GetTransaction(); auto database_name = node.GetDatabaseName(); ResultType result = catalog::Catalog::GetInstance()->CreateDatabase( @@ -277,6 +276,33 @@ 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 table_name = node.GetTableName(); + std::string sequence_name = node.GetSequenceName(); + + auto database_object = catalog::Catalog::GetInstance()->GetDatabaseObject( + database_name, txn); + + catalog::SequenceCatalog::GetInstance().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_TRACE("Creating sequence succeeded!"); + } else if (txn->GetResult() == ResultType::FAILURE) { + LOG_TRACE("Creating sequence failed!"); + } else { + LOG_TRACE("Result is: %s", + ResultTypeToString(txn->GetResult()).c_str()); + } + + return (true); +} + } // namespace executor } // namespace peloton diff --git a/src/include/catalog/catalog_defaults.h b/src/include/catalog/catalog_defaults.h index 69834ec769a..e5697632bb2 100644 --- a/src/include/catalog/catalog_defaults.h +++ b/src/include/catalog/catalog_defaults.h @@ -44,6 +44,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 pg_catalog database oid #define CATALOG_DATABASE_OID (0 | DATABASE_OID_MASK) @@ -76,6 +77,7 @@ enum class CatalogType : uint32_t { TRIGGER = 5 << CATALOG_TYPE_OFFSET, LANGUAGE = 6 << CATALOG_TYPE_OFFSET, PROC = 7 << CATALOG_TYPE_OFFSET, + SEQUENCE = 8 << CATALOG_TYPE_OFFSET, // To be added }; diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h new file mode 100644 index 00000000000..ecdb4a91f4e --- /dev/null +++ b/src/include/catalog/sequence_catalog.h @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// 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 "catalog/abstract_catalog.h" +#include "catalog/catalog_defaults.h" +#include "sequence/sequence.h" + +#define SEQUENCE_CATALOG_NAME "pg_sequence" + +namespace peloton { +namespace catalog { + +class SequenceCatalog : public AbstractCatalog { + public: + ~SequenceCatalog(); + + // Global Singleton + static SequenceCatalog &GetInstance(concurrency::TransactionContext *txn = nullptr); + + //===--------------------------------------------------------------------===// + // 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::unique_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); + + 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 + }; + + private: + SequenceCatalog(concurrency::TransactionContext *txn); + + oid_t GetNextOid() { return oid_++ | SEQUENCE_OID_MASK; } + + enum IndexId { + PRIMARY_KEY = 0, + DBOID_SEQNAME_KEY = 1 + }; +}; + +} // namespace catalog +} // namespace peloton diff --git a/src/include/common/exception.h b/src/include/common/exception.h index f7b050805be..ce17f62aa51 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 { @@ -128,6 +129,8 @@ class Exception : public std::runtime_error { return "Settings"; case ExceptionType::OPTIMIZER: return "Optimizer"; + case ExceptionType::SEQUENCE: + return "Sequence"; default: return "Unknown"; } @@ -463,4 +466,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/executor/create_executor.h b/src/include/executor/create_executor.h index 1802081ac62..fbdfd5ab7a0 100644 --- a/src/include/executor/create_executor.h +++ b/src/include/executor/create_executor.h @@ -52,6 +52,8 @@ class CreateExecutor : public AbstractExecutor { bool CreateTrigger(const planner::CreatePlan &node); + bool CreateSequence(const planner::CreatePlan &node); + private: ExecutorContext *context_; diff --git a/src/include/parser/create_statement.h b/src/include/parser/create_statement.h index 81945a5f646..5d1cbd1e548 100644 --- a/src/include/parser/create_statement.h +++ b/src/include/parser/create_statement.h @@ -13,6 +13,8 @@ #pragma once #include +#include + #include "common/sql_node_visitor.h" #include "expression/abstract_expression.h" #include "parser/sql_statement.h" @@ -258,12 +260,12 @@ class CreateStatement : public TableRefStatement { // attributes related to sequences std::string sequence_name; std::unique_ptr table; // deal with RangeVar - int64_t seq_start; - int64_t seq_increment; - int64_t seq_max_value; - int64_t seq_min_value; + int64_t seq_start = 1; + int64_t seq_increment = 1; + int64_t seq_max_value = LONG_MAX; + int64_t seq_min_value = 1; int64_t seq_cache; // sequence cache size, probably won't be supported in this project - bool seq_cycle; + bool seq_cycle = false; }; } // namespace parser diff --git a/src/include/sequence/sequence.h b/src/include/sequence/sequence.h index fd70f6d72e3..d8f53342f7b 100644 --- a/src/include/sequence/sequence.h +++ b/src/include/sequence/sequence.h @@ -12,6 +12,8 @@ #pragma once +#include + #include "common/logger.h" #include "planner/create_plan.h" #include "storage/tuple.h" @@ -31,30 +33,29 @@ class Sequence { Sequence(const std::string &name, const int64_t seqstart, const int64_t seqincrement, const int64_t seqmax, const int64_t seqmin, - const int64_t seqcache, const bool seqcycle): + const bool seqcycle, const int64_t seqval): seq_name(name), - seqstart(seqstart), - seqincrement(seqincrement), - seqmax(seqmax), - seqmin(seqmin), - seqcache(seqcache), - seqcycle(seqcycle) - { - curr_val = seqstart; - } + seq_start(seqstart), + seq_increment(seqincrement), + seq_max(seqmax), + seq_min(seqmin), + seq_cycle(seqcycle), + seq_curr_val(seqval){}; std::string seq_name; - int64_t seqstart; // Start value of the sequence - int64_t seqincrement; // Increment value of the sequence - int64_t seqmax; // Maximum value of the sequence - int64_t seqmin; // Minimum value of the sequence - int64_t seqcache; // Cache size of the sequence - bool seqcycle; // Whether the sequence cycles - + 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 + + std::mutex sequence_mutex; // mutex for all operations int64_t GetNextVal(); private: - int64_t curr_val; + int64_t seq_curr_val; + int64_t get_next_val(); }; diff --git a/src/sequence/sequence.cpp b/src/sequence/sequence.cpp index 472c5c36bfb..9c195f4bbd9 100644 --- a/src/sequence/sequence.cpp +++ b/src/sequence/sequence.cpp @@ -10,29 +10,62 @@ // //===----------------------------------------------------------------------===// +#include + #include "common/logger.h" #include "planner/create_plan.h" #include "storage/tuple.h" #include "common/internal_types.h" #include "sequence/sequence.h" +#include "common/exception.h" +#include "util/string_util.h" namespace peloton { namespace sequence { - Sequence::Sequence(const planner::CreatePlan &plan) { - seq_name = plan.GetSequenceName(); - seqstart = plan.GetSequenceStart(); // Start value of the sequence - seqincrement = plan.GetSequenceIncrement(); // Increment value of the sequence - seqmax = plan.GetSequenceMaxValue(); // Maximum value of the sequence - seqmin = plan.GetSequenceMinValue(); // Minimum value of the sequence - seqcache = plan.GetSequenceCacheSize(); // Cache size of the sequence - seqcycle = plan.GetSequenceCycle(); // Whether the sequence cycles - - curr_val = seqstart; - } - int64_t GetNextVal(){ - return 0; +Sequence::Sequence(const planner::CreatePlan &plan) { + seq_name = plan.GetSequenceName(); + seq_start = plan.GetSequenceStart(); // Start value of the sequence + seq_increment = plan.GetSequenceIncrement(); // Increment value of the sequence + seq_max = plan.GetSequenceMaxValue(); // Maximum value of the sequence + seq_min = plan.GetSequenceMinValue(); // Minimum value of the sequence + seq_cycle = plan.GetSequenceCycle(); // Whether the sequence cycles + + seq_curr_val = seq_start; +} + +int64_t Sequence::GetNextVal() { + std::lock_guard lock(sequence_mutex); + return get_next_val(); +} + +int64_t Sequence::get_next_val() { + int64_t result = seq_curr_val; + if(seq_increment > 0) { + 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("Sequence exceeds upper limit!")); + } + seq_curr_val = seq_min; + } + else + seq_curr_val += seq_increment; + } + else { + 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("Sequence exceeds lower limit!")); + } + seq_curr_val = seq_max; + } + else + seq_curr_val += seq_increment; } + return result; +} } // namespace sequence } // namespace peloton From c1a4e1db105178d3eb8f0b78c8f26235f3694ff2 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Mon, 2 Apr 2018 19:04:51 -0400 Subject: [PATCH 07/29] having issue with GetSequence() --- src/catalog/catalog.cpp | 14 +++-- src/catalog/sequence_catalog.cpp | 11 ++-- src/executor/create_executor.cpp | 7 ++- src/include/sequence/sequence.h | 3 + src/planner/create_plan.cpp | 3 +- test/sequence/sequence_test.cpp | 99 ++++++++++++++++++++++++++++++++ 6 files changed, 121 insertions(+), 16 deletions(-) create mode 100644 test/sequence/sequence_test.cpp diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index a7dfd8647fa..545c0b9fedd 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -25,6 +25,7 @@ #include "catalog/table_catalog.h" #include "catalog/table_metrics_catalog.h" #include "catalog/trigger_catalog.h" +#include "catalog/sequence_catalog.h" #include "concurrency/transaction_manager_factory.h" #include "function/date_functions.h" #include "function/decimal_functions.h" @@ -148,12 +149,13 @@ void Catalog::Bootstrap() { DatabaseMetricsCatalog::GetInstance(txn); TableMetricsCatalog::GetInstance(txn); IndexMetricsCatalog::GetInstance(txn); - QueryMetricsCatalog::GetInstance(txn); + QueryMetricsCatalog::GetInstance(txn); SettingsCatalog::GetInstance(txn); TriggerCatalog::GetInstance(txn); LanguageCatalog::GetInstance(txn); ProcCatalog::GetInstance(txn); - + SequenceCatalog::GetInstance(txn); + if (settings::SettingsManager::GetBool(settings::SettingId::brain)) { QueryHistoryCatalog::GetInstance(txn); } @@ -1106,28 +1108,28 @@ void Catalog::InitializeFunctions() { * integer functions */ AddBuiltinFunction( - "abs", {type::TypeId::TINYINT}, type::TypeId::TINYINT, + "abs", {type::TypeId::TINYINT}, type::TypeId::TINYINT, internal_lang, "Abs", function::BuiltInFuncType{OperatorId::Abs, function::DecimalFunctions::_Abs}, txn); AddBuiltinFunction( - "abs", {type::TypeId::SMALLINT}, type::TypeId::SMALLINT, + "abs", {type::TypeId::SMALLINT}, type::TypeId::SMALLINT, internal_lang, "Abs", function::BuiltInFuncType{OperatorId::Abs, function::DecimalFunctions::_Abs}, txn); AddBuiltinFunction( - "abs", {type::TypeId::INTEGER}, type::TypeId::INTEGER, + "abs", {type::TypeId::INTEGER}, type::TypeId::INTEGER, internal_lang, "Abs", function::BuiltInFuncType{OperatorId::Abs, function::DecimalFunctions::_Abs}, txn); AddBuiltinFunction( - "abs", {type::TypeId::BIGINT}, type::TypeId::BIGINT, + "abs", {type::TypeId::BIGINT}, type::TypeId::BIGINT, internal_lang, "Abs", function::BuiltInFuncType{OperatorId::Abs, function::DecimalFunctions::_Abs}, diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index e0b99415ef4..d9e5f424b0e 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -44,7 +44,7 @@ SequenceCatalog::SequenceCatalog(concurrency::TransactionContext *txn) Catalog::GetInstance()->CreateIndex( CATALOG_DATABASE_NAME, SEQUENCE_CATALOG_NAME, {ColumnId::DATABSE_OID, ColumnId::SEQUENCE_NAME}, - SEQUENCE_CATALOG_NAME "_skey0", true, IndexType::BWTREE, txn); + SEQUENCE_CATALOG_NAME "_skey0", false, IndexType::BWTREE, txn); } SequenceCatalog::~SequenceCatalog() {} @@ -54,6 +54,7 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, std::string sequence_na int64_t seq_start, bool seq_cycle, type::AbstractPool *pool, concurrency::TransactionContext *txn){ + LOG_DEBUG("In Insert Sequence Mode"); std::unique_ptr tuple( new storage::Tuple(catalog_table_->GetSchema(), true)); @@ -76,7 +77,7 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, std::string sequence_na 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, val7, pool); + tuple->SetValue(ColumnId::SEQUENCE_VALUE, val8, pool); // Insert the tuple return InsertTuple(std::move(tuple), txn); @@ -87,7 +88,7 @@ ResultType SequenceCatalog::DropSequence(const std::string &database_name, concurrency::TransactionContext *txn) { if (txn == nullptr) { LOG_TRACE("Do not have transaction to drop sequence: %s", - table_name.c_str()); + database_name.c_str()); return ResultType::FAILURE; } @@ -141,7 +142,7 @@ std::unique_ptr SequenceCatalog::GetSequence( GetResultWithIndexScan(column_ids, index_offset, values, txn); // carefull! the result tile could be null! if (result_tiles == nullptr) { - LOG_INFO("no trigger on sequence %d and %s", database_oid, sequence_name.c_str()); + LOG_INFO("no sequence on database %d and %s", database_oid, sequence_name.c_str()); return std::unique_ptr(nullptr); } else { LOG_INFO("size of the result tiles = %lu", result_tiles->size()); @@ -151,7 +152,7 @@ std::unique_ptr SequenceCatalog::GetSequence( for (unsigned int i = 0; i < result_tiles->size(); i++) { size_t tuple_count = (*result_tiles)[i]->GetTupleCount(); for (size_t j = 0; j < tuple_count; j++) { - // create a new trigger instance + // create a new sequence instance std::unique_ptr new_sequence = std::make_unique( (*result_tiles)[i]->GetValue(j, 0).ToString(), diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index b00c4594225..76b6c469280 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -277,6 +277,7 @@ bool CreateExecutor::CreateTrigger(const planner::CreatePlan &node) { } bool CreateExecutor::CreateSequence(const planner::CreatePlan &node) { + LOG_DEBUG("In create executor: sequence"); auto txn = context_->GetTransaction(); std::string database_name = node.GetDatabaseName(); std::string table_name = node.GetTableName(); @@ -292,11 +293,11 @@ bool CreateExecutor::CreateSequence(const planner::CreatePlan &node) { node.GetSequenceCycle(), pool_.get(), txn); if (txn->GetResult() == ResultType::SUCCESS) { - LOG_TRACE("Creating sequence succeeded!"); + LOG_DEBUG("Creating sequence succeeded!"); } else if (txn->GetResult() == ResultType::FAILURE) { - LOG_TRACE("Creating sequence failed!"); + LOG_DEBUG("Creating sequence failed!"); } else { - LOG_TRACE("Result is: %s", + LOG_DEBUG("Result is: %s", ResultTypeToString(txn->GetResult()).c_str()); } diff --git a/src/include/sequence/sequence.h b/src/include/sequence/sequence.h index d8f53342f7b..e7357a24b36 100644 --- a/src/include/sequence/sequence.h +++ b/src/include/sequence/sequence.h @@ -53,6 +53,9 @@ class Sequence { std::mutex sequence_mutex; // mutex for all operations int64_t GetNextVal(); + // should only be used in test. + int64_t GetCurrVal() {return seq_curr_val;}; + private: int64_t seq_curr_val; int64_t get_next_val(); diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index 20cf93d306e..9fa2f0fbc39 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -183,8 +183,7 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) case parser::CreateStatement::CreateType::kSequence: { LOG_DEBUG("CreatePlan: Create Sequence"); create_type = CreateType::SEQUENCE; - table_name = parse_tree->table->table_info_->table_name; - database_name = parse_tree->table->table_info_->database_name; + database_name = std::string(parse_tree->GetDatabaseName()); sequence_name = parse_tree->sequence_name; seq_start = parse_tree->seq_start; diff --git a/test/sequence/sequence_test.cpp b/test/sequence/sequence_test.cpp new file mode 100644 index 00000000000..bc21a07a69f --- /dev/null +++ b/test/sequence/sequence_test.cpp @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// +// 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 "sequence/sequence.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()->CreateDatabase(DEFAULT_DB_NAME, txn); + + txn_manager.CommitTransaction(txn); + } + + std::unique_ptr CreateSequenceHelper(std::string query, std::string sequence_name) { + // Bootstrap + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto parser = parser::PostgresParser::GetInstance(); + catalog::Catalog::GetInstance()->Bootstrap(); + + 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 + auto txn = txn_manager.BeginTransaction(); + std::unique_ptr context( + new executor::ExecutorContext(txn)); + executor::CreateExecutor createSequenceExecutor(&plan, context.get()); + createSequenceExecutor.Init(); + createSequenceExecutor.Execute(); + + // Check the effect of creation + txn_manager.CommitTransaction(txn); + txn = txn_manager.BeginTransaction(); + std::unique_ptr new_sequence = + catalog::SequenceCatalog::GetInstance().GetSequence(DEFAULT_DB_ID, sequence_name, txn); + txn_manager.CommitTransaction(txn); + + return new_sequence; + } +}; + +TEST_F(SequenceTests, BasicTest) { + // Create statement + CreateDatabaseHelper(); + auto parser = parser::PostgresParser::GetInstance(); + + std::string query = + "CREATE SEQUENCE seq " + "INCREMENT BY 2 " + "MINVALUE 10 MAXVALUE 50 " + "START 10 CYCLE;"; + std::string name = "seq"; + + std::unique_ptr new_sequence = CreateSequenceHelper(query, name); + 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->GetCurrVal()); +} + +} +} From f8ec42a2fca31b59eb37ec7dcca21b909701505d Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Sun, 8 Apr 2018 13:54:00 -0400 Subject: [PATCH 08/29] add new GetSequence impl; fix BasicTest in sequence --- src/catalog/sequence_catalog.cpp | 51 +++++++++++++++++++++----- src/include/catalog/sequence_catalog.h | 11 +++++- test/sequence/sequence_test.cpp | 14 ++++--- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index d9e5f424b0e..41274dc58fd 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -10,6 +10,9 @@ // //===----------------------------------------------------------------------===// +#include +#include + #include "catalog/sequence_catalog.h" #include "catalog/catalog.h" @@ -54,7 +57,8 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, std::string sequence_na int64_t seq_start, bool seq_cycle, type::AbstractPool *pool, concurrency::TransactionContext *txn){ - LOG_DEBUG("In Insert Sequence Mode"); + LOG_DEBUG("Insert Sequence Database Oid: %u", database_oid); + LOG_DEBUG("Insert Sequence Sequence Name: %s", sequence_name.c_str()); std::unique_ptr tuple( new storage::Tuple(catalog_table_->GetSchema(), true)); @@ -80,7 +84,18 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, std::string sequence_na tuple->SetValue(ColumnId::SEQUENCE_VALUE, val8, pool); // Insert the tuple - return InsertTuple(std::move(tuple), txn); + bool result = InsertTuple(std::move(tuple), txn); + + // If tuple successfully inserted, put the sequence into the sequence pool. + if(result) { + LOG_DEBUG("put sequence in the pool!"); + auto new_sequence = + std::make_shared(sequence_name, seq_start, seq_increment, seq_max, seq_min, seq_cycle, seq_start); + + sequence_pool.emplace(std::make_pair(boost::hash_value(std::make_pair(database_oid, sequence_name)), new_sequence)); + } + + return result; } ResultType SequenceCatalog::DropSequence(const std::string &database_name, @@ -102,12 +117,16 @@ ResultType SequenceCatalog::DropSequence(const std::string &database_name, return ResultType::FAILURE; } - LOG_INFO("trigger %d will be deleted!", sequence_oid); + LOG_INFO("sequence %d will be deleted!", sequence_oid); + oid_t database_oid = database_object->GetDatabaseOid(); bool delete_success = - DeleteSequenceByName(sequence_name, database_object->GetDatabaseOid(), txn); + DeleteSequenceByName(sequence_name, database_oid, txn); if (delete_success) { // might need to do sth. else after implementing insert + if(sequence_pool.erase(boost::hash_value(std::make_pair(database_oid, sequence_name))) != 1){ + LOG_INFO("the sequence %s to be deleted already not in the pool!", sequence_name.c_str()); + } return ResultType::SUCCESS; } @@ -125,7 +144,20 @@ bool SequenceCatalog::DeleteSequenceByName(const std::string &sequence_name, oid return DeleteWithIndexScan(index_offset, values, txn); } -std::unique_ptr SequenceCatalog::GetSequence( +std::shared_ptr SequenceCatalog::GetSequence( + oid_t database_oid, const std::string &sequence_name, UNUSED_ATTRIBUTE concurrency::TransactionContext *txn){ + LOG_DEBUG("Get Sequence Database Oid: %u", database_oid); + LOG_DEBUG("Get Sequence Sequence Name: %s", sequence_name.c_str()); + std::size_t key = boost::hash_value(std::make_pair(database_oid, sequence_name)); + auto it = sequence_pool.find(key); + if (it != sequence_pool.end()) { + return it->second; + } + + return nullptr; +} + +std::shared_ptr SequenceCatalog::GetSequenceFromPGTable( oid_t database_oid, const std::string &sequence_name, concurrency::TransactionContext *txn){ std::vector column_ids( {ColumnId::SEQUENCE_NAME,ColumnId::SEQUENCE_START, @@ -136,6 +168,8 @@ std::unique_ptr SequenceCatalog::GetSequence( std::vector values; values.push_back(type::ValueFactory::GetIntegerValue(database_oid).Copy()); values.push_back(type::ValueFactory::GetVarcharValue(sequence_name).Copy()); + LOG_DEBUG("The database_oid is %u", database_oid); + LOG_DEBUG("The sequence_name is %s", sequence_name.c_str()); // the result is a vector of executor::LogicalTile auto result_tiles = @@ -148,13 +182,12 @@ std::unique_ptr SequenceCatalog::GetSequence( LOG_INFO("size of the result tiles = %lu", result_tiles->size()); } - PL_ASSERT(result_tiles->size() == 1); for (unsigned int i = 0; i < result_tiles->size(); i++) { size_t tuple_count = (*result_tiles)[i]->GetTupleCount(); for (size_t j = 0; j < tuple_count; j++) { // create a new sequence instance - std::unique_ptr new_sequence = - std::make_unique( + auto new_sequence = + std::make_shared( (*result_tiles)[i]->GetValue(j, 0).ToString(), (*result_tiles)[i]->GetValue(j, 1).GetAs(), (*result_tiles)[i]->GetValue(j, 2).GetAs(), @@ -184,7 +217,7 @@ oid_t SequenceCatalog::GetSequenceOid(std::string sequence_name, oid_t database_ GetResultWithIndexScan(column_ids, index_offset, values, txn); // carefull! the result tile could be null! if (result_tiles == nullptr) { - LOG_INFO("no trigger on sequence %d and %s", database_oid, sequence_name.c_str()); + LOG_INFO("no sequence on database %d and %s", database_oid, sequence_name.c_str()); return INVALID_OID; } diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h index ecdb4a91f4e..84c22a23cba 100644 --- a/src/include/catalog/sequence_catalog.h +++ b/src/include/catalog/sequence_catalog.h @@ -31,6 +31,10 @@ #pragma once +#include +#include +#include + #include "catalog/abstract_catalog.h" #include "catalog/catalog_defaults.h" #include "sequence/sequence.h" @@ -63,9 +67,12 @@ class SequenceCatalog : public AbstractCatalog { bool DeleteSequenceByName(const std::string &sequence_name, oid_t database_oid, concurrency::TransactionContext *txn); - std::unique_ptr GetSequence( + std::shared_ptr GetSequence( oid_t database_oid, const std::string &sequence_name, concurrency::TransactionContext *txn); + std::shared_ptr GetSequenceFromPGTable( + 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); @@ -90,6 +97,8 @@ class SequenceCatalog : public AbstractCatalog { PRIMARY_KEY = 0, DBOID_SEQNAME_KEY = 1 }; + + std::unordered_map> sequence_pool; }; } // namespace catalog diff --git a/test/sequence/sequence_test.cpp b/test/sequence/sequence_test.cpp index bc21a07a69f..e9862d7d241 100644 --- a/test/sequence/sequence_test.cpp +++ b/test/sequence/sequence_test.cpp @@ -34,7 +34,7 @@ class SequenceTests : public PelotonTest { txn_manager.CommitTransaction(txn); } - std::unique_ptr CreateSequenceHelper(std::string query, std::string sequence_name) { + std::shared_ptr CreateSequenceHelper(std::string query, std::string sequence_name) { // Bootstrap auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto parser = parser::PostgresParser::GetInstance(); @@ -63,10 +63,9 @@ class SequenceTests : public PelotonTest { createSequenceExecutor.Execute(); // Check the effect of creation - txn_manager.CommitTransaction(txn); - txn = txn_manager.BeginTransaction(); - std::unique_ptr new_sequence = - catalog::SequenceCatalog::GetInstance().GetSequence(DEFAULT_DB_ID, sequence_name, txn); + oid_t database_oid = catalog::Catalog::GetInstance()->GetDatabaseWithName(DEFAULT_DB_NAME, txn)->GetOid(); + std::shared_ptr new_sequence = + catalog::SequenceCatalog::GetInstance().GetSequence(database_oid, sequence_name, txn); txn_manager.CommitTransaction(txn); return new_sequence; @@ -85,7 +84,10 @@ TEST_F(SequenceTests, BasicTest) { "START 10 CYCLE;"; std::string name = "seq"; - std::unique_ptr new_sequence = CreateSequenceHelper(query, name); + std::shared_ptr new_sequence = CreateSequenceHelper(query, name); + if(!new_sequence) { + std::cout << "get nullptr" << std::endl; + } EXPECT_EQ(name, new_sequence->seq_name); EXPECT_EQ(2, new_sequence->seq_increment); EXPECT_EQ(10, new_sequence->seq_min); From 0d3521cf5a31624c5fcde4aa89d9071f44600685 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Tue, 10 Apr 2018 19:04:56 -0400 Subject: [PATCH 09/29] add tests for sequence --- src/catalog/sequence_catalog.cpp | 50 +--------- src/include/catalog/sequence_catalog.h | 3 - src/include/sequence/sequence.h | 5 +- test/sequence/sequence_test.cpp | 130 ++++++++++++++++++++++--- 4 files changed, 125 insertions(+), 63 deletions(-) diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index 41274dc58fd..5dc3b746f81 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -59,6 +59,10 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, std::string sequence_na concurrency::TransactionContext *txn){ LOG_DEBUG("Insert Sequence Database Oid: %u", database_oid); LOG_DEBUG("Insert Sequence Sequence Name: %s", sequence_name.c_str()); + if(GetSequence(database_oid, sequence_name, txn) != nullptr) { + throw SequenceException(StringUtil::Format("Insert Sequence with Duplicate Sequence Name: %s", sequence_name.c_str())); + } + std::unique_ptr tuple( new storage::Tuple(catalog_table_->GetSchema(), true)); @@ -157,52 +161,6 @@ std::shared_ptr SequenceCatalog::GetSequence( return nullptr; } -std::shared_ptr SequenceCatalog::GetSequenceFromPGTable( - oid_t database_oid, const std::string &sequence_name, concurrency::TransactionContext *txn){ - std::vector column_ids( - {ColumnId::SEQUENCE_NAME,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()); - LOG_DEBUG("The database_oid is %u", database_oid); - LOG_DEBUG("The sequence_name is %s", sequence_name.c_str()); - - // the result is a vector of executor::LogicalTile - auto result_tiles = - GetResultWithIndexScan(column_ids, index_offset, values, txn); - // carefull! the result tile could be null! - if (result_tiles == nullptr) { - LOG_INFO("no sequence on database %d and %s", database_oid, sequence_name.c_str()); - return std::unique_ptr(nullptr); - } else { - LOG_INFO("size of the result tiles = %lu", result_tiles->size()); - } - - for (unsigned int i = 0; i < result_tiles->size(); i++) { - size_t tuple_count = (*result_tiles)[i]->GetTupleCount(); - for (size_t j = 0; j < tuple_count; j++) { - // create a new sequence instance - auto new_sequence = - std::make_shared( - (*result_tiles)[i]->GetValue(j, 0).ToString(), - (*result_tiles)[i]->GetValue(j, 1).GetAs(), - (*result_tiles)[i]->GetValue(j, 2).GetAs(), - (*result_tiles)[i]->GetValue(j, 3).GetAs(), - (*result_tiles)[i]->GetValue(j, 4).GetAs(), - (*result_tiles)[i]->GetValue(j, 5).GetAs(), - (*result_tiles)[i]->GetValue(j, 6).GetAs()); - - return new_sequence; - } - } - - return std::unique_ptr(nullptr); -} - oid_t SequenceCatalog::GetSequenceOid(std::string sequence_name, oid_t database_oid, concurrency::TransactionContext *txn) { std::vector column_ids( diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h index 84c22a23cba..f46376d6c85 100644 --- a/src/include/catalog/sequence_catalog.h +++ b/src/include/catalog/sequence_catalog.h @@ -70,9 +70,6 @@ class SequenceCatalog : public AbstractCatalog { std::shared_ptr GetSequence( oid_t database_oid, const std::string &sequence_name, concurrency::TransactionContext *txn); - std::shared_ptr GetSequenceFromPGTable( - 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); diff --git a/src/include/sequence/sequence.h b/src/include/sequence/sequence.h index e7357a24b36..eca96066fd4 100644 --- a/src/include/sequence/sequence.h +++ b/src/include/sequence/sequence.h @@ -53,8 +53,9 @@ class Sequence { std::mutex sequence_mutex; // mutex for all operations int64_t GetNextVal(); - // should only be used in test. - int64_t GetCurrVal() {return seq_curr_val;}; + int64_t GetCurrVal() { return seq_curr_val; }; // only visible for test! + 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; diff --git a/test/sequence/sequence_test.cpp b/test/sequence/sequence_test.cpp index e9862d7d241..a4a52ca67bd 100644 --- a/test/sequence/sequence_test.cpp +++ b/test/sequence/sequence_test.cpp @@ -14,6 +14,7 @@ #include "catalog/sequence_catalog.h" #include "storage/abstract_table.h" #include "common/harness.h" +#include "common/exception.h" #include "sequence/sequence.h" #include "executor/executors.h" #include "parser/postgresparser.h" @@ -34,7 +35,20 @@ class SequenceTests : public PelotonTest { txn_manager.CommitTransaction(txn); } - std::shared_ptr CreateSequenceHelper(std::string query, std::string sequence_name) { + std::shared_ptr GetSequenceHelper(std::string sequence_name) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + + // Check the effect of creation + oid_t database_oid = catalog::Catalog::GetInstance()->GetDatabaseWithName(DEFAULT_DB_NAME, txn)->GetOid(); + std::shared_ptr new_sequence = + catalog::SequenceCatalog::GetInstance().GetSequence(database_oid, sequence_name, txn); + txn_manager.CommitTransaction(txn); + + return new_sequence; + } + + void CreateSequenceHelper(std::string query) { // Bootstrap auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto parser = parser::PostgresParser::GetInstance(); @@ -61,14 +75,7 @@ class SequenceTests : public PelotonTest { executor::CreateExecutor createSequenceExecutor(&plan, context.get()); createSequenceExecutor.Init(); createSequenceExecutor.Execute(); - - // Check the effect of creation - oid_t database_oid = catalog::Catalog::GetInstance()->GetDatabaseWithName(DEFAULT_DB_NAME, txn)->GetOid(); - std::shared_ptr new_sequence = - catalog::SequenceCatalog::GetInstance().GetSequence(database_oid, sequence_name, txn); txn_manager.CommitTransaction(txn); - - return new_sequence; } }; @@ -84,10 +91,9 @@ TEST_F(SequenceTests, BasicTest) { "START 10 CYCLE;"; std::string name = "seq"; - std::shared_ptr new_sequence = CreateSequenceHelper(query, name); - if(!new_sequence) { - std::cout << "get nullptr" << std::endl; - } + CreateSequenceHelper(query); + std::shared_ptr new_sequence = GetSequenceHelper(name); + EXPECT_EQ(name, new_sequence->seq_name); EXPECT_EQ(2, new_sequence->seq_increment); EXPECT_EQ(10, new_sequence->seq_min); @@ -95,6 +101,106 @@ TEST_F(SequenceTests, BasicTest) { EXPECT_EQ(10, new_sequence->seq_start); EXPECT_EQ(true, new_sequence->seq_cycle); EXPECT_EQ(10, new_sequence->GetCurrVal()); + + int64_t nextVal = new_sequence->GetNextVal(); + EXPECT_EQ(10, nextVal); +} + +TEST_F(SequenceTests, NoDuplicateTest) { + // Create statement + auto parser = parser::PostgresParser::GetInstance(); + + 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); + EXPECT_EQ(0, 1); + } + catch(const SequenceException& expected) { + ASSERT_STREQ("Insert Sequence with Duplicate Sequence Name: seq", expected.what()); + } +} + +TEST_F(SequenceTests, NextValPosIncrementTest) { + auto parser = parser::PostgresParser::GetInstance(); + + std::string query = + "CREATE SEQUENCE seq1 " + "INCREMENT BY 1 " + "MINVALUE 10 MAXVALUE 50 " + "START 10 CYCLE;"; + std::string name = "seq1"; + + CreateSequenceHelper(query); + std::shared_ptr new_sequence = GetSequenceHelper(name); + + 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("Sequence exceeds upper limit!", expected.what()); + } +} + +TEST_F(SequenceTests, NextValNegIncrementTest) { + auto parser = parser::PostgresParser::GetInstance(); + + std::string query = + "CREATE SEQUENCE seq2 " + "INCREMENT BY -1 " + "MINVALUE 10 MAXVALUE 50 " + "START 10 CYCLE;"; + std::string name = "seq2"; + + CreateSequenceHelper(query); + std::shared_ptr new_sequence = GetSequenceHelper(name); + + // 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("Sequence exceeds lower limit!", expected.what()); + } } } From 87680be36488f72063d71258e4ff1465d8e25955 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Thu, 12 Apr 2018 10:37:30 -0400 Subject: [PATCH 10/29] one step before submitting pr --- src/catalog/sequence_catalog.cpp | 153 +++++++++++++++++-------- src/executor/create_executor.cpp | 1 - src/include/catalog/sequence_catalog.h | 57 ++++++++- src/include/sequence/sequence.h | 67 ----------- src/parser/postgresparser.cpp | 3 - src/planner/create_plan.cpp | 1 - src/sequence/sequence.cpp | 71 ------------ test/sequence/sequence_test.cpp | 56 +++++---- 8 files changed, 183 insertions(+), 226 deletions(-) delete mode 100644 src/include/sequence/sequence.h delete mode 100644 src/sequence/sequence.cpp diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index 5dc3b746f81..9520f3aa2cd 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include -#include #include "catalog/sequence_catalog.h" @@ -21,28 +20,77 @@ #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 { +int64_t SequenceCatalogObject::get_next_val() { + int64_t result = seq_curr_val; + if(seq_increment > 0) { + 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("Sequence exceeds upper limit!")); + } + seq_curr_val = seq_min; + } + else + seq_curr_val += seq_increment; + } + else { + 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("Sequence exceeds lower limit!")); + } + seq_curr_val = seq_max; + } + else + seq_curr_val += seq_increment; + } + + // auto &peloton_parser = parser::PostgresParser::GetInstance(); + // std::string update_statement = "UPDATE " + std::string(SEQUENCE_CATALOG_NAME) + + // " SET sqval=" + std::to_string(seq_curr_val) + + // " WHERE oid=" + std::to_string(seq_oid); + // LOG_DEBUG("update sql statement:%s", update_statement.c_str()); + // auto update_plan = optimizer::Optimizer().BuildPelotonPlanTree( + // peloton_parser.BuildParseTree(update_statement), + // CATALOG_DATABASE_NAME, txn_).get(); + + // std::unique_ptr context( + // new executor::ExecutorContext(txn_)); + // executor::UpdateExecutor executor(update_plan, context.get()); + // executor.Init(); + // bool status = executor.Execute(); + // LOG_DEBUG("status of update nextval:%d", status); + return result; +} + SequenceCatalog &SequenceCatalog::GetInstance(concurrency::TransactionContext *txn) { static SequenceCatalog sequence_catalog{txn}; return sequence_catalog; } SequenceCatalog::SequenceCatalog(concurrency::TransactionContext *txn) - : AbstractCatalog("CREATE TABLE " CATALOG_DATABASE_NAME - "." SEQUENCE_CATALOG_NAME + : AbstractCatalog("CREATE TABLE " SEQUENCE_CATALOG_NAME " (" "oid INT NOT NULL PRIMARY KEY, " "sqdboid INT NOT NULL, " "sqname VARCHAR NOT NULL, " - "sqinc INT NOT NULL, " - "sqmax INT NOT NULL, " - "sqmin INT NOT NULL, " - "sqstart INT NOT NULL, " + "sqinc BIGINT NOT NULL, " + "sqmax BIGINT NOT NULL, " + "sqmin BIGINT NOT NULL, " + "sqstart BIGINT NOT NULL, " "sqcycle BOOLEAN NOT NULL, " - "sqval INT NOT NULL);", + "sqval BIGINT NOT NULL);", txn) { Catalog::GetInstance()->CreateIndex( CATALOG_DATABASE_NAME, SEQUENCE_CATALOG_NAME, @@ -69,13 +117,13 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, std::string sequence_na auto val0 = type::ValueFactory::GetIntegerValue(GetNextOid()); auto val1 = type::ValueFactory::GetIntegerValue(database_oid); auto val2 = type::ValueFactory::GetVarcharValue(sequence_name); - auto val3 = type::ValueFactory::GetIntegerValue(seq_increment); - auto val4 = type::ValueFactory::GetIntegerValue(seq_max); - auto val5 = type::ValueFactory::GetIntegerValue(seq_min); - auto val6 = type::ValueFactory::GetIntegerValue(seq_start); + 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::GetIntegerValue(seq_start); + auto val8 = type::ValueFactory::GetBigIntValue(seq_start); tuple->SetValue(ColumnId::SEQUENCE_OID, val0, pool); tuple->SetValue(ColumnId::DATABSE_OID, val1, pool); @@ -88,18 +136,7 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, std::string sequence_na tuple->SetValue(ColumnId::SEQUENCE_VALUE, val8, pool); // Insert the tuple - bool result = InsertTuple(std::move(tuple), txn); - - // If tuple successfully inserted, put the sequence into the sequence pool. - if(result) { - LOG_DEBUG("put sequence in the pool!"); - auto new_sequence = - std::make_shared(sequence_name, seq_start, seq_increment, seq_max, seq_min, seq_cycle, seq_start); - - sequence_pool.emplace(std::make_pair(boost::hash_value(std::make_pair(database_oid, sequence_name)), new_sequence)); - } - - return result; + return InsertTuple(std::move(tuple), txn); } ResultType SequenceCatalog::DropSequence(const std::string &database_name, @@ -124,18 +161,9 @@ ResultType SequenceCatalog::DropSequence(const std::string &database_name, LOG_INFO("sequence %d will be deleted!", sequence_oid); oid_t database_oid = database_object->GetDatabaseOid(); - bool delete_success = - DeleteSequenceByName(sequence_name, database_oid, txn); - if (delete_success) { - // might need to do sth. else after implementing insert - if(sequence_pool.erase(boost::hash_value(std::make_pair(database_oid, sequence_name))) != 1){ - LOG_INFO("the sequence %s to be deleted already not in the pool!", sequence_name.c_str()); - } - return ResultType::SUCCESS; - } + DeleteSequenceByName(sequence_name, database_oid, txn); - LOG_DEBUG("Failed to delete sequence"); - return ResultType::FAILURE; + return ResultType::SUCCESS; } bool SequenceCatalog::DeleteSequenceByName(const std::string &sequence_name, oid_t database_oid, @@ -148,17 +176,44 @@ bool SequenceCatalog::DeleteSequenceByName(const std::string &sequence_name, oid return DeleteWithIndexScan(index_offset, values, txn); } -std::shared_ptr SequenceCatalog::GetSequence( - oid_t database_oid, const std::string &sequence_name, UNUSED_ATTRIBUTE concurrency::TransactionContext *txn){ - LOG_DEBUG("Get Sequence Database Oid: %u", database_oid); - LOG_DEBUG("Get Sequence Sequence Name: %s", sequence_name.c_str()); - std::size_t key = boost::hash_value(std::make_pair(database_oid, sequence_name)); - auto it = sequence_pool.find(key); - if (it != sequence_pool.end()) { - return it->second; +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_NAME, + 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); + // carefull! 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()); } - return nullptr; + PELOTON_ASSERT(result_tiles->size() == 1); + size_t tuple_count = (*result_tiles)[0]->GetTupleCount(); + PELOTON_ASSERT(tuple_count == 1); + auto new_sequence = + std::make_shared( + (*result_tiles)[0]->GetValue(0, 0).GetAs(), + (*result_tiles)[0]->GetValue(0, 1).ToString(), + (*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(), + (*result_tiles)[0]->GetValue(0, 7).GetAs(), txn); + + return new_sequence; } oid_t SequenceCatalog::GetSequenceOid(std::string sequence_name, oid_t database_oid, @@ -174,16 +229,14 @@ oid_t SequenceCatalog::GetSequenceOid(std::string sequence_name, oid_t database_ auto result_tiles = GetResultWithIndexScan(column_ids, index_offset, values, txn); // carefull! the result tile could be null! - if (result_tiles == nullptr) { + 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; } - PL_ASSERT(result_tiles->size() == 1); + PELOTON_ASSERT(result_tiles->size() == 1); oid_t result; - for (unsigned int i = 0; i < result_tiles->size(); i++) { - result = (*result_tiles)[i]->GetValue(0, 0).GetAs(); - } + result = (*result_tiles)[0]->GetValue(0, 0).GetAs(); return result; } diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index 9d4ab0522eb..748a27921f6 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -277,7 +277,6 @@ bool CreateExecutor::CreateTrigger(const planner::CreatePlan &node) { } bool CreateExecutor::CreateSequence(const planner::CreatePlan &node) { - LOG_DEBUG("In create executor: sequence"); auto txn = context_->GetTransaction(); std::string database_name = node.GetDatabaseName(); std::string table_name = node.GetTableName(); diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h index f46376d6c85..8a3bb78c04c 100644 --- a/src/include/catalog/sequence_catalog.h +++ b/src/include/catalog/sequence_catalog.h @@ -34,16 +34,67 @@ #include #include #include +#include #include "catalog/abstract_catalog.h" #include "catalog/catalog_defaults.h" -#include "sequence/sequence.h" #define SEQUENCE_CATALOG_NAME "pg_sequence" namespace peloton { + +namespace concurrency { +class TransactionContext; +} + namespace catalog { +class SequenceCatalogObject { + public: + SequenceCatalogObject(oid_t seqoid, 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), + 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; + 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_; + + std::mutex sequence_mutex; // mutex for all operations + int64_t GetNextVal() { + std::lock_guard lock(sequence_mutex); + return get_next_val(); + }; + + int64_t GetCurrVal() { + std::lock_guard lock(sequence_mutex); + return seq_curr_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; + int64_t get_next_val(); +}; + + class SequenceCatalog : public AbstractCatalog { public: ~SequenceCatalog(); @@ -67,7 +118,7 @@ class SequenceCatalog : public AbstractCatalog { bool DeleteSequenceByName(const std::string &sequence_name, oid_t database_oid, concurrency::TransactionContext *txn); - std::shared_ptr GetSequence( + 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, @@ -94,8 +145,6 @@ class SequenceCatalog : public AbstractCatalog { PRIMARY_KEY = 0, DBOID_SEQNAME_KEY = 1 }; - - std::unordered_map> sequence_pool; }; } // namespace catalog diff --git a/src/include/sequence/sequence.h b/src/include/sequence/sequence.h deleted file mode 100644 index eca96066fd4..00000000000 --- a/src/include/sequence/sequence.h +++ /dev/null @@ -1,67 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Peloton -// -// sequence.h -// -// Identification: src/include/sequence/sequence.h -// -// Copyright (c) 2015-17, Carnegie Mellon University Database Group -// -//===----------------------------------------------------------------------===// - -#pragma once - -#include - -#include "common/logger.h" -#include "planner/create_plan.h" -#include "storage/tuple.h" -#include "common/internal_types.h" - -namespace peloton { - -namespace concurrency { -class TransactionContext; -} - -namespace sequence { -class Sequence { - public: - Sequence(const planner::CreatePlan &plan); - - Sequence(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): - seq_name(name), - seq_start(seqstart), - seq_increment(seqincrement), - seq_max(seqmax), - seq_min(seqmin), - seq_cycle(seqcycle), - seq_curr_val(seqval){}; - - 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 - - std::mutex sequence_mutex; // mutex for all operations - int64_t GetNextVal(); - - int64_t GetCurrVal() { return seq_curr_val; }; // only visible for test! - 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; - int64_t get_next_val(); -}; - - -} // namespace sequence -} // namespace peloton diff --git a/src/parser/postgresparser.cpp b/src/parser/postgresparser.cpp index 8747cc6a31d..70f509dd9c1 100644 --- a/src/parser/postgresparser.cpp +++ b/src/parser/postgresparser.cpp @@ -1347,14 +1347,11 @@ parser::SQLStatement *PostgresParser::CreateViewTransform(ViewStmt *root) { } parser::SQLStatement *PostgresParser::CreateSequenceTransform(CreateSeqStmt *root){ - LOG_DEBUG("In create sequence transform"); parser::CreateStatement *result = new parser::CreateStatement(CreateStatement::kSequence); result->sequence_name = std::string(root->sequence->relname); - LOG_DEBUG("New Sequence Name:%s\n", result->sequence_name.c_str()); result->table.reset( RangeVarTransform(reinterpret_cast(root->sequence))); - LOG_DEBUG("Before parse sequences"); parse_sequence_params(root->options, result); return result; } diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index 9fa2f0fbc39..a612c028820 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -181,7 +181,6 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) break; } case parser::CreateStatement::CreateType::kSequence: { - LOG_DEBUG("CreatePlan: Create Sequence"); create_type = CreateType::SEQUENCE; database_name = std::string(parse_tree->GetDatabaseName()); diff --git a/src/sequence/sequence.cpp b/src/sequence/sequence.cpp deleted file mode 100644 index 9c195f4bbd9..00000000000 --- a/src/sequence/sequence.cpp +++ /dev/null @@ -1,71 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Peloton -// -// sequence.cpp -// -// Identification: src/sequence/sequence.cpp -// -// Copyright (c) 2015-17, Carnegie Mellon University Database Group -// -//===----------------------------------------------------------------------===// - -#include - -#include "common/logger.h" -#include "planner/create_plan.h" -#include "storage/tuple.h" -#include "common/internal_types.h" -#include "sequence/sequence.h" -#include "common/exception.h" -#include "util/string_util.h" - -namespace peloton { -namespace sequence { - -Sequence::Sequence(const planner::CreatePlan &plan) { - seq_name = plan.GetSequenceName(); - seq_start = plan.GetSequenceStart(); // Start value of the sequence - seq_increment = plan.GetSequenceIncrement(); // Increment value of the sequence - seq_max = plan.GetSequenceMaxValue(); // Maximum value of the sequence - seq_min = plan.GetSequenceMinValue(); // Minimum value of the sequence - seq_cycle = plan.GetSequenceCycle(); // Whether the sequence cycles - - seq_curr_val = seq_start; -} - -int64_t Sequence::GetNextVal() { - std::lock_guard lock(sequence_mutex); - return get_next_val(); -} - -int64_t Sequence::get_next_val() { - int64_t result = seq_curr_val; - if(seq_increment > 0) { - 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("Sequence exceeds upper limit!")); - } - seq_curr_val = seq_min; - } - else - seq_curr_val += seq_increment; - } - else { - 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("Sequence exceeds lower limit!")); - } - seq_curr_val = seq_max; - } - else - seq_curr_val += seq_increment; - } - return result; -} - -} // namespace sequence -} // namespace peloton diff --git a/test/sequence/sequence_test.cpp b/test/sequence/sequence_test.cpp index a4a52ca67bd..9010dfd69f7 100644 --- a/test/sequence/sequence_test.cpp +++ b/test/sequence/sequence_test.cpp @@ -15,7 +15,6 @@ #include "storage/abstract_table.h" #include "common/harness.h" #include "common/exception.h" -#include "sequence/sequence.h" #include "executor/executors.h" #include "parser/postgresparser.h" #include "planner/create_plan.h" @@ -30,29 +29,22 @@ class SequenceTests : public PelotonTest { 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) { - auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); - auto txn = txn_manager.BeginTransaction(); - + 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 = + std::shared_ptr new_sequence = catalog::SequenceCatalog::GetInstance().GetSequence(database_oid, sequence_name, txn); - txn_manager.CommitTransaction(txn); return new_sequence; } - void CreateSequenceHelper(std::string query) { - // Bootstrap - auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + void CreateSequenceHelper(std::string query, concurrency::TransactionContext *txn) { auto parser = parser::PostgresParser::GetInstance(); - catalog::Catalog::GetInstance()->Bootstrap(); std::unique_ptr stmt_list( parser.BuildParseTree(query).release()); @@ -69,21 +61,20 @@ class SequenceTests : public PelotonTest { EXPECT_EQ(CreateType::SEQUENCE, plan.GetCreateType()); // Execute the create sequence - auto txn = txn_manager.BeginTransaction(); std::unique_ptr context( new executor::ExecutorContext(txn)); executor::CreateExecutor createSequenceExecutor(&plan, context.get()); createSequenceExecutor.Init(); createSequenceExecutor.Execute(); - txn_manager.CommitTransaction(txn); } }; TEST_F(SequenceTests, BasicTest) { - // Create statement CreateDatabaseHelper(); - auto parser = parser::PostgresParser::GetInstance(); + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + // Create statement std::string query = "CREATE SEQUENCE seq " "INCREMENT BY 2 " @@ -91,8 +82,8 @@ TEST_F(SequenceTests, BasicTest) { "START 10 CYCLE;"; std::string name = "seq"; - CreateSequenceHelper(query); - std::shared_ptr new_sequence = GetSequenceHelper(name); + 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); @@ -104,12 +95,14 @@ TEST_F(SequenceTests, BasicTest) { int64_t nextVal = new_sequence->GetNextVal(); EXPECT_EQ(10, nextVal); + txn_manager.CommitTransaction(txn); } TEST_F(SequenceTests, NoDuplicateTest) { - // Create statement - auto parser = parser::PostgresParser::GetInstance(); + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + // Create statement std::string query = "CREATE SEQUENCE seq " "INCREMENT BY 2 " @@ -119,16 +112,18 @@ TEST_F(SequenceTests, NoDuplicateTest) { // Expect exception try { - CreateSequenceHelper(query); + CreateSequenceHelper(query, txn); EXPECT_EQ(0, 1); } catch(const SequenceException& expected) { ASSERT_STREQ("Insert Sequence with Duplicate Sequence Name: seq", expected.what()); } + txn_manager.CommitTransaction(txn); } -TEST_F(SequenceTests, NextValPosIncrementTest) { - auto parser = parser::PostgresParser::GetInstance(); +TEST_F(SequenceTests, NextValPosIncrementFunctionalityTest) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); std::string query = "CREATE SEQUENCE seq1 " @@ -137,8 +132,8 @@ TEST_F(SequenceTests, NextValPosIncrementTest) { "START 10 CYCLE;"; std::string name = "seq1"; - CreateSequenceHelper(query); - std::shared_ptr new_sequence = GetSequenceHelper(name); + CreateSequenceHelper(query, txn); + std::shared_ptr new_sequence = GetSequenceHelper(name, txn); int64_t nextVal = new_sequence->GetNextVal(); EXPECT_EQ(10, nextVal); @@ -163,10 +158,12 @@ TEST_F(SequenceTests, NextValPosIncrementTest) { catch(const SequenceException& expected) { ASSERT_STREQ("Sequence exceeds upper limit!", expected.what()); } + txn_manager.CommitTransaction(txn); } -TEST_F(SequenceTests, NextValNegIncrementTest) { - auto parser = parser::PostgresParser::GetInstance(); +TEST_F(SequenceTests, NextValNegIncrementFunctionalityTest) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); std::string query = "CREATE SEQUENCE seq2 " @@ -175,8 +172,8 @@ TEST_F(SequenceTests, NextValNegIncrementTest) { "START 10 CYCLE;"; std::string name = "seq2"; - CreateSequenceHelper(query); - std::shared_ptr new_sequence = GetSequenceHelper(name); + CreateSequenceHelper(query, txn); + std::shared_ptr new_sequence = GetSequenceHelper(name, txn); // test cycle int64_t nextVal = new_sequence->GetNextVal(); @@ -201,6 +198,7 @@ TEST_F(SequenceTests, NextValNegIncrementTest) { catch(const SequenceException& expected) { ASSERT_STREQ("Sequence exceeds lower limit!", expected.what()); } + txn_manager.CommitTransaction(txn); } } From 7d7955c2f53b75bbd00bd78c17b95fbeee201f6a Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Thu, 12 Apr 2018 13:54:13 -0400 Subject: [PATCH 11/29] change way of update pg_sequence table in nextval --- src/catalog/sequence_catalog.cpp | 70 +++++++++++++++++++++++++------- src/parser/postgresparser.cpp | 25 ------------ 2 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index 9520f3aa2cd..6bd096867b1 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -30,6 +30,10 @@ 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::get_next_val() { int64_t result = seq_curr_val; if(seq_increment > 0) { @@ -56,21 +60,20 @@ int64_t SequenceCatalogObject::get_next_val() { seq_curr_val += seq_increment; } - // auto &peloton_parser = parser::PostgresParser::GetInstance(); - // std::string update_statement = "UPDATE " + std::string(SEQUENCE_CATALOG_NAME) + - // " SET sqval=" + std::to_string(seq_curr_val) + - // " WHERE oid=" + std::to_string(seq_oid); - // LOG_DEBUG("update sql statement:%s", update_statement.c_str()); - // auto update_plan = optimizer::Optimizer().BuildPelotonPlanTree( - // peloton_parser.BuildParseTree(update_statement), - // CATALOG_DATABASE_NAME, txn_).get(); - - // std::unique_ptr context( - // new executor::ExecutorContext(txn_)); - // executor::UpdateExecutor executor(update_plan, context.get()); - // executor.Init(); - // bool status = executor.Execute(); - // LOG_DEBUG("status of update nextval:%d", status); + // TODO: this will become visible after Mengran's team push the AbstractCatalog::UpdateWithIndexScan. + // Link for the function: + // https://github.com/camellyx/peloton/blob/master/src/catalog/abstract_catalog.cpp#L305 + + // std::vector update_columns({ColumnId::SEQUENCE_VALUE}); + // std::vector update_values; + // update_values.push_back(type::ValueFactory::GetBigIntValue(seq_curr_val).Copy()); + // std::vector scan_values; + // scan_values.push_back(type::ValueFactory::GetIntegerValue(seq_oid).Copy()); + // oid_t index_offset = IndexId::PRIMARY_KEY; + + // bool status = catalog::SequenceCatalog::GetInstance().UpdateWithIndexScan(update_columns, update_values, scan_values, index_offset, txn_); + // LOG_DEBUG("status of update pg_sequence: %d", status); + return result; } @@ -100,6 +103,19 @@ SequenceCatalog::SequenceCatalog(concurrency::TransactionContext *txn) SequenceCatalog::~SequenceCatalog() {} +/* @brief Delete 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, @@ -139,6 +155,12 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, std::string sequence_na return InsertTuple(std::move(tuple), txn); } +/* @brief Delete the sequence by name. + * @param database_oid the databse_oid associated with the sequence + * @param sequence_name the name of the sequence + * @param txn current transaction + * @return ResultType::SUCCESS if the sequence exists, ResultType::FAILURE otherwise. + */ ResultType SequenceCatalog::DropSequence(const std::string &database_name, const std::string &sequence_name, concurrency::TransactionContext *txn) { @@ -166,6 +188,12 @@ ResultType SequenceCatalog::DropSequence(const std::string &database_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; @@ -176,6 +204,12 @@ bool SequenceCatalog::DeleteSequenceByName(const std::string &sequence_name, oid 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( @@ -216,6 +250,12 @@ std::shared_ptr SequenceCatalog::GetSequence( return new_sequence; } +/* @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( diff --git a/src/parser/postgresparser.cpp b/src/parser/postgresparser.cpp index 70f509dd9c1..6821565c861 100644 --- a/src/parser/postgresparser.cpp +++ b/src/parser/postgresparser.cpp @@ -1364,8 +1364,6 @@ void PostgresParser::parse_sequence_params(List* options, parser::CreateStatemen DefElem *min_value = NULL; DefElem *cache_value = NULL; DefElem *is_cycled = NULL; - // bool reset_max_value = false; - // bool reset_min_value = false; if(!options) return; ListCell *option; @@ -1387,15 +1385,6 @@ void PostgresParser::parse_sequence_params(List* options, parser::CreateStatemen start_value = defel; result->seq_start = get_long_in_defel(start_value); } - // else if (strcmp(defel->defname, "restart") == 0) - // { - // // if (restart_value) - // // ereport(ERROR, - // // (errcode(ERRCODE_SYNTAX_ERROR), - // // errmsg("conflicting or redundant options"), - // // parser_errposition(pstate, defel->location))); - // restart_value = defel; - // } else if (strcmp(defel->defname, "maxvalue") == 0) { if (max_value) @@ -1434,24 +1423,10 @@ void PostgresParser::parse_sequence_params(List* options, parser::CreateStatemen // // parser_errposition(pstate, defel->location))); // *owned_by = defGetQualifiedName(defel); // } - // else if (strcmp(defel->defname, "sequence_name") == 0) - // { - /* - * The parser allows this, but it is only for identity columns, in - * which case it is filtered out in parse_utilcmd.c. We only get - * here if someone puts it into a CREATE SEQUENCE. - */ - // ereport(ERROR, - // (errcode(ERRCODE_SYNTAX_ERROR), - // errmsg("invalid sequence option SEQUENCE NAME"), - // parser_errposition(pstate, defel->location))); - // } else throw ParserException(StringUtil::Format( "option \"%s\" not recognized\n", defel->defname)); } - - //TODO: support type in sequence } parser::DropStatement *PostgresParser::DropTransform(DropStmt *root) { From 503c89f263dde7830bc3bfaf1690e20deb9b8d30 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 12 Apr 2018 18:06:56 +0000 Subject: [PATCH 12/29] style fix --- src/catalog/sequence_catalog.cpp | 105 ++++++++------- src/include/catalog/sequence_catalog.h | 70 +++++----- src/include/common/exception.h | 8 +- src/include/parser/create_statement.h | 15 ++- src/include/parser/postgresparser.h | 30 +++-- src/include/planner/create_plan.h | 16 ++- src/parser/create_statement.cpp | 3 +- src/parser/postgresparser.cpp | 173 ++++++++++++------------- src/planner/create_plan.cpp | 54 ++++---- test/parser/postgresparser_test.cpp | 28 ++-- test/sequence/sequence_test.cpp | 35 ++--- 11 files changed, 282 insertions(+), 255 deletions(-) diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index 6bd096867b1..ffd9afe661d 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -32,35 +32,35 @@ 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. + * @exception throws SequenceException if the sequence exceeds the upper/lower + * limit. */ int64_t SequenceCatalogObject::get_next_val() { int64_t result = seq_curr_val; - if(seq_increment > 0) { + if (seq_increment > 0) { 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("Sequence exceeds upper limit!")); - } - seq_curr_val = seq_min; + (seq_max < 0 && seq_curr_val + seq_increment > seq_max)) { + if (!seq_cycle) { + throw SequenceException( + StringUtil::Format("Sequence exceeds upper limit!")); } - else + seq_curr_val = seq_min; + } else seq_curr_val += seq_increment; - } - else { + } else { 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("Sequence exceeds lower limit!")); + (seq_min >= 0 && seq_curr_val + seq_increment < seq_min)) { + if (!seq_cycle) { + throw SequenceException( + StringUtil::Format("Sequence exceeds lower limit!")); } seq_curr_val = seq_max; - } - else + } else seq_curr_val += seq_increment; } - // TODO: this will become visible after Mengran's team push the AbstractCatalog::UpdateWithIndexScan. + // TODO: this will become visible after Mengran's team push the + // AbstractCatalog::UpdateWithIndexScan. // Link for the function: // https://github.com/camellyx/peloton/blob/master/src/catalog/abstract_catalog.cpp#L305 @@ -71,13 +71,16 @@ int64_t SequenceCatalogObject::get_next_val() { // scan_values.push_back(type::ValueFactory::GetIntegerValue(seq_oid).Copy()); // oid_t index_offset = IndexId::PRIMARY_KEY; - // bool status = catalog::SequenceCatalog::GetInstance().UpdateWithIndexScan(update_columns, update_values, scan_values, index_offset, txn_); + // bool status = + // catalog::SequenceCatalog::GetInstance().UpdateWithIndexScan(update_columns, + // update_values, scan_values, index_offset, txn_); // LOG_DEBUG("status of update pg_sequence: %d", status); return result; } -SequenceCatalog &SequenceCatalog::GetInstance(concurrency::TransactionContext *txn) { +SequenceCatalog &SequenceCatalog::GetInstance( + concurrency::TransactionContext *txn) { static SequenceCatalog sequence_catalog{txn}; return sequence_catalog; } @@ -113,18 +116,22 @@ SequenceCatalog::~SequenceCatalog() {} * @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. + * @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){ +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()); - if(GetSequence(database_oid, sequence_name, txn) != nullptr) { - throw SequenceException(StringUtil::Format("Insert Sequence with Duplicate Sequence Name: %s", sequence_name.c_str())); + if (GetSequence(database_oid, sequence_name, txn) != nullptr) { + throw SequenceException( + StringUtil::Format("Insert Sequence with Duplicate Sequence Name: %s", + sequence_name.c_str())); } std::unique_ptr tuple( @@ -159,11 +166,12 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, std::string sequence_na * @param database_oid the databse_oid associated with the sequence * @param sequence_name the name of the sequence * @param txn current transaction - * @return ResultType::SUCCESS if the sequence exists, ResultType::FAILURE otherwise. + * @return ResultType::SUCCESS if the sequence exists, ResultType::FAILURE + * otherwise. */ ResultType SequenceCatalog::DropSequence(const std::string &database_name, - const std::string &sequence_name, - concurrency::TransactionContext *txn) { + const std::string &sequence_name, + concurrency::TransactionContext *txn) { if (txn == nullptr) { LOG_TRACE("Do not have transaction to drop sequence: %s", database_name.c_str()); @@ -194,8 +202,9 @@ ResultType SequenceCatalog::DropSequence(const std::string &database_name, * @param txn current transaction * @return The result of DeleteWithIndexScan. */ -bool SequenceCatalog::DeleteSequenceByName(const std::string &sequence_name, oid_t database_oid, - concurrency::TransactionContext *txn) { +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()); @@ -211,12 +220,13 @@ bool SequenceCatalog::DeleteSequenceByName(const std::string &sequence_name, oid * @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){ + oid_t database_oid, const std::string &sequence_name, + concurrency::TransactionContext *txn) { std::vector column_ids( {ColumnId::SEQUENCE_OID, ColumnId::SEQUENCE_NAME, - ColumnId::SEQUENCE_START, ColumnId::SEQUENCE_INC, - ColumnId::SEQUENCE_MAX, ColumnId::SEQUENCE_MIN, - ColumnId::SEQUENCE_CYCLE, ColumnId::SEQUENCE_VALUE}); + 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()); @@ -227,7 +237,8 @@ std::shared_ptr SequenceCatalog::GetSequence( GetResultWithIndexScan(column_ids, index_offset, values, txn); // carefull! 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()); + 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()); @@ -236,8 +247,7 @@ std::shared_ptr SequenceCatalog::GetSequence( PELOTON_ASSERT(result_tiles->size() == 1); size_t tuple_count = (*result_tiles)[0]->GetTupleCount(); PELOTON_ASSERT(tuple_count == 1); - auto new_sequence = - std::make_shared( + auto new_sequence = std::make_shared( (*result_tiles)[0]->GetValue(0, 0).GetAs(), (*result_tiles)[0]->GetValue(0, 1).ToString(), (*result_tiles)[0]->GetValue(0, 2).GetAs(), @@ -250,16 +260,18 @@ std::shared_ptr SequenceCatalog::GetSequence( return new_sequence; } -/* @brief get sequence oid from pg_sequence table given sequence_name and database_oid +/* @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 + * @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 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()); @@ -270,7 +282,8 @@ oid_t SequenceCatalog::GetSequenceOid(std::string sequence_name, oid_t database_ GetResultWithIndexScan(column_ids, index_offset, values, txn); // carefull! 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()); + LOG_INFO("no sequence on database %d and %s", database_oid, + sequence_name.c_str()); return INVALID_OID; } diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h index 8a3bb78c04c..23a5ead0299 100644 --- a/src/include/catalog/sequence_catalog.h +++ b/src/include/catalog/sequence_catalog.h @@ -52,30 +52,31 @@ namespace catalog { class SequenceCatalogObject { public: SequenceCatalogObject(oid_t seqoid, 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), - seq_name(name), - seq_start(seqstart), - seq_increment(seqincrement), - seq_max(seqmax), - seq_min(seqmin), - seq_cycle(seqcycle), - txn_(txn), - seq_curr_val(seqval){}; + 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), + 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; 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 + 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_; - std::mutex sequence_mutex; // mutex for all operations + std::mutex sequence_mutex; // mutex for all operations int64_t GetNextVal() { std::lock_guard lock(sequence_mutex); return get_next_val(); @@ -86,7 +87,9 @@ class SequenceCatalogObject { return seq_curr_val; }; - void SetCurrVal(int64_t curr_val) { seq_curr_val = curr_val; }; // only visible for test! + void SetCurrVal(int64_t curr_val) { + seq_curr_val = curr_val; + }; // only visible for test! void SetCycle(bool cycle) { seq_cycle = cycle; }; private: @@ -94,35 +97,37 @@ class SequenceCatalogObject { int64_t get_next_val(); }; - class SequenceCatalog : public AbstractCatalog { public: ~SequenceCatalog(); // Global Singleton - static SequenceCatalog &GetInstance(concurrency::TransactionContext *txn = nullptr); + static SequenceCatalog &GetInstance( + concurrency::TransactionContext *txn = nullptr); //===--------------------------------------------------------------------===// // 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, + 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); + const std::string &sequence_name, + concurrency::TransactionContext *txn); - bool DeleteSequenceByName(const std::string &sequence_name, oid_t database_oid, - 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 database_oid, const std::string &sequence_name, + concurrency::TransactionContext *txn); oid_t GetSequenceOid(std::string sequence_name, oid_t database_oid, - concurrency::TransactionContext *txn); + concurrency::TransactionContext *txn); enum ColumnId { SEQUENCE_OID = 0, @@ -141,10 +146,7 @@ class SequenceCatalog : public AbstractCatalog { oid_t GetNextOid() { return oid_++ | SEQUENCE_OID_MASK; } - enum IndexId { - PRIMARY_KEY = 0, - DBOID_SEQNAME_KEY = 1 - }; + enum IndexId { PRIMARY_KEY = 0, DBOID_SEQNAME_KEY = 1 }; }; } // namespace catalog diff --git a/src/include/common/exception.h b/src/include/common/exception.h index 9688f902c19..d8e82565da1 100644 --- a/src/include/common/exception.h +++ b/src/include/common/exception.h @@ -59,8 +59,8 @@ enum class ExceptionType { SETTINGS = 23, // settings related BINDER = 24, // binder related NETWORK = 25, // network related - OPTIMIZER = 26, // optimizer related - SEQUENCE = 27 // sequence related + OPTIMIZER = 26, // optimizer related + SEQUENCE = 27 // sequence related }; class Exception : public std::runtime_error { @@ -77,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) { diff --git a/src/include/parser/create_statement.h b/src/include/parser/create_statement.h index 5d1cbd1e548..1b9dce7d88e 100644 --- a/src/include/parser/create_statement.h +++ b/src/include/parser/create_statement.h @@ -217,7 +217,15 @@ struct ColumnDefinition { */ class CreateStatement : public TableRefStatement { public: - enum CreateType { kTable, kDatabase, kIndex, kTrigger, kSchema, kView, kSequence }; + enum CreateType { + kTable, + kDatabase, + kIndex, + kTrigger, + kSchema, + kView, + kSequence + }; CreateStatement(CreateType type) : TableRefStatement(StatementType::CREATE), @@ -259,12 +267,13 @@ class CreateStatement : public TableRefStatement { // attributes related to sequences std::string sequence_name; - std::unique_ptr table; // deal with RangeVar + std::unique_ptr table; // deal with RangeVar int64_t seq_start = 1; int64_t seq_increment = 1; int64_t seq_max_value = LONG_MAX; int64_t seq_min_value = 1; - int64_t seq_cache; // sequence cache size, probably won't be supported in this project + int64_t seq_cache; // sequence cache size, probably won't be supported in + // this project bool seq_cycle = false; }; diff --git a/src/include/parser/postgresparser.h b/src/include/parser/postgresparser.h index fc103caac9a..3827dcf52d1 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); @@ -210,8 +212,8 @@ class PostgresParser { // 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); @@ -235,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); @@ -284,17 +286,19 @@ 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 parse_sequence_params(List* options, parser::CreateStatement* result); + static void parse_sequence_params(List *options, + parser::CreateStatement *result); - static int64_t get_long_in_defel(DefElem* defel){ - return (int64_t) ((reinterpret_cast(defel->arg))->val.ival); + static int64_t get_long_in_defel(DefElem *defel) { + return (int64_t)((reinterpret_cast(defel->arg))->val.ival); }; }; diff --git a/src/include/planner/create_plan.h b/src/include/planner/create_plan.h index e784017d0ec..20973b4a1d7 100644 --- a/src/include/planner/create_plan.h +++ b/src/include/planner/create_plan.h @@ -86,7 +86,9 @@ class CreatePlan : public AbstractPlan { std::vector GetIndexAttributes() const { return index_attrs; } - inline std::vector GetForeignKeys() const { return foreign_keys; } + inline std::vector GetForeignKeys() const { + return foreign_keys; + } std::vector GetKeyAttrs() const { return key_attrs; } void SetKeyAttrs(std::vector p_key_attrs) { key_attrs = p_key_attrs; } @@ -116,11 +118,11 @@ class CreatePlan : public AbstractPlan { int64_t GetSequenceCacheSize() const { return seq_cache; } bool GetSequenceCycle() const { return seq_cycle; } -protected: - // This is a helper method for extracting foreign key information - // and storing it in an internal struct. - void ProcessForeignKeyConstraint(const std::string &table_name, - const parser::ColumnDefinition *col); + protected: + // This is a helper method for extracting foreign key information + // and storing it in an internal struct. + void ProcessForeignKeyConstraint(const std::string &table_name, + const parser::ColumnDefinition *col); private: // Table Name @@ -164,7 +166,7 @@ class CreatePlan : public AbstractPlan { int64_t seq_increment; int64_t seq_max_value; int64_t seq_min_value; - int64_t seq_cache; // sequence cache size, not supported yet + int64_t seq_cache; // sequence cache size, not supported yet bool seq_cycle; private: diff --git a/src/parser/create_statement.cpp b/src/parser/create_statement.cpp index 7547f704f0a..c150ed4d855 100644 --- a/src/parser/create_statement.cpp +++ b/src/parser/create_statement.cpp @@ -28,7 +28,8 @@ const std::string CreateStatement::GetInfo(int num_indent) const { << StringUtil::Format("IF NOT EXISTS: %s", (if_not_exists) ? "True" : "False") << std::endl; os << StringUtil::Indent(num_indent + 1) - << StringUtil::Format("Table name: %s", GetTableName().c_str());; + << StringUtil::Format("Table name: %s", GetTableName().c_str()); + ; break; } case CreateStatement::CreateType::kDatabase: { diff --git a/src/parser/postgresparser.cpp b/src/parser/postgresparser.cpp index 6821565c861..c407d68c3c3 100644 --- a/src/parser/postgresparser.cpp +++ b/src/parser/postgresparser.cpp @@ -286,12 +286,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; } @@ -490,9 +488,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))); @@ -558,8 +555,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) { @@ -865,9 +862,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 = @@ -1055,9 +1051,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 @@ -1346,87 +1341,83 @@ parser::SQLStatement *PostgresParser::CreateViewTransform(ViewStmt *root) { return result; } -parser::SQLStatement *PostgresParser::CreateSequenceTransform(CreateSeqStmt *root){ +parser::SQLStatement *PostgresParser::CreateSequenceTransform( + CreateSeqStmt *root) { parser::CreateStatement *result = new parser::CreateStatement(CreateStatement::kSequence); result->sequence_name = std::string(root->sequence->relname); result->table.reset( - RangeVarTransform(reinterpret_cast(root->sequence))); + RangeVarTransform(reinterpret_cast(root->sequence))); parse_sequence_params(root->options, result); return result; } -void PostgresParser::parse_sequence_params(List* options, parser::CreateStatement* result){ - DefElem *start_value = NULL; - // DefElem *restart_value = NULL; - DefElem *increment_by = NULL; - DefElem *max_value = NULL; - DefElem *min_value = NULL; - DefElem *cache_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; +void PostgresParser::parse_sequence_params(List *options, + parser::CreateStatement *result) { + DefElem *start_value = NULL; + // DefElem *restart_value = NULL; + DefElem *increment_by = NULL; + DefElem *max_value = NULL; + DefElem *min_value = NULL; + DefElem *cache_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 = get_long_in_defel(increment_by); - } - else if (strcmp(defel->defname, "start") == 0) - { - if (start_value) - throw ParserException("Redundant definition of start in defining sequence"); - start_value = defel; + } 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 = get_long_in_defel(start_value); - } - else if (strcmp(defel->defname, "maxvalue") == 0) - { - if (max_value) - throw ParserException("Redundant definition of max in defining sequence"); - max_value = defel; + } 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 = get_long_in_defel(max_value); - } - else if (strcmp(defel->defname, "minvalue") == 0) - { - if (min_value) - throw ParserException("Redundant definition of min in defining sequence"); - min_value = defel; + } 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 = get_long_in_defel(min_value); - } - else if (strcmp(defel->defname, "cache") == 0) - { - if (cache_value) - throw ParserException("Redundant definition of cache in defining sequence"); - cache_value = defel; + } else if (strcmp(defel->defname, "cache") == 0) { + if (cache_value) + throw ParserException( + "Redundant definition of cache in defining sequence"); + cache_value = defel; result->seq_cache = get_long_in_defel(cache_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) get_long_in_defel(is_cycled); - } + } 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)get_long_in_defel(is_cycled); + } // TODO: support owned_by - // else if (strcmp(defel->defname, "owned_by") == 0) - // { - // // if (*owned_by) - // // ereport(ERROR, - // // (errcode(ERRCODE_SYNTAX_ERROR), - // // errmsg("conflicting or redundant options"), - // // parser_errposition(pstate, defel->location))); - // *owned_by = defGetQualifiedName(defel); - // } - else - throw ParserException(StringUtil::Format( - "option \"%s\" not recognized\n", defel->defname)); - } + // else if (strcmp(defel->defname, "owned_by") == 0) + // { + // // if (*owned_by) + // // ereport(ERROR, + // // (errcode(ERRCODE_SYNTAX_ERROR), + // // errmsg("conflicting or redundant options"), + // // parser_errposition(pstate, defel->location))); + // *owned_by = defGetQualifiedName(defel); + // } + else + throw ParserException( + StringUtil::Format("option \"%s\" not recognized\n", defel->defname)); + } } parser::DropStatement *PostgresParser::DropTransform(DropStmt *root) { @@ -1598,8 +1589,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>>(); @@ -1710,8 +1701,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) { @@ -1847,7 +1838,7 @@ parser::SQLStatement *PostgresParser::NodeTransform(Node *stmt) { CreateSchemaTransform(reinterpret_cast(stmt)); break; case T_CreateSeqStmt: - result = CreateSequenceTransform(reinterpret_cast (stmt)); + result = CreateSequenceTransform(reinterpret_cast(stmt)); break; case T_ViewStmt: result = CreateViewTransform(reinterpret_cast(stmt)); @@ -1929,8 +1920,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(); diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index a612c028820..bab9553f68f 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -21,8 +21,7 @@ namespace peloton { namespace planner { CreatePlan::CreatePlan(std::string database_name, CreateType c_type) - : database_name(database_name), - create_type(c_type) {} + : database_name(database_name), create_type(c_type) {} CreatePlan::CreatePlan(std::string table_name, std::string database_name, std::unique_ptr schema, @@ -32,8 +31,7 @@ CreatePlan::CreatePlan(std::string table_name, std::string database_name, table_schema(schema.release()), create_type(c_type) {} -CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) -{ +CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { switch (parse_tree->type) { case parser::CreateStatement::CreateType::kDatabase: { create_type = CreateType::DB; @@ -57,25 +55,31 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) for (auto &col : parse_tree->columns) { type::TypeId val = col->GetValueType(col->type); - LOG_TRACE("Column name: %s.%s; Is primary key: %d", table_name.c_str(), col->name.c_str(), col->primary); + LOG_TRACE("Column name: %s.%s; Is primary key: %d", table_name.c_str(), + col->name.c_str(), col->primary); // Check main constraints if (col->primary) { - catalog::Constraint constraint(ConstraintType::PRIMARY, "con_primary"); + catalog::Constraint constraint(ConstraintType::PRIMARY, + "con_primary"); column_constraints.push_back(constraint); - LOG_TRACE("Added a primary key constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); + LOG_TRACE("Added a primary key constraint on column \"%s.%s\"", + table_name.c_str(), col->name.c_str()); } if (col->not_null) { - catalog::Constraint constraint(ConstraintType::NOTNULL, "con_not_null"); + catalog::Constraint constraint(ConstraintType::NOTNULL, + "con_not_null"); column_constraints.push_back(constraint); - LOG_TRACE("Added a not-null constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); + LOG_TRACE("Added a not-null constraint on column \"%s.%s\"", + table_name.c_str(), col->name.c_str()); } if (col->unique) { catalog::Constraint constraint(ConstraintType::UNIQUE, "con_unique"); column_constraints.push_back(constraint); - LOG_TRACE("Added a unique constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); + LOG_TRACE("Added a unique constraint on column \"%s.%s\"", + table_name.c_str(), col->name.c_str()); } /* **************** */ @@ -83,16 +87,20 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) // Add the default value if (col->default_value != nullptr) { // Referenced from insert_plan.cpp - if (col->default_value->GetExpressionType() != ExpressionType::VALUE_PARAMETER) { + if (col->default_value->GetExpressionType() != + ExpressionType::VALUE_PARAMETER) { expression::ConstantValueExpression *const_expr_elem = - dynamic_cast(col->default_value.get()); + dynamic_cast( + col->default_value.get()); - catalog::Constraint constraint(ConstraintType::DEFAULT, "con_default"); + catalog::Constraint constraint(ConstraintType::DEFAULT, + "con_default"); type::Value v = const_expr_elem->GetValue(); constraint.addDefaultValue(v); column_constraints.push_back(constraint); LOG_TRACE("Added a default constraint %s on column \"%s.%s\"", - v.ToString().c_str(), table_name.c_str(), col->name.c_str()); + v.ToString().c_str(), table_name.c_str(), + col->name.c_str()); } } @@ -104,10 +112,13 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) catalog::Constraint constraint(ConstraintType::CHECK, "con_check"); const expression::ConstantValueExpression *const_expr_elem = - dynamic_cast(col->check_expression->GetChild(1)); + dynamic_cast( + col->check_expression->GetChild(1)); type::Value tmp_value = const_expr_elem->GetValue(); - constraint.AddCheck(std::move(col->check_expression->GetExpressionType()), std::move(tmp_value)); + constraint.AddCheck( + std::move(col->check_expression->GetExpressionType()), + std::move(tmp_value)); column_constraints.push_back(constraint); LOG_TRACE("Added a check constraint on column \"%s.%s\"", table_name.c_str(), col->name.c_str()); @@ -196,23 +207,22 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) } default: LOG_ERROR("UNKNOWN CREATE TYPE"); - //TODO Should we handle this here? + // TODO Should we handle this here? break; } // TODO check type CreateType::kDatabase } -void CreatePlan::ProcessForeignKeyConstraint(const std::string &table_name, - const parser::ColumnDefinition *col) { - +void CreatePlan::ProcessForeignKeyConstraint( + const std::string &table_name, const parser::ColumnDefinition *col) { ForeignKeyInfo fkey_info; // Extract source and sink column names - for (auto& key : col->foreign_key_source) { + for (auto &key : col->foreign_key_source) { fkey_info.foreign_key_sources.push_back(key); } - for (auto& key : col->foreign_key_sink) { + for (auto &key : col->foreign_key_sink) { fkey_info.foreign_key_sinks.push_back(key); } diff --git a/test/parser/postgresparser_test.cpp b/test/parser/postgresparser_test.cpp index 549924ffad5..5e4740cd783 100644 --- a/test/parser/postgresparser_test.cpp +++ b/test/parser/postgresparser_test.cpp @@ -588,8 +588,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 +1020,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)); @@ -1096,16 +1093,11 @@ TEST_F(PostgresParserTests, CreateSequenceTest) { // 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); + 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, FuncCallTest) { diff --git a/test/sequence/sequence_test.cpp b/test/sequence/sequence_test.cpp index 9010dfd69f7..3f9dda1611d 100644 --- a/test/sequence/sequence_test.cpp +++ b/test/sequence/sequence_test.cpp @@ -34,16 +34,21 @@ class SequenceTests : public PelotonTest { txn_manager.CommitTransaction(txn); } - std::shared_ptr GetSequenceHelper(std::string sequence_name, concurrency::TransactionContext *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(); + oid_t database_oid = catalog::Catalog::GetInstance() + ->GetDatabaseWithName(DEFAULT_DB_NAME, txn) + ->GetOid(); std::shared_ptr new_sequence = - catalog::SequenceCatalog::GetInstance().GetSequence(database_oid, sequence_name, txn); + catalog::SequenceCatalog::GetInstance().GetSequence(database_oid, + sequence_name, txn); return new_sequence; } - void CreateSequenceHelper(std::string query, concurrency::TransactionContext *txn) { + void CreateSequenceHelper(std::string query, + concurrency::TransactionContext *txn) { auto parser = parser::PostgresParser::GetInstance(); std::unique_ptr stmt_list( @@ -83,7 +88,8 @@ TEST_F(SequenceTests, BasicTest) { std::string name = "seq"; CreateSequenceHelper(query, txn); - std::shared_ptr new_sequence = GetSequenceHelper(name, txn); + std::shared_ptr new_sequence = + GetSequenceHelper(name, txn); EXPECT_EQ(name, new_sequence->seq_name); EXPECT_EQ(2, new_sequence->seq_increment); @@ -114,9 +120,9 @@ TEST_F(SequenceTests, NoDuplicateTest) { try { CreateSequenceHelper(query, txn); EXPECT_EQ(0, 1); - } - catch(const SequenceException& expected) { - ASSERT_STREQ("Insert Sequence with Duplicate Sequence Name: seq", expected.what()); + } catch (const SequenceException &expected) { + ASSERT_STREQ("Insert Sequence with Duplicate Sequence Name: seq", + expected.what()); } txn_manager.CommitTransaction(txn); } @@ -133,7 +139,8 @@ TEST_F(SequenceTests, NextValPosIncrementFunctionalityTest) { std::string name = "seq1"; CreateSequenceHelper(query, txn); - std::shared_ptr new_sequence = GetSequenceHelper(name, txn); + std::shared_ptr new_sequence = + GetSequenceHelper(name, txn); int64_t nextVal = new_sequence->GetNextVal(); EXPECT_EQ(10, nextVal); @@ -154,8 +161,7 @@ TEST_F(SequenceTests, NextValPosIncrementFunctionalityTest) { try { nextVal = new_sequence->GetNextVal(); EXPECT_EQ(0, 1); - } - catch(const SequenceException& expected) { + } catch (const SequenceException &expected) { ASSERT_STREQ("Sequence exceeds upper limit!", expected.what()); } txn_manager.CommitTransaction(txn); @@ -173,7 +179,8 @@ TEST_F(SequenceTests, NextValNegIncrementFunctionalityTest) { std::string name = "seq2"; CreateSequenceHelper(query, txn); - std::shared_ptr new_sequence = GetSequenceHelper(name, txn); + std::shared_ptr new_sequence = + GetSequenceHelper(name, txn); // test cycle int64_t nextVal = new_sequence->GetNextVal(); @@ -194,12 +201,10 @@ TEST_F(SequenceTests, NextValNegIncrementFunctionalityTest) { try { nextVal = new_sequence->GetNextVal(); EXPECT_EQ(0, 1); - } - catch(const SequenceException& expected) { + } catch (const SequenceException &expected) { ASSERT_STREQ("Sequence exceeds lower limit!", expected.what()); } txn_manager.CommitTransaction(txn); } - } } From 77623542fcc593b227ae4b9862836690a62b2e24 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Thu, 12 Apr 2018 14:19:32 -0400 Subject: [PATCH 13/29] rename sequence test --- .../sequence_test.cpp => catalog/sequence_catalog_test.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{sequence/sequence_test.cpp => catalog/sequence_catalog_test.cpp} (100%) diff --git a/test/sequence/sequence_test.cpp b/test/catalog/sequence_catalog_test.cpp similarity index 100% rename from test/sequence/sequence_test.cpp rename to test/catalog/sequence_catalog_test.cpp From 689756691df40816fff22a1a39f24d693b33f5e1 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Thu, 12 Apr 2018 14:24:18 -0400 Subject: [PATCH 14/29] remove unnecessary file --- sequence_test.sql | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 sequence_test.sql diff --git a/sequence_test.sql b/sequence_test.sql deleted file mode 100644 index 7f43710c01b..00000000000 --- a/sequence_test.sql +++ /dev/null @@ -1,4 +0,0 @@ --- psql "sslmode=disable" -U postgres -h localhost -p 15721 -\c test; --- currently not support AS, CACHE and OWNED BY. -CREATE SEQUENCE seq INCREMENT BY 2 MINVALUE 10 MAXVALUE 50 START 10 CYCLE; From b8c7317588c9e141ba2502e026cb380d4041414b Mon Sep 17 00:00:00 2001 From: Peixin Sun Date: Sat, 14 Apr 2018 17:59:53 -0400 Subject: [PATCH 15/29] adding nextval & currval functions; comment out lock and nextval not functioning well --- src/catalog/catalog.cpp | 15 ++++++ src/codegen/proxy/string_functions_proxy.cpp | 4 ++ src/codegen/type/varchar_type.cpp | 46 ++++++++++++++++++- src/executor/executor_context.cpp | 13 +++++- src/executor/plan_executor.cpp | 24 ++++++---- src/expression/function_expression.cpp | 4 +- src/function/old_engine_string_functions.cpp | 13 ++++++ src/function/string_functions.cpp | 34 ++++++++++++++ src/include/catalog/sequence_catalog.h | 4 +- .../codegen/proxy/string_functions_proxy.h | 4 ++ src/include/common/internal_types.h | 2 + src/include/executor/executor_context.h | 7 ++- src/include/executor/plan_executor.h | 3 +- .../function/old_engine_string_functions.h | 4 ++ src/include/function/string_functions.h | 6 +++ src/traffic_cop/traffic_cop.cpp | 5 +- 16 files changed, 169 insertions(+), 19 deletions(-) diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 45a02ba6cfc..856377b9f8d 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -30,6 +30,7 @@ #include "function/date_functions.h" #include "function/decimal_functions.h" #include "function/old_engine_string_functions.h" +#include "function/string_functions.h" #include "function/timestamp_functions.h" #include "index/index_factory.h" #include "settings/settings_manager.h" @@ -1062,6 +1063,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::OldEngineStringFunctions::Nextval}, + txn); + AddBuiltinFunction( + "currval", {type::TypeId::VARCHAR}, type::TypeId::INTEGER, + internal_lang, "Currval", + function::BuiltInFuncType{OperatorId::Currval, + function::OldEngineStringFunctions::Currval}, + txn); + /** * decimal functions diff --git a/src/codegen/proxy/string_functions_proxy.cpp b/src/codegen/proxy/string_functions_proxy.cpp index 46a356b61dd..d8786cc5b29 100644 --- a/src/codegen/proxy/string_functions_proxy.cpp +++ b/src/codegen/proxy/string_functions_proxy.cpp @@ -33,5 +33,9 @@ DEFINE_METHOD(peloton::function, StringFunctions, Trim); DEFINE_METHOD(peloton::function, StringFunctions, LTrim); DEFINE_METHOD(peloton::function, StringFunctions, RTrim); +// Sequence-related functions +DEFINE_METHOD(peloton::function, StringFunctions, Nextval); +DEFINE_METHOD(peloton::function, StringFunctions, Currval); + } // namespace codegen } // namespace peloton diff --git a/src/codegen/type/varchar_type.cpp b/src/codegen/type/varchar_type.cpp index 0066457e425..52716c60d66 100644 --- a/src/codegen/type/varchar_type.cpp +++ b/src/codegen/type/varchar_type.cpp @@ -187,6 +187,46 @@ struct Trim : public TypeSystem::UnaryOperatorHandleNull { } }; +// 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 Integer::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(StringFunctionsProxy::Nextval, + {executor_ctx, val.GetValue()}); + return Value{Integer::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 Integer::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(StringFunctionsProxy::Currval, + {executor_ctx, val.GetValue()}); + return Value{Integer::Instance(), raw_ret}; + } +}; + //////////////////////////////////////////////////////////////////////////////// /// /// Binary operators @@ -536,10 +576,14 @@ std::vector kComparisonTable = {{kCompareVarchar}}; Ascii kAscii; Length kLength; Trim kTrim; +Nextval kNextval; +Currval kCurrval; std::vector kUnaryOperatorTable = { {OperatorId::Ascii, kAscii}, {OperatorId::Length, kLength}, - {OperatorId::Trim, kTrim}}; + {OperatorId::Trim, kTrim}, + {OperatorId::Nextval, kNextval}, + {OperatorId::Currval, kCurrval}}; // Binary operations Like kLike; diff --git a/src/executor/executor_context.cpp b/src/executor/executor_context.cpp index ae9281c13fe..72071dccfa9 100644 --- a/src/executor/executor_context.cpp +++ b/src/executor/executor_context.cpp @@ -16,12 +16,17 @@ #include "executor/executor_context.h" #include "concurrency/transaction_context.h" + 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) { + LOG_DEBUG("ExecutorContext default db name: %s", default_database_name.c_str()); +} concurrency::TransactionContext *ExecutorContext::GetTransaction() const { return transaction_; @@ -43,5 +48,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..414aa703603 100644 --- a/src/executor/plan_executor.cpp +++ b/src/executor/plan_executor.cpp @@ -36,9 +36,10 @@ 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 ..."); + LOG_DEBUG("CompileAndExecutePlan default db name: %s", default_database_name.c_str()); // Perform binding planner::BindingContext context; @@ -51,7 +52,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 +89,14 @@ 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; + LOG_DEBUG("InterpretPlan default db name: %s", default_database_name.c_str()); 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,19 +146,20 @@ 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()); + LOG_DEBUG("PlanExecutor 1 default db name: %s", default_database_name.c_str()); bool codegen_enabled = settings::SettingsManager::GetBool(settings::SettingId::codegen); 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; @@ -181,6 +186,7 @@ int PlanExecutor::ExecutePlan( std::vector> &logical_tile_list) { PELOTON_ASSERT(plan != nullptr); LOG_TRACE("PlanExecutor Start with transaction"); + LOG_DEBUG("PlanExecutor 2"); auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); diff --git a/src/expression/function_expression.cpp b/src/expression/function_expression.cpp index 9f74f30e475..1ab6d28af31 100644 --- a/src/expression/function_expression.cpp +++ b/src/expression/function_expression.cpp @@ -42,13 +42,15 @@ 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)); } + 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..96fe5a30e35 100644 --- a/src/function/old_engine_string_functions.cpp +++ b/src/function/old_engine_string_functions.cpp @@ -235,5 +235,18 @@ type::Value OldEngineStringFunctions::Lower( throw Exception{"Lower not implemented in old engine"}; } +type::Value OldEngineStringFunctions::Nextval( + UNUSED_ATTRIBUTE const std::vector &args) { + executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); + uint32_t ret = StringFunctions::Nextval(*ctx, args[0].GetAs()); + return type::ValueFactory::GetIntegerValue(ret); +} + +type::Value OldEngineStringFunctions::Currval( + UNUSED_ATTRIBUTE const std::vector &args) { + executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); + uint32_t ret = StringFunctions::Currval(*ctx, args[0].GetAs()); + return type::ValueFactory::GetIntegerValue(ret); +} } // namespace function } // namespace peloton diff --git a/src/function/string_functions.cpp b/src/function/string_functions.cpp index 841a9ee6e15..5b739bcd40f 100644 --- a/src/function/string_functions.cpp +++ b/src/function/string_functions.cpp @@ -14,6 +14,9 @@ #include "common/macros.h" #include "executor/executor_context.h" +#include "catalog/catalog.h" +#include "catalog/database_catalog.h" +#include "catalog/sequence_catalog.h" namespace peloton { namespace function { @@ -220,5 +223,36 @@ uint32_t StringFunctions::Length( return length; } +uint32_t StringFunctions::Nextval(executor::ExecutorContext &ctx, const char *sequence_name) { + PELOTON_ASSERT(sequence_name != nullptr); + auto database_object = + catalog::Catalog::GetInstance() + ->GetDatabaseObject(ctx.GetDatabaseName(), ctx.GetTransaction()); + catalog::SequenceCatalogObject* sequence_object = catalog::SequenceCatalog::GetInstance(). + GetSequence(database_object->GetDatabaseOid(), sequence_name, ctx.GetTransaction()).get(); + if (sequence_object != nullptr) { + return sequence_object->GetNextVal(); + } else { + throw SequenceException( + StringUtil::Format("Sequence not exists!")); + } +} + + +uint32_t StringFunctions::Currval(executor::ExecutorContext &ctx, const char *sequence_name) { + PELOTON_ASSERT(sequence_name != nullptr); + auto database_object = + catalog::Catalog::GetInstance() + ->GetDatabaseObject(ctx.GetDatabaseName(), ctx.GetTransaction()); + catalog::SequenceCatalogObject* sequence_object = catalog::SequenceCatalog::GetInstance(). + GetSequence(database_object->GetDatabaseOid(), sequence_name, ctx.GetTransaction()).get(); + if (sequence_object != nullptr) { + return sequence_object->GetCurrVal(); + } else { + throw SequenceException( + StringUtil::Format("Sequence not exists!")); + } +} + } // namespace function } // namespace peloton diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h index 23a5ead0299..25d07ae0f3a 100644 --- a/src/include/catalog/sequence_catalog.h +++ b/src/include/catalog/sequence_catalog.h @@ -78,12 +78,12 @@ class SequenceCatalogObject { std::mutex sequence_mutex; // mutex for all operations int64_t GetNextVal() { - std::lock_guard lock(sequence_mutex); + //std::lock_guard lock(sequence_mutex); return get_next_val(); }; int64_t GetCurrVal() { - std::lock_guard lock(sequence_mutex); + //std::lock_guard lock(sequence_mutex); return seq_curr_val; }; diff --git a/src/include/codegen/proxy/string_functions_proxy.h b/src/include/codegen/proxy/string_functions_proxy.h index 1862db23db9..5868229e13b 100644 --- a/src/include/codegen/proxy/string_functions_proxy.h +++ b/src/include/codegen/proxy/string_functions_proxy.h @@ -31,6 +31,10 @@ PROXY(StringFunctions) { DECLARE_METHOD(RTrim); DECLARE_METHOD(Substr); DECLARE_METHOD(Repeat); + + // Sequence-related functions + DECLARE_METHOD(Nextval); + DECLARE_METHOD(Currval); }; PROXY(StrWithLen) { diff --git a/src/include/common/internal_types.h b/src/include/common/internal_types.h index 05bc389ee3e..4ffad744001 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -1091,6 +1091,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/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..c02e3e32581 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..f8748e9ae76 100644 --- a/src/include/function/old_engine_string_functions.h +++ b/src/include/function/old_engine_string_functions.h @@ -68,6 +68,10 @@ class OldEngineStringFunctions { // Upper, Lower static type::Value Upper(const std::vector &args); static type::Value Lower(const std::vector &args); + + // Sequence-related + static type::Value Nextval(const std::vector &args); + static type::Value Currval(const std::vector &args); }; } // namespace function diff --git a/src/include/function/string_functions.h b/src/include/function/string_functions.h index 2a209d0dee6..1d41551cef1 100644 --- a/src/include/function/string_functions.h +++ b/src/include/function/string_functions.h @@ -74,6 +74,12 @@ class StringFunctions { // Length will return the number of characters in the given string static uint32_t Length(executor::ExecutorContext &ctx, const char *str, uint32_t length); + + // 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); }; } // namespace function diff --git a/src/traffic_cop/traffic_cop.cpp b/src/traffic_cop/traffic_cop.cpp index fd29c7966b2..a3cbd34b009 100644 --- a/src/traffic_cop/traffic_cop.cpp +++ b/src/traffic_cop/traffic_cop.cpp @@ -191,9 +191,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; From d665c94cb38e0bb315169e00b020447c7ae8b3aa Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Mon, 16 Apr 2018 11:04:41 -0400 Subject: [PATCH 16/29] update pg_sequence after calling nextval; have seg fault in txn; --- src/catalog/abstract_catalog.cpp | 66 ++++++++++++++++++++++++++ src/catalog/sequence_catalog.cpp | 26 +++++----- src/include/catalog/abstract_catalog.h | 5 ++ src/include/catalog/sequence_catalog.h | 11 +++-- 4 files changed, 92 insertions(+), 16 deletions(-) diff --git a/src/catalog/abstract_catalog.cpp b/src/catalog/abstract_catalog.cpp index 98879a0d36c..5894941a37e 100644 --- a/src/catalog/abstract_catalog.cpp +++ b/src/catalog/abstract_catalog.cpp @@ -32,6 +32,8 @@ #include "executor/index_scan_executor.h" #include "executor/insert_executor.h" #include "executor/seq_scan_executor.h" +#include "executor/update_executor.h" +#include "executor/plan_executor.h" #include "storage/database.h" #include "storage/storage_manager.h" @@ -272,5 +274,69 @@ void AbstractCatalog::AddIndex(const std::vector &key_attrs, index_name.c_str(), (int)catalog_table_->GetOid()); } +/*@brief Update specific columns using index scan + * @param update_columns Columns to be updated + * @param update_values Values to be updated + * @param scan_values Value to be scaned (used in index scan) + * @param index_offset Offset of index for scan + * @return true if successfully executes + */ +bool AbstractCatalog::UpdateWithIndexScan( + std::vector update_columns, std::vector update_values, + std::vector scan_values, oid_t index_offset, + concurrency::TransactionContext *txn) { + if (txn == nullptr) throw CatalogException("Scan table requires transaction"); + + std::unique_ptr context( + new executor::ExecutorContext(txn)); + // Construct index scan executor + auto index = catalog_table_->GetIndex(index_offset); + std::vector key_column_offsets = + index->GetMetadata()->GetKeySchema()->GetIndexedColumns(); + PELOTON_ASSERT(scan_values.size() == key_column_offsets.size()); + std::vector expr_types(scan_values.size(), + ExpressionType::COMPARE_EQUAL); + std::vector runtime_keys; + + planner::IndexScanPlan::IndexScanDesc index_scan_desc( + index, key_column_offsets, expr_types, scan_values, runtime_keys); + + planner::IndexScanPlan index_scan_node(catalog_table_, nullptr, + update_columns, index_scan_desc); + + executor::IndexScanExecutor index_scan_executor(&index_scan_node, + context.get()); + // Construct update executor + TargetList target_list; + DirectMapList direct_map_list; + + size_t column_count = catalog_table_->GetSchema()->GetColumnCount(); + for (size_t col_itr = 0; col_itr < column_count; col_itr++) { + // Skip any column for update + if (std::find(std::begin(update_columns), std::end(update_columns), + col_itr) == std::end(update_columns)) { + direct_map_list.emplace_back(col_itr, std::make_pair(0, col_itr)); + } + } + + PELOTON_ASSERT(update_columns.size() == update_values.size()); + for (size_t i = 0; i < update_values.size(); i++) { + planner::DerivedAttribute update_attribute{ + new expression::ConstantValueExpression(update_values[i])}; + target_list.emplace_back(update_columns[i], update_attribute); + } + + std::unique_ptr project_info( + new planner::ProjectInfo(std::move(target_list), + std::move(direct_map_list))); + planner::UpdatePlan update_node(catalog_table_, std::move(project_info)); + + executor::UpdateExecutor update_executor(&update_node, context.get()); + update_executor.AddChild(&index_scan_executor); + // Execute + update_executor.Init(); + return update_executor.Execute(); +} + } // namespace catalog } // namespace peloton diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index ffd9afe661d..43ae067c6d6 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -63,18 +63,8 @@ int64_t SequenceCatalogObject::get_next_val() { // AbstractCatalog::UpdateWithIndexScan. // Link for the function: // https://github.com/camellyx/peloton/blob/master/src/catalog/abstract_catalog.cpp#L305 - - // std::vector update_columns({ColumnId::SEQUENCE_VALUE}); - // std::vector update_values; - // update_values.push_back(type::ValueFactory::GetBigIntValue(seq_curr_val).Copy()); - // std::vector scan_values; - // scan_values.push_back(type::ValueFactory::GetIntegerValue(seq_oid).Copy()); - // oid_t index_offset = IndexId::PRIMARY_KEY; - - // bool status = - // catalog::SequenceCatalog::GetInstance().UpdateWithIndexScan(update_columns, - // update_values, scan_values, index_offset, txn_); - // LOG_DEBUG("status of update pg_sequence: %d", status); + bool status = catalog::SequenceCatalog::GetInstance().UpdateNextVal(seq_oid, seq_curr_val, txn_); + LOG_DEBUG("status of update pg_sequence: %d", status); return result; } @@ -260,6 +250,18 @@ std::shared_ptr SequenceCatalog::GetSequence( return new_sequence; } +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 diff --git a/src/include/catalog/abstract_catalog.h b/src/include/catalog/abstract_catalog.h index 9acf67773b9..bf62b62e2d4 100644 --- a/src/include/catalog/abstract_catalog.h +++ b/src/include/catalog/abstract_catalog.h @@ -72,6 +72,11 @@ class AbstractCatalog { expression::AbstractExpression *predicate, concurrency::TransactionContext *txn); + bool UpdateWithIndexScan( + std::vector update_columns, std::vector update_values, + std::vector scan_values, oid_t index_offset, + concurrency::TransactionContext *txn); + void AddIndex(const std::vector &key_attrs, oid_t index_oid, const std::string &index_name, IndexConstraintType index_constraint); diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h index 25d07ae0f3a..9b26a647647 100644 --- a/src/include/catalog/sequence_catalog.h +++ b/src/include/catalog/sequence_catalog.h @@ -78,12 +78,12 @@ class SequenceCatalogObject { std::mutex sequence_mutex; // mutex for all operations int64_t GetNextVal() { - //std::lock_guard lock(sequence_mutex); + std::lock_guard lock(sequence_mutex); return get_next_val(); }; int64_t GetCurrVal() { - //std::lock_guard lock(sequence_mutex); + std::lock_guard lock(sequence_mutex); return seq_curr_val; }; @@ -129,6 +129,9 @@ class SequenceCatalog : public AbstractCatalog { 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, @@ -141,12 +144,12 @@ class SequenceCatalog : public AbstractCatalog { SEQUENCE_VALUE = 8 }; + enum IndexId { PRIMARY_KEY = 0, DBOID_SEQNAME_KEY = 1 }; + private: SequenceCatalog(concurrency::TransactionContext *txn); oid_t GetNextOid() { return oid_++ | SEQUENCE_OID_MASK; } - - enum IndexId { PRIMARY_KEY = 0, DBOID_SEQNAME_KEY = 1 }; }; } // namespace catalog From e71a21c326174da37f01926032d38b50dab6d910 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Sun, 22 Apr 2018 20:07:07 -0400 Subject: [PATCH 17/29] temporary add code from other team --- src/catalog/sequence_catalog.cpp | 2 +- src/executor/create_executor.cpp | 1 - src/include/catalog/sequence_catalog.h | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index 43ae067c6d6..c56d1d755f6 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -120,7 +120,7 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, LOG_DEBUG("Insert Sequence Sequence Name: %s", sequence_name.c_str()); if (GetSequence(database_oid, sequence_name, txn) != nullptr) { throw SequenceException( - StringUtil::Format("Insert Sequence with Duplicate Sequence Name: %s", + StringUtil::Format("Cannot insert Sequence with Duplicate Sequence Name: %s", sequence_name.c_str())); } diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index 748a27921f6..61cca2c0753 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -279,7 +279,6 @@ bool CreateExecutor::CreateTrigger(const planner::CreatePlan &node) { bool CreateExecutor::CreateSequence(const planner::CreatePlan &node) { auto txn = context_->GetTransaction(); std::string database_name = node.GetDatabaseName(); - std::string table_name = node.GetTableName(); std::string sequence_name = node.GetSequenceName(); auto database_object = catalog::Catalog::GetInstance()->GetDatabaseObject( diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h index 9b26a647647..14744c0d235 100644 --- a/src/include/catalog/sequence_catalog.h +++ b/src/include/catalog/sequence_catalog.h @@ -78,12 +78,10 @@ class SequenceCatalogObject { std::mutex sequence_mutex; // mutex for all operations int64_t GetNextVal() { - std::lock_guard lock(sequence_mutex); return get_next_val(); }; int64_t GetCurrVal() { - std::lock_guard lock(sequence_mutex); return seq_curr_val; }; From 85af57419af587e32554a992f84a04f9c03cd83d Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Thu, 3 May 2018 22:25:09 -0400 Subject: [PATCH 18/29] again fix conflicts --- src/catalog/abstract_catalog.cpp | 3 --- src/catalog/catalog.cpp | 9 --------- src/executor/create_executor.cpp | 11 +---------- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/src/catalog/abstract_catalog.cpp b/src/catalog/abstract_catalog.cpp index 20f239934db..c5634b7d82e 100644 --- a/src/catalog/abstract_catalog.cpp +++ b/src/catalog/abstract_catalog.cpp @@ -34,10 +34,7 @@ #include "executor/plan_executor.h" #include "executor/seq_scan_executor.h" #include "executor/update_executor.h" -<<<<<<< HEAD #include "executor/plan_executor.h" -======= ->>>>>>> upstream/master #include "storage/database.h" #include "storage/storage_manager.h" diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index cc883a48f60..db6a0d218e1 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -191,21 +191,12 @@ void Catalog::Bootstrap() { catalog_map_[CATALOG_DATABASE_OID]->Bootstrap(CATALOG_DATABASE_NAME, txn); // bootstrap other global catalog tables DatabaseMetricsCatalog::GetInstance(txn); -<<<<<<< HEAD - TableMetricsCatalog::GetInstance(txn); - IndexMetricsCatalog::GetInstance(txn); - QueryMetricsCatalog::GetInstance(txn); -======= ->>>>>>> upstream/master SettingsCatalog::GetInstance(txn); LanguageCatalog::GetInstance(txn); // TODO: change pg_proc to per database ProcCatalog::GetInstance(txn); -<<<<<<< HEAD SequenceCatalog::GetInstance(txn); -======= ->>>>>>> upstream/master if (settings::SettingsManager::GetBool(settings::SettingId::brain)) { QueryHistoryCatalog::GetInstance(txn); diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index cbdbf97bc93..6a33a7388f4 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -14,14 +14,8 @@ #include "catalog/catalog.h" #include "catalog/foreign_key.h" -<<<<<<< HEAD -#include "catalog/sequence_catalog.h" -#include "catalog/trigger_catalog.h" -#include "catalog/database_catalog.h" -#include "catalog/table_catalog.h" -======= #include "catalog/system_catalogs.h" ->>>>>>> upstream/master +#include "catalog/sequence_catalog.h" #include "concurrency/transaction_context.h" #include "executor/executor_context.h" #include "planner/create_plan.h" @@ -103,8 +97,6 @@ bool CreateExecutor::DExecute() { } bool CreateExecutor::CreateDatabase(const planner::CreatePlan &node) { -<<<<<<< HEAD -======= auto txn = context_->GetTransaction(); auto database_name = node.GetDatabaseName(); // invoke logic within catalog.cpp @@ -116,7 +108,6 @@ bool CreateExecutor::CreateDatabase(const planner::CreatePlan &node) { } bool CreateExecutor::CreateSchema(const planner::CreatePlan &node) { ->>>>>>> upstream/master auto txn = context_->GetTransaction(); auto database_name = node.GetDatabaseName(); auto schema_name = node.GetSchemaName(); From 7997a9a891cc7d538b4c60000e898e0869dcb406 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Fri, 4 May 2018 01:05:22 -0400 Subject: [PATCH 19/29] move sequence catalog into system catalogs --- src/catalog/abstract_catalog.cpp | 1 - src/catalog/catalog.cpp | 2 -- src/catalog/sequence_catalog.cpp | 30 ++++++++++++-------------- src/catalog/system_catalogs.cpp | 6 ++++++ src/common/internal_types.cpp | 1 + src/executor/create_executor.cpp | 5 ++++- src/executor/executor_context.cpp | 1 - src/executor/plan_executor.cpp | 4 ---- src/function/string_functions.cpp | 14 ++++++++---- src/include/catalog/catalog_defaults.h | 2 +- src/include/catalog/sequence_catalog.h | 19 ++++++++-------- src/include/catalog/system_catalogs.h | 11 ++++++++++ src/include/executor/plan_executor.h | 2 +- 13 files changed, 58 insertions(+), 40 deletions(-) diff --git a/src/catalog/abstract_catalog.cpp b/src/catalog/abstract_catalog.cpp index c5634b7d82e..645e9c9d93f 100644 --- a/src/catalog/abstract_catalog.cpp +++ b/src/catalog/abstract_catalog.cpp @@ -34,7 +34,6 @@ #include "executor/plan_executor.h" #include "executor/seq_scan_executor.h" #include "executor/update_executor.h" -#include "executor/plan_executor.h" #include "storage/database.h" #include "storage/storage_manager.h" diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index db6a0d218e1..24e4d56ec77 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -26,7 +26,6 @@ #include "catalog/table_catalog.h" #include "catalog/table_metrics_catalog.h" #include "catalog/trigger_catalog.h" -#include "catalog/sequence_catalog.h" #include "concurrency/transaction_manager_factory.h" #include "function/date_functions.h" #include "function/decimal_functions.h" @@ -196,7 +195,6 @@ void Catalog::Bootstrap() { // TODO: change pg_proc to per database ProcCatalog::GetInstance(txn); - SequenceCatalog::GetInstance(txn); if (settings::SettingsManager::GetBool(settings::SettingId::brain)) { QueryHistoryCatalog::GetInstance(txn); diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index c56d1d755f6..5c48e7872c8 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -59,24 +59,19 @@ int64_t SequenceCatalogObject::get_next_val() { seq_curr_val += seq_increment; } - // TODO: this will become visible after Mengran's team push the - // AbstractCatalog::UpdateWithIndexScan. - // Link for the function: - // https://github.com/camellyx/peloton/blob/master/src/catalog/abstract_catalog.cpp#L305 - bool status = catalog::SequenceCatalog::GetInstance().UpdateNextVal(seq_oid, seq_curr_val, txn_); + bool status = Catalog::GetInstance() + ->GetSystemCatalogs(db_oid) + ->GetSequenceCatalog() + ->UpdateNextVal(seq_oid, seq_curr_val, txn_); LOG_DEBUG("status of update pg_sequence: %d", status); return result; } -SequenceCatalog &SequenceCatalog::GetInstance( - concurrency::TransactionContext *txn) { - static SequenceCatalog sequence_catalog{txn}; - return sequence_catalog; -} - -SequenceCatalog::SequenceCatalog(concurrency::TransactionContext *txn) - : AbstractCatalog("CREATE TABLE " SEQUENCE_CATALOG_NAME +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, " @@ -89,7 +84,7 @@ SequenceCatalog::SequenceCatalog(concurrency::TransactionContext *txn) "sqval BIGINT NOT NULL);", txn) { Catalog::GetInstance()->CreateIndex( - CATALOG_DATABASE_NAME, SEQUENCE_CATALOG_NAME, + database_name, CATALOG_SCHEMA_NAME, SEQUENCE_CATALOG_NAME, {ColumnId::DATABSE_OID, ColumnId::SEQUENCE_NAME}, SEQUENCE_CATALOG_NAME "_skey0", false, IndexType::BWTREE, txn); } @@ -171,8 +166,10 @@ ResultType SequenceCatalog::DropSequence(const std::string &database_name, auto database_object = Catalog::GetInstance()->GetDatabaseObject(database_name, txn); - oid_t sequence_oid = SequenceCatalog::GetInstance().GetSequenceOid( - sequence_name, database_object->GetDatabaseOid(), txn); + oid_t sequence_oid = Catalog::GetInstance() + ->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetSequenceCatalog() + ->GetSequenceOid(sequence_name, database_object->GetDatabaseOid(), txn); if (sequence_oid == INVALID_OID) { LOG_TRACE("Cannot find sequence %s to drop!", sequence_name.c_str()); return ResultType::FAILURE; @@ -239,6 +236,7 @@ std::shared_ptr SequenceCatalog::GetSequence( PELOTON_ASSERT(tuple_count == 1); auto new_sequence = std::make_shared( (*result_tiles)[0]->GetValue(0, 0).GetAs(), + database_oid, (*result_tiles)[0]->GetValue(0, 1).ToString(), (*result_tiles)[0]->GetValue(0, 2).GetAs(), (*result_tiles)[0]->GetValue(0, 3).GetAs(), 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/common/internal_types.cpp b/src/common/internal_types.cpp index 5d5e72c84c0..348af8e3421 100644 --- a/src/common/internal_types.cpp +++ b/src/common/internal_types.cpp @@ -331,6 +331,7 @@ std::string CreateTypeToString(CreateType type) { } case CreateType::SEQUENCE: { return "SEQUENCE"; + } case CreateType::SCHEMA: { return "SCHEMA"; } diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index 6a33a7388f4..9e04a968ffc 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -296,7 +296,10 @@ bool CreateExecutor::CreateSequence(const planner::CreatePlan &node) { auto database_object = catalog::Catalog::GetInstance()->GetDatabaseObject( database_name, txn); - catalog::SequenceCatalog::GetInstance().InsertSequence( + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetSequenceCatalog() + ->InsertSequence( database_object->GetDatabaseOid(), sequence_name, node.GetSequenceIncrement(), node.GetSequenceMaxValue(), node.GetSequenceMinValue(), node.GetSequenceStart(), diff --git a/src/executor/executor_context.cpp b/src/executor/executor_context.cpp index 72071dccfa9..29fb3794538 100644 --- a/src/executor/executor_context.cpp +++ b/src/executor/executor_context.cpp @@ -25,7 +25,6 @@ ExecutorContext::ExecutorContext(concurrency::TransactionContext *transaction, const std::string default_database_name) : transaction_(transaction), parameters_(std::move(parameters)), default_database_name_(default_database_name) { - LOG_DEBUG("ExecutorContext default db name: %s", default_database_name.c_str()); } concurrency::TransactionContext *ExecutorContext::GetTransaction() const { diff --git a/src/executor/plan_executor.cpp b/src/executor/plan_executor.cpp index 414aa703603..0fb90e193db 100644 --- a/src/executor/plan_executor.cpp +++ b/src/executor/plan_executor.cpp @@ -39,7 +39,6 @@ static void CompileAndExecutePlan( std::function &&)> on_complete, std::string default_database_name) { LOG_TRACE("Compiling and executing query ..."); - LOG_DEBUG("CompileAndExecutePlan default db name: %s", default_database_name.c_str()); // Perform binding planner::BindingContext context; @@ -93,7 +92,6 @@ static void InterpretPlan( std::string default_database_name) { executor::ExecutionResult result; std::vector values; - LOG_DEBUG("InterpretPlan default db name: %s", default_database_name.c_str()); std::unique_ptr executor_context( new executor::ExecutorContext(txn, params, default_database_name)); @@ -150,7 +148,6 @@ void PlanExecutor::ExecutePlan( std::string default_database_name) { PELOTON_ASSERT(plan != nullptr && txn != nullptr); LOG_TRACE("PlanExecutor Start (Txn ID=%" PRId64 ")", txn->GetTransactionId()); - LOG_DEBUG("PlanExecutor 1 default db name: %s", default_database_name.c_str()); bool codegen_enabled = settings::SettingsManager::GetBool(settings::SettingId::codegen); @@ -186,7 +183,6 @@ int PlanExecutor::ExecutePlan( std::vector> &logical_tile_list) { PELOTON_ASSERT(plan != nullptr); LOG_TRACE("PlanExecutor Start with transaction"); - LOG_DEBUG("PlanExecutor 2"); auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); auto txn = txn_manager.BeginTransaction(); diff --git a/src/function/string_functions.cpp b/src/function/string_functions.cpp index 5b739bcd40f..a97c8c5f24b 100644 --- a/src/function/string_functions.cpp +++ b/src/function/string_functions.cpp @@ -228,8 +228,11 @@ uint32_t StringFunctions::Nextval(executor::ExecutorContext &ctx, const char *se auto database_object = catalog::Catalog::GetInstance() ->GetDatabaseObject(ctx.GetDatabaseName(), ctx.GetTransaction()); - catalog::SequenceCatalogObject* sequence_object = catalog::SequenceCatalog::GetInstance(). - GetSequence(database_object->GetDatabaseOid(), sequence_name, ctx.GetTransaction()).get(); + catalog::SequenceCatalogObject* sequence_object = + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetSequenceCatalog() + ->GetSequence(database_object->GetDatabaseOid(), sequence_name, ctx.GetTransaction()).get(); if (sequence_object != nullptr) { return sequence_object->GetNextVal(); } else { @@ -244,8 +247,11 @@ uint32_t StringFunctions::Currval(executor::ExecutorContext &ctx, const char *se auto database_object = catalog::Catalog::GetInstance() ->GetDatabaseObject(ctx.GetDatabaseName(), ctx.GetTransaction()); - catalog::SequenceCatalogObject* sequence_object = catalog::SequenceCatalog::GetInstance(). - GetSequence(database_object->GetDatabaseOid(), sequence_name, ctx.GetTransaction()).get(); + catalog::SequenceCatalogObject* sequence_object = + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetSequenceCatalog() + ->GetSequence(database_object->GetDatabaseOid(), sequence_name, ctx.GetTransaction()).get(); if (sequence_object != nullptr) { return sequence_object->GetCurrVal(); } else { diff --git a/src/include/catalog/catalog_defaults.h b/src/include/catalog/catalog_defaults.h index 8e65de001ab..ce2a405a034 100644 --- a/src/include/catalog/catalog_defaults.h +++ b/src/include/catalog/catalog_defaults.h @@ -100,7 +100,7 @@ enum class CatalogType : uint32_t { TRIGGER = 6 << CATALOG_TYPE_OFFSET, LANGUAGE = 7 << CATALOG_TYPE_OFFSET, PROC = 8 << CATALOG_TYPE_OFFSET, - SEQUENCE = 8 << CATALOG_TYPE_OFFSET, + SEQUENCE = 9 << CATALOG_TYPE_OFFSET, // To be added }; diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h index 14744c0d235..72a2915aa49 100644 --- a/src/include/catalog/sequence_catalog.h +++ b/src/include/catalog/sequence_catalog.h @@ -38,6 +38,7 @@ #include "catalog/abstract_catalog.h" #include "catalog/catalog_defaults.h" +#include "catalog/system_catalogs.h" #define SEQUENCE_CATALOG_NAME "pg_sequence" @@ -51,12 +52,13 @@ namespace catalog { class SequenceCatalogObject { public: - SequenceCatalogObject(oid_t seqoid, const std::string &name, + 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), @@ -67,6 +69,7 @@ class SequenceCatalogObject { 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 @@ -76,7 +79,6 @@ class SequenceCatalogObject { bool seq_cycle; // Whether the sequence cycles concurrency::TransactionContext *txn_; - std::mutex sequence_mutex; // mutex for all operations int64_t GetNextVal() { return get_next_val(); }; @@ -97,12 +99,10 @@ class SequenceCatalogObject { class SequenceCatalog : public AbstractCatalog { public: + SequenceCatalog(const std::string &database_name, + concurrency::TransactionContext *txn); ~SequenceCatalog(); - // Global Singleton - static SequenceCatalog &GetInstance( - concurrency::TransactionContext *txn = nullptr); - //===--------------------------------------------------------------------===// // write Related API //===--------------------------------------------------------------------===// @@ -142,11 +142,12 @@ class SequenceCatalog : public AbstractCatalog { SEQUENCE_VALUE = 8 }; - enum IndexId { PRIMARY_KEY = 0, DBOID_SEQNAME_KEY = 1 }; + enum IndexId { + PRIMARY_KEY = 0, + DBOID_SEQNAME_KEY = 1 + }; private: - SequenceCatalog(concurrency::TransactionContext *txn); - oid_t GetNextOid() { return oid_++ | SEQUENCE_OID_MASK; } }; 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/executor/plan_executor.h b/src/include/executor/plan_executor.h index c02e3e32581..99d8d51eedd 100644 --- a/src/include/executor/plan_executor.h +++ b/src/include/executor/plan_executor.h @@ -62,7 +62,7 @@ class PlanExecutor { const std::vector &result_format, std::function &&)> on_complete, - std::string default_database_name); + std::string default_database_name=""); /* * @brief When a peloton node recvs a query plan, this function is invoked From 35d6a5a7f1171788354917dd1521a37a5a4cfcf2 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Fri, 4 May 2018 14:56:18 -0400 Subject: [PATCH 20/29] fix issues in comments; add sanity check for sequence arguments --- src/catalog/sequence_catalog.cpp | 45 +++++++++++----------- src/common/internal_types.cpp | 3 ++ src/executor/create_executor.cpp | 2 + src/include/catalog/catalog_defaults.h | 1 + src/include/catalog/sequence_catalog.h | 37 ++++++++++++++---- src/include/parser/create_statement.h | 3 -- src/include/parser/postgresparser.h | 4 +- src/include/planner/create_plan.h | 1 + src/network/postgres_protocol_handler.cpp | 1 + src/parser/postgresparser.cpp | 46 +++++++++-------------- src/planner/create_plan.cpp | 2 - test/parser/postgresparser_test.cpp | 4 -- 12 files changed, 81 insertions(+), 68 deletions(-) diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index 5c48e7872c8..f950234a447 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -35,14 +35,16 @@ namespace catalog { * @exception throws SequenceException if the sequence exceeds the upper/lower * limit. */ -int64_t SequenceCatalogObject::get_next_val() { +int64_t SequenceCatalogObject::GetNextVal() { int64_t result = seq_curr_val; + seq_prev_val = result; if (seq_increment > 0) { 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("Sequence exceeds upper limit!")); + StringUtil::Format( + "nextval: reached maximum value of sequence %s (%ld)", seq_name.c_str(), seq_max)); } seq_curr_val = seq_min; } else @@ -52,7 +54,8 @@ int64_t SequenceCatalogObject::get_next_val() { (seq_min >= 0 && seq_curr_val + seq_increment < seq_min)) { if (!seq_cycle) { throw SequenceException( - StringUtil::Format("Sequence exceeds lower limit!")); + StringUtil::Format( + "nextval: reached minimum value of sequence %s (%ld)", seq_name.c_str(), seq_min)); } seq_curr_val = seq_max; } else @@ -91,7 +94,7 @@ SequenceCatalog::SequenceCatalog(const std::string &database_name, SequenceCatalog::~SequenceCatalog() {} -/* @brief Delete the sequence by name. +/* @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 @@ -113,9 +116,11 @@ bool SequenceCatalog::InsertSequence(oid_t database_oid, 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("Cannot insert Sequence with Duplicate Sequence Name: %s", + StringUtil::Format("Sequence %s already exists!", sequence_name.c_str())); } @@ -151,16 +156,14 @@ bool SequenceCatalog::InsertSequence(oid_t 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 ResultType::SUCCESS if the sequence exists, ResultType::FAILURE + * @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) { - LOG_TRACE("Do not have transaction to drop sequence: %s", - database_name.c_str()); - return ResultType::FAILURE; + throw CatalogException("Transaction is invalid!"); } auto database_object = @@ -171,8 +174,9 @@ ResultType SequenceCatalog::DropSequence(const std::string &database_name, ->GetSequenceCatalog() ->GetSequenceOid(sequence_name, database_object->GetDatabaseOid(), txn); if (sequence_oid == INVALID_OID) { - LOG_TRACE("Cannot find sequence %s to drop!", sequence_name.c_str()); - return ResultType::FAILURE; + throw SequenceException( + StringUtil::Format("Sequence %s does not exist!", + sequence_name.c_str())); } LOG_INFO("sequence %d will be deleted!", sequence_oid); @@ -210,8 +214,8 @@ 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_NAME, - ColumnId::SEQUENCE_START, ColumnId::SEQUENCE_INC, ColumnId::SEQUENCE_MAX, + {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; @@ -222,7 +226,7 @@ std::shared_ptr SequenceCatalog::GetSequence( // the result is a vector of executor::LogicalTile auto result_tiles = GetResultWithIndexScan(column_ids, index_offset, values, txn); - // carefull! the result tile could be null! + // 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()); @@ -237,13 +241,13 @@ std::shared_ptr SequenceCatalog::GetSequence( auto new_sequence = std::make_shared( (*result_tiles)[0]->GetValue(0, 0).GetAs(), database_oid, - (*result_tiles)[0]->GetValue(0, 1).ToString(), + 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(), - (*result_tiles)[0]->GetValue(0, 7).GetAs(), txn); + (*result_tiles)[0]->GetValue(0, 5).GetAs(), + (*result_tiles)[0]->GetValue(0, 6).GetAs(), txn); return new_sequence; } @@ -288,10 +292,7 @@ oid_t SequenceCatalog::GetSequenceOid(std::string sequence_name, } PELOTON_ASSERT(result_tiles->size() == 1); - oid_t result; - result = (*result_tiles)[0]->GetValue(0, 0).GetAs(); - - return result; + return (*result_tiles)[0]->GetValue(0, 0).GetAs(); } } // namespace catalog diff --git a/src/common/internal_types.cpp b/src/common/internal_types.cpp index 348af8e3421..1fb299783e8 100644 --- a/src/common/internal_types.cpp +++ b/src/common/internal_types.cpp @@ -560,6 +560,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: @@ -621,6 +623,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 = diff --git a/src/executor/create_executor.cpp b/src/executor/create_executor.cpp index 9e04a968ffc..5ea732fc587 100644 --- a/src/executor/create_executor.cpp +++ b/src/executor/create_executor.cpp @@ -314,6 +314,8 @@ bool CreateExecutor::CreateSequence(const planner::CreatePlan &node) { ResultTypeToString(txn->GetResult()).c_str()); } + // Notice this action will always return true, since any exception + // will be handled in CreateSequence function in SequencCatalog. return (true); } diff --git a/src/include/catalog/catalog_defaults.h b/src/include/catalog/catalog_defaults.h index ce2a405a034..17960b14391 100644 --- a/src/include/catalog/catalog_defaults.h +++ b/src/include/catalog/catalog_defaults.h @@ -32,6 +32,7 @@ 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 diff --git a/src/include/catalog/sequence_catalog.h b/src/include/catalog/sequence_catalog.h index 72a2915aa49..a833cb7df2e 100644 --- a/src/include/catalog/sequence_catalog.h +++ b/src/include/catalog/sequence_catalog.h @@ -40,8 +40,6 @@ #include "catalog/catalog_defaults.h" #include "catalog/system_catalogs.h" -#define SEQUENCE_CATALOG_NAME "pg_sequence" - namespace peloton { namespace concurrency { @@ -79,12 +77,12 @@ class SequenceCatalogObject { bool seq_cycle; // Whether the sequence cycles concurrency::TransactionContext *txn_; - int64_t GetNextVal() { - return get_next_val(); - }; + int64_t seq_prev_val; + + int64_t GetNextVal(); int64_t GetCurrVal() { - return seq_curr_val; + return seq_prev_val; }; void SetCurrVal(int64_t curr_val) { @@ -94,7 +92,6 @@ class SequenceCatalogObject { private: int64_t seq_curr_val; - int64_t get_next_val(); }; class SequenceCatalog : public AbstractCatalog { @@ -149,6 +146,32 @@ class SequenceCatalog : public AbstractCatalog { private: oid_t GetNextOid() { return oid_++ | SEQUENCE_OID_MASK; } + + 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 (%d) must be less than MAXVALUE (%d)", 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 (%d) cannot be less than MINVALUE (%d)", seq_start, seq_min)); + } + + if (seq_increment < 0 && seq_start > seq_max) { + throw SequenceException( + StringUtil::Format( + "START value (%d) cannot be greater than MAXVALUE (%d)", seq_start, seq_max)); + } + }; }; } // namespace catalog diff --git a/src/include/parser/create_statement.h b/src/include/parser/create_statement.h index b20c73c054e..a3b27a9dd30 100644 --- a/src/include/parser/create_statement.h +++ b/src/include/parser/create_statement.h @@ -265,13 +265,10 @@ class CreateStatement : public TableRefStatement { // attributes related to sequences std::string sequence_name; - std::unique_ptr table; // deal with RangeVar int64_t seq_start = 1; int64_t seq_increment = 1; int64_t seq_max_value = LONG_MAX; int64_t seq_min_value = 1; - int64_t seq_cache; // sequence cache size, probably won't be supported in - // this project bool seq_cycle = false; }; diff --git a/src/include/parser/postgresparser.h b/src/include/parser/postgresparser.h index 3827dcf52d1..00507c22afa 100644 --- a/src/include/parser/postgresparser.h +++ b/src/include/parser/postgresparser.h @@ -294,10 +294,10 @@ class PostgresParser { // transform helper for subquery expressions static expression::AbstractExpression *SubqueryExprTransform(SubLink *node); - static void parse_sequence_params(List *options, + static void ParseSequenceParams(List *options, parser::CreateStatement *result); - static int64_t get_long_in_defel(DefElem *defel) { + static int64_t GetLongInDefElem(DefElem *defel) { return (int64_t)((reinterpret_cast(defel->arg))->val.ival); }; }; diff --git a/src/include/planner/create_plan.h b/src/include/planner/create_plan.h index 7d4cff6233f..3b5cda6e3df 100644 --- a/src/include/planner/create_plan.h +++ b/src/include/planner/create_plan.h @@ -14,6 +14,7 @@ #include "parser/create_statement.h" #include "planner/abstract_plan.h" +#include "common/exception.h" namespace peloton { namespace catalog { diff --git a/src/network/postgres_protocol_handler.cpp b/src/network/postgres_protocol_handler.cpp index ffbb786b88e..4aabc487cb1 100644 --- a/src/network/postgres_protocol_handler.cpp +++ b/src/network/postgres_protocol_handler.cpp @@ -1222,6 +1222,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/parser/postgresparser.cpp b/src/parser/postgresparser.cpp index 10df4de202d..5f9fdc9a7c3 100644 --- a/src/parser/postgresparser.cpp +++ b/src/parser/postgresparser.cpp @@ -1352,20 +1352,16 @@ parser::SQLStatement *PostgresParser::CreateSequenceTransform( parser::CreateStatement *result = new parser::CreateStatement(CreateStatement::kSequence); result->sequence_name = std::string(root->sequence->relname); - result->table.reset( - RangeVarTransform(reinterpret_cast(root->sequence))); - parse_sequence_params(root->options, result); + ParseSequenceParams(root->options, result); return result; } -void PostgresParser::parse_sequence_params(List *options, +void PostgresParser::ParseSequenceParams(List *options, parser::CreateStatement *result) { DefElem *start_value = NULL; - // DefElem *restart_value = NULL; DefElem *increment_by = NULL; DefElem *max_value = NULL; DefElem *min_value = NULL; - DefElem *cache_value = NULL; DefElem *is_cycled = NULL; if (!options) return; @@ -1378,52 +1374,46 @@ void PostgresParser::parse_sequence_params(List *options, throw ParserException( "Redundant definition of increment in defining sequence"); increment_by = defel; - result->seq_increment = get_long_in_defel(increment_by); + 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 = get_long_in_defel(start_value); + 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 = get_long_in_defel(max_value); + 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 = get_long_in_defel(min_value); - } else if (strcmp(defel->defname, "cache") == 0) { - if (cache_value) - throw ParserException( - "Redundant definition of cache in defining sequence"); - cache_value = defel; - result->seq_cache = get_long_in_defel(cache_value); + 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)get_long_in_defel(is_cycled); - } - // TODO: support owned_by - // else if (strcmp(defel->defname, "owned_by") == 0) - // { - // // if (*owned_by) - // // ereport(ERROR, - // // (errcode(ERRCODE_SYNTAX_ERROR), - // // errmsg("conflicting or redundant options"), - // // parser_errposition(pstate, defel->location))); - // *owned_by = defGetQualifiedName(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) { diff --git a/src/planner/create_plan.cpp b/src/planner/create_plan.cpp index 0394c54ed9d..83e6cc259ff 100644 --- a/src/planner/create_plan.cpp +++ b/src/planner/create_plan.cpp @@ -214,9 +214,7 @@ CreatePlan::CreatePlan(parser::CreateStatement *parse_tree) { seq_increment = parse_tree->seq_increment; seq_max_value = parse_tree->seq_max_value; seq_min_value = parse_tree->seq_min_value; - seq_cache = parse_tree->seq_cache; seq_cycle = parse_tree->seq_cycle; - break; } default: diff --git a/test/parser/postgresparser_test.cpp b/test/parser/postgresparser_test.cpp index c8088d8d51f..91ff5039fdd 100644 --- a/test/parser/postgresparser_test.cpp +++ b/test/parser/postgresparser_test.cpp @@ -1079,10 +1079,6 @@ TEST_F(PostgresParserTests, CreateSequenceTest) { 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::CREATE, stmt_list->GetStatement(0)->GetType()); auto create_sequence_stmt = static_cast(stmt_list->GetStatement(0)); From 6b1258483a227f73aa44ff377f193b4df05e42d3 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Fri, 4 May 2018 21:48:15 -0400 Subject: [PATCH 21/29] move sequence functions from string files to new files --- src/catalog/catalog.cpp | 5 +- .../proxy/sequence_functions_proxy.cpp | 24 ++++++ src/codegen/proxy/string_functions_proxy.cpp | 4 - src/codegen/type/bigint_type.cpp | 49 +++++++++++- src/codegen/type/varchar_type.cpp | 46 +----------- src/function/old_engine_string_functions.cpp | 14 ---- src/function/sequence_functions.cpp | 75 +++++++++++++++++++ src/function/string_functions.cpp | 38 ---------- .../codegen/proxy/sequence_functions_proxy.h | 28 +++++++ src/include/codegen/type/varchar_type.h | 2 +- .../function/old_engine_string_functions.h | 4 - src/include/function/sequence_functions.h | 40 ++++++++++ src/include/function/string_functions.h | 6 -- 13 files changed, 220 insertions(+), 115 deletions(-) create mode 100644 src/codegen/proxy/sequence_functions_proxy.cpp create mode 100644 src/function/sequence_functions.cpp create mode 100644 src/include/codegen/proxy/sequence_functions_proxy.h create mode 100644 src/include/function/sequence_functions.h diff --git a/src/catalog/catalog.cpp b/src/catalog/catalog.cpp index 24e4d56ec77..ca9398574e3 100644 --- a/src/catalog/catalog.cpp +++ b/src/catalog/catalog.cpp @@ -31,6 +31,7 @@ #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" @@ -1210,13 +1211,13 @@ void Catalog::InitializeFunctions() { "nextval", {type::TypeId::VARCHAR}, type::TypeId::INTEGER, internal_lang, "Nextval", function::BuiltInFuncType{OperatorId::Nextval, - function::OldEngineStringFunctions::Nextval}, + function::SequenceFunctions::_Nextval}, txn); AddBuiltinFunction( "currval", {type::TypeId::VARCHAR}, type::TypeId::INTEGER, internal_lang, "Currval", function::BuiltInFuncType{OperatorId::Currval, - function::OldEngineStringFunctions::Currval}, + function::SequenceFunctions::_Currval}, 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/proxy/string_functions_proxy.cpp b/src/codegen/proxy/string_functions_proxy.cpp index d8786cc5b29..46a356b61dd 100644 --- a/src/codegen/proxy/string_functions_proxy.cpp +++ b/src/codegen/proxy/string_functions_proxy.cpp @@ -33,9 +33,5 @@ DEFINE_METHOD(peloton::function, StringFunctions, Trim); DEFINE_METHOD(peloton::function, StringFunctions, LTrim); DEFINE_METHOD(peloton::function, StringFunctions, RTrim); -// Sequence-related functions -DEFINE_METHOD(peloton::function, StringFunctions, Nextval); -DEFINE_METHOD(peloton::function, StringFunctions, 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/codegen/type/varchar_type.cpp b/src/codegen/type/varchar_type.cpp index 52716c60d66..0066457e425 100644 --- a/src/codegen/type/varchar_type.cpp +++ b/src/codegen/type/varchar_type.cpp @@ -187,46 +187,6 @@ struct Trim : public TypeSystem::UnaryOperatorHandleNull { } }; -// 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 Integer::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(StringFunctionsProxy::Nextval, - {executor_ctx, val.GetValue()}); - return Value{Integer::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 Integer::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(StringFunctionsProxy::Currval, - {executor_ctx, val.GetValue()}); - return Value{Integer::Instance(), raw_ret}; - } -}; - //////////////////////////////////////////////////////////////////////////////// /// /// Binary operators @@ -576,14 +536,10 @@ std::vector kComparisonTable = {{kCompareVarchar}}; Ascii kAscii; Length kLength; Trim kTrim; -Nextval kNextval; -Currval kCurrval; std::vector kUnaryOperatorTable = { {OperatorId::Ascii, kAscii}, {OperatorId::Length, kLength}, - {OperatorId::Trim, kTrim}, - {OperatorId::Nextval, kNextval}, - {OperatorId::Currval, kCurrval}}; + {OperatorId::Trim, kTrim}}; // Binary operations Like kLike; diff --git a/src/function/old_engine_string_functions.cpp b/src/function/old_engine_string_functions.cpp index 96fe5a30e35..09a4be34985 100644 --- a/src/function/old_engine_string_functions.cpp +++ b/src/function/old_engine_string_functions.cpp @@ -234,19 +234,5 @@ type::Value OldEngineStringFunctions::Lower( UNUSED_ATTRIBUTE const std::vector &args) { throw Exception{"Lower not implemented in old engine"}; } - -type::Value OldEngineStringFunctions::Nextval( - UNUSED_ATTRIBUTE const std::vector &args) { - executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); - uint32_t ret = StringFunctions::Nextval(*ctx, args[0].GetAs()); - return type::ValueFactory::GetIntegerValue(ret); -} - -type::Value OldEngineStringFunctions::Currval( - UNUSED_ATTRIBUTE const std::vector &args) { - executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); - uint32_t ret = StringFunctions::Currval(*ctx, args[0].GetAs()); - return type::ValueFactory::GetIntegerValue(ret); -} } // namespace function } // namespace peloton diff --git a/src/function/sequence_functions.cpp b/src/function/sequence_functions.cpp new file mode 100644 index 00000000000..409beaa44d7 --- /dev/null +++ b/src/function/sequence_functions.cpp @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// string_functions.cpp +// +// Identification: src/function/string_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" + +namespace peloton { +namespace function { + +uint32_t SequenceFunctions::Nextval(executor::ExecutorContext &ctx, const char *sequence_name) { + PELOTON_ASSERT(sequence_name != nullptr); + auto database_object = + catalog::Catalog::GetInstance() + ->GetDatabaseObject(ctx.GetDatabaseName(), ctx.GetTransaction()); + catalog::SequenceCatalogObject* sequence_object = + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetSequenceCatalog() + ->GetSequence(database_object->GetDatabaseOid(), sequence_name, ctx.GetTransaction()).get(); + if (sequence_object != nullptr) { + return sequence_object->GetNextVal(); + } else { + throw SequenceException( + StringUtil::Format("Sequence not exists!")); + } +} + +uint32_t SequenceFunctions::Currval(executor::ExecutorContext &ctx, const char *sequence_name) { + PELOTON_ASSERT(sequence_name != nullptr); + auto database_object = + catalog::Catalog::GetInstance() + ->GetDatabaseObject(ctx.GetDatabaseName(), ctx.GetTransaction()); + catalog::SequenceCatalogObject* sequence_object = + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_object->GetDatabaseOid()) + ->GetSequenceCatalog() + ->GetSequence(database_object->GetDatabaseOid(), sequence_name, ctx.GetTransaction()).get(); + if (sequence_object != nullptr) { + return sequence_object->GetCurrVal(); + } else { + throw SequenceException( + StringUtil::Format("Sequence not exists!")); + } +} + +type::Value SequenceFunctions::_Nextval( + UNUSED_ATTRIBUTE 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); +} + +type::Value SequenceFunctions::_Currval( + UNUSED_ATTRIBUTE 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/function/string_functions.cpp b/src/function/string_functions.cpp index a97c8c5f24b..960a01bd2de 100644 --- a/src/function/string_functions.cpp +++ b/src/function/string_functions.cpp @@ -16,7 +16,6 @@ #include "executor/executor_context.h" #include "catalog/catalog.h" #include "catalog/database_catalog.h" -#include "catalog/sequence_catalog.h" namespace peloton { namespace function { @@ -223,42 +222,5 @@ uint32_t StringFunctions::Length( return length; } -uint32_t StringFunctions::Nextval(executor::ExecutorContext &ctx, const char *sequence_name) { - PELOTON_ASSERT(sequence_name != nullptr); - auto database_object = - catalog::Catalog::GetInstance() - ->GetDatabaseObject(ctx.GetDatabaseName(), ctx.GetTransaction()); - catalog::SequenceCatalogObject* sequence_object = - catalog::Catalog::GetInstance() - ->GetSystemCatalogs(database_object->GetDatabaseOid()) - ->GetSequenceCatalog() - ->GetSequence(database_object->GetDatabaseOid(), sequence_name, ctx.GetTransaction()).get(); - if (sequence_object != nullptr) { - return sequence_object->GetNextVal(); - } else { - throw SequenceException( - StringUtil::Format("Sequence not exists!")); - } -} - - -uint32_t StringFunctions::Currval(executor::ExecutorContext &ctx, const char *sequence_name) { - PELOTON_ASSERT(sequence_name != nullptr); - auto database_object = - catalog::Catalog::GetInstance() - ->GetDatabaseObject(ctx.GetDatabaseName(), ctx.GetTransaction()); - catalog::SequenceCatalogObject* sequence_object = - catalog::Catalog::GetInstance() - ->GetSystemCatalogs(database_object->GetDatabaseOid()) - ->GetSequenceCatalog() - ->GetSequence(database_object->GetDatabaseOid(), sequence_name, ctx.GetTransaction()).get(); - if (sequence_object != nullptr) { - return sequence_object->GetCurrVal(); - } else { - throw SequenceException( - StringUtil::Format("Sequence not exists!")); - } -} - } // namespace function } // namespace peloton 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/function/old_engine_string_functions.h b/src/include/function/old_engine_string_functions.h index f8748e9ae76..7603ac14fd0 100644 --- a/src/include/function/old_engine_string_functions.h +++ b/src/include/function/old_engine_string_functions.h @@ -68,10 +68,6 @@ class OldEngineStringFunctions { // Upper, Lower static type::Value Upper(const std::vector &args); static type::Value Lower(const std::vector &args); - - // Sequence-related - static type::Value Nextval(const std::vector &args); - static type::Value Currval(const std::vector &args); }; } // namespace function diff --git a/src/include/function/sequence_functions.h b/src/include/function/sequence_functions.h new file mode 100644 index 00000000000..62783ffc221 --- /dev/null +++ b/src/include/function/sequence_functions.h @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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); + + 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/function/string_functions.h b/src/include/function/string_functions.h index 1d41551cef1..2a209d0dee6 100644 --- a/src/include/function/string_functions.h +++ b/src/include/function/string_functions.h @@ -74,12 +74,6 @@ class StringFunctions { // Length will return the number of characters in the given string static uint32_t Length(executor::ExecutorContext &ctx, const char *str, uint32_t length); - - // 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); }; } // namespace function From bd4210e1c9d2e1b8cb5d6bed29961d3b12a0c5b5 Mon Sep 17 00:00:00 2001 From: Peixin Sun Date: Fri, 4 May 2018 23:32:56 -0400 Subject: [PATCH 22/29] implement nextval&currval for multi-session, minor bugs --- .vscode/settings.json | 29 ++++++++ src/catalog/catalog_cache.cpp | 73 +++++++++++++++++++ src/function/old_engine_string_functions.cpp | 49 +++++++++++-- src/include/catalog/catalog_cache.h | 21 ++++++ .../function/old_engine_string_functions.h | 1 + 5 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..731524cd9dc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,29 @@ +{ + "files.associations": { + "__functional_base": "cpp", + "__functional_base_03": "cpp", + "__hash_table": "cpp", + "__tree": "cpp", + "__tuple": "cpp", + "array": "cpp", + "chrono": "cpp", + "functional": "cpp", + "limits": "cpp", + "memory": "cpp", + "random": "cpp", + "ratio": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "__config": "cpp", + "cstddef": "cpp", + "exception": "cpp", + "initializer_list": "cpp", + "new": "cpp", + "stdexcept": "cpp", + "typeinfo": "cpp", + "slist": "cpp", + "cctype": "cpp", + "cstdlib": "cpp" + } +} \ No newline at end of file diff --git a/src/catalog/catalog_cache.cpp b/src/catalog/catalog_cache.cpp index 54f0e1a3d13..c1b8a889eaa 100644 --- a/src/catalog/catalog_cache.cpp +++ b/src/catalog/catalog_cache.cpp @@ -13,8 +13,10 @@ #include #include "catalog/catalog_cache.h" +#include #include "catalog/database_catalog.h" +#include "catalog/sequence_catalog.h" #include "common/logger.h" namespace peloton { @@ -157,5 +159,76 @@ std::shared_ptr CatalogCache::GetCachedIndexObject( return nullptr; } +/*@brief insert sequence catalog object into cache + * @param txn_id, sequence_object + * @return false only if sequence already exists in cache + */ +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, database_oid, txn_id + * @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, database_oid, txn_id + * @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, database_oid, txn_id + * @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/function/old_engine_string_functions.cpp b/src/function/old_engine_string_functions.cpp index 96fe5a30e35..9c93776eb5f 100644 --- a/src/function/old_engine_string_functions.cpp +++ b/src/function/old_engine_string_functions.cpp @@ -18,7 +18,11 @@ #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 "catalog/sequence_catalog.h" +#include "concurrency/transaction_context.h" +#include "concurrency/transaction_manager_factory.h" namespace peloton { namespace function { @@ -237,16 +241,49 @@ type::Value OldEngineStringFunctions::Lower( type::Value OldEngineStringFunctions::Nextval( UNUSED_ATTRIBUTE const std::vector &args) { - executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); - uint32_t ret = StringFunctions::Nextval(*ctx, args[0].GetAs()); - return type::ValueFactory::GetIntegerValue(ret); + executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); + concurrency::TransactionContext* txn = ctx->GetTransaction(); + const char * sequence_name = args[0].GetAs(); + PELOTON_ASSERT(sequence_name != nullptr); + oid_t database_oid = catalog::Catalog::GetInstance() + ->GetDatabaseObject(ctx->GetDatabaseName(), txn)->GetDatabaseOid(); + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto mini_txn = txn_manager.BeginTransaction(); + 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) { + int64_t val = sequence_object->GetNextVal(); + bool insert = txn->catalog_cache.InsertSequenceObject(sequence_object); + PELOTON_ASSERT(insert); + txn_manager.CommitTransaction(mini_txn); + return type::ValueFactory::GetIntegerValue(val); + } else { + throw SequenceException( + StringUtil::Format("relation \"%s\" does not exist", sequence_name)); + } } type::Value OldEngineStringFunctions::Currval( UNUSED_ATTRIBUTE const std::vector &args) { executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); - uint32_t ret = StringFunctions::Currval(*ctx, args[0].GetAs()); - return type::ValueFactory::GetIntegerValue(ret); + concurrency::TransactionContext* txn = ctx->GetTransaction(); + const char * sequence_name = args[0].GetAs(); + PELOTON_ASSERT(sequence_name != nullptr); + oid_t database_oid = catalog::Catalog::GetInstance() + ->GetDatabaseObject(ctx->GetDatabaseName(), txn)->GetDatabaseOid(); + auto sequence_object = txn->catalog_cache.GetSequenceObject(sequence_name, + database_oid); + if (sequence_object != nullptr) { + return type::ValueFactory::GetIntegerValue(sequence_object->GetCurrVal()); + } else { + throw SequenceException( + StringUtil::Format("relation \"%s\" does not exist", sequence_name)); + } } + } // namespace function } // namespace peloton diff --git a/src/include/catalog/catalog_cache.h b/src/include/catalog/catalog_cache.h index 5bde19760ad..e57dfdd852a 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 OldEngineStringFunctions; +} // 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::OldEngineStringFunctions; 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/function/old_engine_string_functions.h b/src/include/function/old_engine_string_functions.h index f8748e9ae76..2d30d710c73 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); From 80ad516714d7085d551da6cc1251e28386bc4a56 Mon Sep 17 00:00:00 2001 From: Bowen Deng Date: Fri, 4 May 2018 23:34:29 -0400 Subject: [PATCH 23/29] partially implemented drop seq --- src/catalog/sequence_catalog.cpp | 3 +- src/executor/drop_executor.cpp | 42 ++++++++++++++++++++++++++++ src/include/executor/drop_executor.h | 3 ++ src/include/planner/drop_plan.h | 6 ++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index f950234a447..3a7eef07273 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -67,7 +67,7 @@ int64_t SequenceCatalogObject::GetNextVal() { ->GetSequenceCatalog() ->UpdateNextVal(seq_oid, seq_curr_val, txn_); LOG_DEBUG("status of update pg_sequence: %d", status); - + void(status); return result; } @@ -238,6 +238,7 @@ std::shared_ptr SequenceCatalog::GetSequence( 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, diff --git a/src/executor/drop_executor.cpp b/src/executor/drop_executor.cpp index b9413366c2e..0e5b2cea1f9 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)); @@ -215,6 +219,44 @@ 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 schema_name = node.GetSchemaName(); + std::string table_name = node.GetTableName(); + std::string trigger_name = node.GetTriggerName(); + + auto table_object = catalog::Catalog::GetInstance()->GetTableObject( + database_name, schema_name, table_name, txn); + // drop trigger + ResultType result = + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(table_object->GetDatabaseOid()) + ->GetTriggerCatalog() + ->DropTrigger(table_object->GetDatabaseOid(), + table_object->GetTableOid(), trigger_name, txn); + txn->SetResult(result); + if (txn->GetResult() == ResultType::SUCCESS) { + LOG_DEBUG("Dropping trigger succeeded!"); + + if (StatementCacheManager::GetStmtCacheManager().get()) { + oid_t table_id = table_object->GetTableOid(); + StatementCacheManager::GetStmtCacheManager()->InvalidateTableOid( + table_id); + } + } else if (txn->GetResult() == ResultType::FAILURE && node.IsMissing()) { + txn->SetResult(ResultType::SUCCESS); + LOG_TRACE("Dropping trigger Succeeded!"); + } else if (txn->GetResult() == ResultType::FAILURE && !node.IsMissing()) { + LOG_TRACE("Dropping trigger 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(); 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/planner/drop_plan.h b/src/include/planner/drop_plan.h index c5593680202..9ef92f73c93 100644 --- a/src/include/planner/drop_plan.h +++ b/src/include/planner/drop_plan.h @@ -57,6 +57,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; } @@ -77,6 +79,10 @@ class DropPlan : public AbstractPlan { std::string schema_name; std::string trigger_name; + + // sequence name + std::string sequence_name; + std::string index_name; bool missing; From 28045bec3fe4ebd411908dcc6bd8cac8d2cb0f6b Mon Sep 17 00:00:00 2001 From: Peixin Sun Date: Sat, 5 May 2018 15:08:44 -0400 Subject: [PATCH 24/29] fix bug with nextval & currval. now support multi-session --- src/catalog/catalog_cache.cpp | 8 +-- src/catalog/sequence_catalog.cpp | 1 - src/expression/function_expression.cpp | 6 +- src/function/sequence_functions.cpp | 66 ++++++++++++++----- src/function/string_functions.cpp | 2 - src/include/catalog/catalog_cache.h | 4 +- .../codegen/proxy/string_functions_proxy.h | 4 -- src/include/common/internal_types.h | 3 +- 8 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/catalog/catalog_cache.cpp b/src/catalog/catalog_cache.cpp index c1b8a889eaa..411cb5706b3 100644 --- a/src/catalog/catalog_cache.cpp +++ b/src/catalog/catalog_cache.cpp @@ -160,7 +160,7 @@ std::shared_ptr CatalogCache::GetCachedIndexObject( } /*@brief insert sequence catalog object into cache - * @param txn_id, sequence_object + * @param sequence_object * @return false only if sequence already exists in cache */ bool CatalogCache::InsertSequenceObject( @@ -186,7 +186,7 @@ bool CatalogCache::InsertSequenceObject( } /*@brief evict sequence catalog object from cache - * @param sequence_name, database_oid, txn_id + * @param sequence_name, database_oid * @return true if specified sequence is found and evicted; * false if not found */ @@ -206,7 +206,7 @@ bool CatalogCache::EvictSequenceObject(const std::string & sequence_name, } /*@brief get sequence catalog object from cache - * @param sequence_name, database_oid, txn_id + * @param sequence_name, database_oid * @return sequence catalog object; if not found return object with invalid oid */ std::shared_ptr CatalogCache::GetSequenceObject( @@ -220,7 +220,7 @@ std::shared_ptr CatalogCache::GetSequenceObject( } /*@brief get the hash key given the sequence information - * @param sequence_name, database_oid, txn_id + * @param sequence_name, database_oid * @return hash key */ std::size_t CatalogCache::GetHashKey(const std::string sequence_name, diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index 3a7eef07273..19f7a409ae3 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -67,7 +67,6 @@ int64_t SequenceCatalogObject::GetNextVal() { ->GetSequenceCatalog() ->UpdateNextVal(seq_oid, seq_curr_val, txn_); LOG_DEBUG("status of update pg_sequence: %d", status); - void(status); return result; } diff --git a/src/expression/function_expression.cpp b/src/expression/function_expression.cpp index 1ab6d28af31..eef472e025f 100644 --- a/src/expression/function_expression.cpp +++ b/src/expression/function_expression.cpp @@ -49,8 +49,10 @@ type::Value FunctionExpression::Evaluate( for (auto &child : children_) { child_values.push_back(child->Evaluate(tuple1, tuple2, context)); } - uint64_t ctx = (uint64_t)context; - child_values.push_back(type::ValueFactory::GetBigIntValue(ctx)); + 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/sequence_functions.cpp b/src/function/sequence_functions.cpp index 388c60c89e0..81fc6489f15 100644 --- a/src/function/sequence_functions.cpp +++ b/src/function/sequence_functions.cpp @@ -19,20 +19,25 @@ #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 { -type::Value OldEngineStringFunctions::Nextval( - UNUSED_ATTRIBUTE const std::vector &args) { - executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); - concurrency::TransactionContext* txn = ctx->GetTransaction(); - const char * sequence_name = args[0].GetAs(); +// The next value of the sequence +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(); + ->GetDatabaseObject(ctx.GetDatabaseName(), txn)->GetDatabaseOid(); + + // 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() @@ -40,34 +45,59 @@ type::Value OldEngineStringFunctions::Nextval( ->GetSequenceCatalog() ->GetSequence(database_oid, sequence_name, mini_txn); if (sequence_object != nullptr) { - int64_t val = sequence_object->GetNextVal(); + uint32_t val = sequence_object->GetNextVal(); + // insert the new copy of sequence into cache for future currval bool insert = txn->catalog_cache.InsertSequenceObject(sequence_object); PELOTON_ASSERT(insert); - txn_manager.CommitTransaction(mini_txn); - return type::ValueFactory::GetIntegerValue(val); + auto ret = txn_manager.CommitTransaction(mini_txn); + while (ret != ResultType::SUCCESS) { + ret = txn_manager.CommitTransaction(mini_txn); + } + return val; } else { throw SequenceException( StringUtil::Format("relation \"%s\" does not exist", sequence_name)); } } -type::Value OldEngineStringFunctions::Currval( - UNUSED_ATTRIBUTE const std::vector &args) { - executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); - concurrency::TransactionContext* txn = ctx->GetTransaction(); - const char * sequence_name = args[0].GetAs(); +// The next value of the sequence +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(); - auto sequence_object = txn->catalog_cache.GetSequenceObject(sequence_name, - database_oid); + ->GetDatabaseObject(ctx.GetDatabaseName(), txn)->GetDatabaseOid(); + // get the sequence copy from cache + auto sequence_object = txn-> + catalog_cache.GetSequenceObject(sequence_name, database_oid); if (sequence_object != nullptr) { - return type::ValueFactory::GetIntegerValue(sequence_object->GetCurrVal()); + return sequence_object->GetCurrVal(); } else { throw SequenceException( StringUtil::Format("relation \"%s\" does not exist", sequence_name)); } } +/*@brief get the incremented value for the specified sequence + * @param sequence name, executor context + * @return 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 get the current value for the specified sequence + * @param sequence name, executor context + * @return 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/function/string_functions.cpp b/src/function/string_functions.cpp index 960a01bd2de..841a9ee6e15 100644 --- a/src/function/string_functions.cpp +++ b/src/function/string_functions.cpp @@ -14,8 +14,6 @@ #include "common/macros.h" #include "executor/executor_context.h" -#include "catalog/catalog.h" -#include "catalog/database_catalog.h" namespace peloton { namespace function { diff --git a/src/include/catalog/catalog_cache.h b/src/include/catalog/catalog_cache.h index e57dfdd852a..b00ec7403c8 100644 --- a/src/include/catalog/catalog_cache.h +++ b/src/include/catalog/catalog_cache.h @@ -24,7 +24,7 @@ class PlanUtil; } // namespace planner namespace function { -class OldEngineStringFunctions; +class SequenceFunctions; } // namespace function namespace catalog { @@ -44,7 +44,7 @@ class CatalogCache { friend class IndexCatalogObject; friend class planner::PlanUtil; friend class SequenceCatalogObject; - friend class function::OldEngineStringFunctions; + friend class function::SequenceFunctions; public: CatalogCache() {} diff --git a/src/include/codegen/proxy/string_functions_proxy.h b/src/include/codegen/proxy/string_functions_proxy.h index 5868229e13b..1862db23db9 100644 --- a/src/include/codegen/proxy/string_functions_proxy.h +++ b/src/include/codegen/proxy/string_functions_proxy.h @@ -31,10 +31,6 @@ PROXY(StringFunctions) { DECLARE_METHOD(RTrim); DECLARE_METHOD(Substr); DECLARE_METHOD(Repeat); - - // Sequence-related functions - DECLARE_METHOD(Nextval); - DECLARE_METHOD(Currval); }; PROXY(StrWithLen) { diff --git a/src/include/common/internal_types.h b/src/include/common/internal_types.h index 180f31e915c..f5cfe76bde0 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -633,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); From 3d93dc625b9e366219ce9b6a3bcc118a3bcb8345 Mon Sep 17 00:00:00 2001 From: Peixin Sun Date: Sat, 5 May 2018 15:56:32 -0400 Subject: [PATCH 25/29] fix bug with nextval & currval. now support multi-session --- .vscode/settings.json | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 731524cd9dc..00000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "files.associations": { - "__functional_base": "cpp", - "__functional_base_03": "cpp", - "__hash_table": "cpp", - "__tree": "cpp", - "__tuple": "cpp", - "array": "cpp", - "chrono": "cpp", - "functional": "cpp", - "limits": "cpp", - "memory": "cpp", - "random": "cpp", - "ratio": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "__config": "cpp", - "cstddef": "cpp", - "exception": "cpp", - "initializer_list": "cpp", - "new": "cpp", - "stdexcept": "cpp", - "typeinfo": "cpp", - "slist": "cpp", - "cctype": "cpp", - "cstdlib": "cpp" - } -} \ No newline at end of file From fc4a3858b36320d2a6429a7b8649cfd9772e8e45 Mon Sep 17 00:00:00 2001 From: kzhou10 Date: Sat, 5 May 2018 16:34:55 -0400 Subject: [PATCH 26/29] fixing some comments --- src/function/sequence_functions.cpp | 28 +++++++++++++++-------- src/include/function/sequence_functions.h | 1 + 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/function/sequence_functions.cpp b/src/function/sequence_functions.cpp index 81fc6489f15..42e5f4c94ed 100644 --- a/src/function/sequence_functions.cpp +++ b/src/function/sequence_functions.cpp @@ -2,9 +2,9 @@ // // Peloton // -// string_functions.cpp +// sequence_functions.cpp // -// Identification: src/function/string_functions.cpp +// Identification: src/function/sequence_functions.cpp // // Copyright (c) 2015-2018, Carnegie Mellon University Database Group // @@ -24,7 +24,11 @@ namespace peloton { namespace function { -// The next value of the sequence +/*@brief The actual implementation to get the incremented value for the specified sequence + * @param sequence name, 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); @@ -56,11 +60,15 @@ uint32_t SequenceFunctions::Nextval(executor::ExecutorContext &ctx, return val; } else { throw SequenceException( - StringUtil::Format("relation \"%s\" does not exist", sequence_name)); + StringUtil::Format("Sequence \"%s\" does not exist", sequence_name.c_str())); } } -// The next value of the sequence +/*@brief The actual implementation to get the current value for the specified sequence + * @param sequence name, 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); @@ -75,13 +83,13 @@ uint32_t SequenceFunctions::Currval(executor::ExecutorContext &ctx, return sequence_object->GetCurrVal(); } else { throw SequenceException( - StringUtil::Format("relation \"%s\" does not exist", sequence_name)); + StringUtil::Format("Sequence \"%s\" does not exist", sequence_name.c_str())); } } -/*@brief get the incremented value for the specified sequence +/*@brief The wrapper function to get the incremented value for the specified sequence * @param sequence name, executor context - * @return nextval + * @return the result of executing NextVal */ type::Value SequenceFunctions::_Nextval(const std::vector &args) { executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); @@ -89,9 +97,9 @@ type::Value SequenceFunctions::_Nextval(const std::vector &args) { return type::ValueFactory::GetIntegerValue(ret); } -/*@brief get the current value for the specified sequence +/*@brief The wrapper function to get the current value for the specified sequence * @param sequence name, executor context - * @return currval + * @return the result of executing CurrVal */ type::Value SequenceFunctions::_Currval(const std::vector &args) { executor::ExecutorContext* ctx=(executor::ExecutorContext*)args[1].GetAs(); diff --git a/src/include/function/sequence_functions.h b/src/include/function/sequence_functions.h index 62783ffc221..a91faf5dffd 100644 --- a/src/include/function/sequence_functions.h +++ b/src/include/function/sequence_functions.h @@ -32,6 +32,7 @@ class SequenceFunctions { // 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); }; From 527bfc50da8189a449d9cb72eacd4b00195566b7 Mon Sep 17 00:00:00 2001 From: Peixin Sun Date: Sat, 5 May 2018 16:44:13 -0400 Subject: [PATCH 27/29] add an exception case for currval --- src/function/sequence_functions.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/function/sequence_functions.cpp b/src/function/sequence_functions.cpp index 42e5f4c94ed..1927377b814 100644 --- a/src/function/sequence_functions.cpp +++ b/src/function/sequence_functions.cpp @@ -60,7 +60,7 @@ uint32_t SequenceFunctions::Nextval(executor::ExecutorContext &ctx, return val; } else { throw SequenceException( - StringUtil::Format("Sequence \"%s\" does not exist", sequence_name.c_str())); + StringUtil::Format("Sequence \"%s\" does not exist", sequence_name)); } } @@ -82,8 +82,22 @@ uint32_t SequenceFunctions::Currval(executor::ExecutorContext &ctx, if (sequence_object != nullptr) { return sequence_object->GetCurrVal(); } else { - throw SequenceException( - StringUtil::Format("Sequence \"%s\" does not exist", sequence_name.c_str())); + // get sequence from catalog + sequence_object = + catalog::Catalog::GetInstance() + ->GetSystemCatalogs(database_oid) + ->GetSequenceCatalog() + ->GetSequence(database_oid, sequence_name, txn); + if (sequence_object != nullptr) { + // nextval not called brefore + throw SequenceException( + StringUtil::Format("Nextval never called for sequence \"%s\"", + sequence_name)); + } else { + // sequence does not exist + throw SequenceException( + StringUtil::Format("Sequence \"%s\" does not exist", sequence_name)); + } } } From 836ffc0ef59bf3b6d64582898c76f71d976bcf3e Mon Sep 17 00:00:00 2001 From: Bowen Deng Date: Sat, 5 May 2018 18:58:45 -0400 Subject: [PATCH 28/29] drop seq with errors --- src/catalog/sequence_catalog.cpp | 10 ++-- src/executor/drop_executor.cpp | 69 ++++++++++++---------------- src/include/executor/drop_executor.h | 4 +- src/include/parser/drop_statement.h | 13 +++++- src/parser/drop_statement.cpp | 8 ++++ src/planner/drop_plan.cpp | 7 +++ 6 files changed, 64 insertions(+), 47 deletions(-) diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index 19f7a409ae3..aaaa18e5b90 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -62,11 +62,11 @@ int64_t SequenceCatalogObject::GetNextVal() { seq_curr_val += seq_increment; } - bool status = Catalog::GetInstance() - ->GetSystemCatalogs(db_oid) - ->GetSequenceCatalog() - ->UpdateNextVal(seq_oid, seq_curr_val, txn_); - LOG_DEBUG("status of update pg_sequence: %d", status); + // bool status = Catalog::GetInstance() + // ->GetSystemCatalogs(db_oid) + // ->GetSequenceCatalog() + // ->UpdateNextVal(seq_oid, seq_curr_val, txn_); + // LOG_DEBUG("status of update pg_sequence: %d", status); return result; } diff --git a/src/executor/drop_executor.cpp b/src/executor/drop_executor.cpp index 0e5b2cea1f9..fb3aca7b6d2 100644 --- a/src/executor/drop_executor.cpp +++ b/src/executor/drop_executor.cpp @@ -65,10 +65,10 @@ bool DropExecutor::DExecute() { result = DropIndex(node, current_txn); break; } - case DropType::SEQUENCE:{ - result = DropSequence(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)); @@ -219,41 +219,32 @@ 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 schema_name = node.GetSchemaName(); - std::string table_name = node.GetTableName(); - std::string trigger_name = node.GetTriggerName(); - - auto table_object = catalog::Catalog::GetInstance()->GetTableObject( - database_name, schema_name, table_name, txn); - // drop trigger - ResultType result = - catalog::Catalog::GetInstance() - ->GetSystemCatalogs(table_object->GetDatabaseOid()) - ->GetTriggerCatalog() - ->DropTrigger(table_object->GetDatabaseOid(), - table_object->GetTableOid(), trigger_name, txn); - txn->SetResult(result); - if (txn->GetResult() == ResultType::SUCCESS) { - LOG_DEBUG("Dropping trigger succeeded!"); - - if (StatementCacheManager::GetStmtCacheManager().get()) { - oid_t table_id = table_object->GetTableOid(); - StatementCacheManager::GetStmtCacheManager()->InvalidateTableOid( - table_id); - } - } else if (txn->GetResult() == ResultType::FAILURE && node.IsMissing()) { - txn->SetResult(ResultType::SUCCESS); - LOG_TRACE("Dropping trigger Succeeded!"); - } else if (txn->GetResult() == ResultType::FAILURE && !node.IsMissing()) { - LOG_TRACE("Dropping trigger Failed!"); - } else { - LOG_TRACE("Result is: %s", ResultTypeToString(txn->GetResult()).c_str()); - } - 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 trigger 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; +// } diff --git a/src/include/executor/drop_executor.h b/src/include/executor/drop_executor.h index 8e792083518..a32164e968f 100644 --- a/src/include/executor/drop_executor.h +++ b/src/include/executor/drop_executor.h @@ -60,8 +60,8 @@ class DropExecutor : public AbstractExecutor { bool DropIndex(const planner::DropPlan &node, concurrency::TransactionContext *txn); - bool DropSequence(const planner::DropPlan &node, - concurrency::TransactionContext *txn); + // bool DropSequence(const planner::DropPlan &node, + // concurrency::TransactionContext *txn); private: ExecutorContext *context_; 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/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/planner/drop_plan.cpp b/src/planner/drop_plan.cpp index 34240f85cad..6e05312982b 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"); } } } From 5c760c662e322d90801f84a910d430a8a751a6ef Mon Sep 17 00:00:00 2001 From: Bowen Deng Date: Sat, 5 May 2018 22:30:33 -0400 Subject: [PATCH 29/29] drop seq with a bug about txn visibility --- src/catalog/sequence_catalog.cpp | 10 ++--- src/executor/drop_executor.cpp | 60 ++++++++++++++-------------- src/include/common/internal_types.h | 3 +- src/include/executor/drop_executor.h | 4 +- src/include/parser/postgresparser.h | 3 ++ src/parser/postgresparser.cpp | 12 ++++++ src/planner/drop_plan.cpp | 12 +++--- 7 files changed, 60 insertions(+), 44 deletions(-) diff --git a/src/catalog/sequence_catalog.cpp b/src/catalog/sequence_catalog.cpp index aaaa18e5b90..19f7a409ae3 100644 --- a/src/catalog/sequence_catalog.cpp +++ b/src/catalog/sequence_catalog.cpp @@ -62,11 +62,11 @@ int64_t SequenceCatalogObject::GetNextVal() { seq_curr_val += seq_increment; } - // bool status = Catalog::GetInstance() - // ->GetSystemCatalogs(db_oid) - // ->GetSequenceCatalog() - // ->UpdateNextVal(seq_oid, seq_curr_val, txn_); - // LOG_DEBUG("status of update pg_sequence: %d", status); + bool status = Catalog::GetInstance() + ->GetSystemCatalogs(db_oid) + ->GetSequenceCatalog() + ->UpdateNextVal(seq_oid, seq_curr_val, txn_); + LOG_DEBUG("status of update pg_sequence: %d", status); return result; } diff --git a/src/executor/drop_executor.cpp b/src/executor/drop_executor.cpp index fb3aca7b6d2..0135a286480 100644 --- a/src/executor/drop_executor.cpp +++ b/src/executor/drop_executor.cpp @@ -65,10 +65,10 @@ bool DropExecutor::DExecute() { result = DropIndex(node, current_txn); break; } - // case DropType::SEQUENCE:{ - // // result = DropSequence(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)); @@ -219,32 +219,32 @@ 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 trigger 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::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; +} diff --git a/src/include/common/internal_types.h b/src/include/common/internal_types.h index f5cfe76bde0..3648cc2001b 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -715,7 +715,8 @@ enum class QueryType { QUERY_CREATE_SCHEMA = 22, QUERY_CREATE_VIEW = 23, QUERY_EXPLAIN = 24, - QUERY_CREATE_SEQUENCE = 25 + QUERY_CREATE_SEQUENCE = 25, + QUERY_DROP_SEQUENCE = 26 }; std::string QueryTypeToString(QueryType query_type); QueryType StringToQueryType(std::string str); diff --git a/src/include/executor/drop_executor.h b/src/include/executor/drop_executor.h index a32164e968f..8e792083518 100644 --- a/src/include/executor/drop_executor.h +++ b/src/include/executor/drop_executor.h @@ -60,8 +60,8 @@ class DropExecutor : public AbstractExecutor { bool DropIndex(const planner::DropPlan &node, concurrency::TransactionContext *txn); - // bool DropSequence(const planner::DropPlan &node, - // concurrency::TransactionContext *txn); + bool DropSequence(const planner::DropPlan &node, + concurrency::TransactionContext *txn); private: ExecutorContext *context_; diff --git a/src/include/parser/postgresparser.h b/src/include/parser/postgresparser.h index 00507c22afa..56497e10225 100644 --- a/src/include/parser/postgresparser.h +++ b/src/include/parser/postgresparser.h @@ -257,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); diff --git a/src/parser/postgresparser.cpp b/src/parser/postgresparser.cpp index 5f9fdc9a7c3..453e2bcb651 100644 --- a/src/parser/postgresparser.cpp +++ b/src/parser/postgresparser.cpp @@ -1422,6 +1422,8 @@ parser::DropStatement *PostgresParser::DropTransform(DropStmt *root) { 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: @@ -1495,6 +1497,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); diff --git a/src/planner/drop_plan.cpp b/src/planner/drop_plan.cpp index 6e05312982b..21e92cfcc9a 100644 --- a/src/planner/drop_plan.cpp +++ b/src/planner/drop_plan.cpp @@ -64,12 +64,12 @@ 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; - // } + 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"); } }