From 5e5d0ae35bc1a4cb082a2d6f941a64a3da592eed Mon Sep 17 00:00:00 2001 From: vagrant <411468452@qq.com> Date: Sun, 6 May 2018 12:00:27 -0400 Subject: [PATCH 01/13] Handle explain plan in the optimizer --- src/include/common/internal_types.h | 1 + src/include/optimizer/optimizer.h | 30 ++++++------ src/include/planner/explain_plan.h | 60 ++++++++++++++++++++++++ src/optimizer/optimizer.cpp | 71 +++++++++++++++-------------- 4 files changed, 113 insertions(+), 49 deletions(-) create mode 100644 src/include/planner/explain_plan.h diff --git a/src/include/common/internal_types.h b/src/include/common/internal_types.h index 17020512944..ba35695c2c2 100644 --- a/src/include/common/internal_types.h +++ b/src/include/common/internal_types.h @@ -596,6 +596,7 @@ enum class PlanNodeType { RESULT = 70, COPY = 71, CREATE_FUNC = 72, + EXPLAIN = 73, // Test MOCK = 80 diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h index 82b1d4c9a05..baeb8720be3 100644 --- a/src/include/optimizer/optimizer.h +++ b/src/include/optimizer/optimizer.h @@ -38,9 +38,9 @@ class TransactionContext; } namespace test { - class OptimizerRuleTests_SimpleAssociativeRuleTest_Test; - class OptimizerRuleTests_SimpleAssociativeRuleTest2_Test; -} +class OptimizerRuleTests_SimpleAssociativeRuleTest_Test; +class OptimizerRuleTests_SimpleAssociativeRuleTest2_Test; +} namespace optimizer { @@ -60,8 +60,10 @@ class Optimizer : public AbstractOptimizer { friend class BindingIterator; friend class GroupBindingIterator; - friend class ::peloton::test::OptimizerRuleTests_SimpleAssociativeRuleTest_Test; - friend class ::peloton::test::OptimizerRuleTests_SimpleAssociativeRuleTest2_Test; + friend class ::peloton::test:: + OptimizerRuleTests_SimpleAssociativeRuleTest_Test; + friend class ::peloton::test:: + OptimizerRuleTests_SimpleAssociativeRuleTest2_Test; public: Optimizer(const Optimizer &) = delete; @@ -83,27 +85,25 @@ class Optimizer : public AbstractOptimizer { OptimizerMetadata &GetMetadata() { return metadata_; } /* For test purposes only */ - std::shared_ptr TestInsertQueryTree(parser::SQLStatement *tree, - concurrency::TransactionContext *txn) { + std::shared_ptr TestInsertQueryTree( + parser::SQLStatement *tree, concurrency::TransactionContext *txn) { return InsertQueryTree(tree, txn); } /* For test purposes only */ void TestExecuteTaskStack(OptimizerTaskStack &task_stack, int root_group_id, - std::shared_ptr root_context) { + std::shared_ptr root_context) { return ExecuteTaskStack(task_stack, root_group_id, root_context); } private: - /* HandleDDLStatement - Check and handle DDL statment (currently only support + /* HandleUtilStatement - Check and handle Util statment (currently only + *support *CREATE), set - * is_ddl_stmt to false if there is no DDL statement. - * * tree: a peloton query tree representing a select query - * return: the DDL plan if it is a DDL statement + * return: the util plan if it is a util statement */ - std::unique_ptr HandleDDLStatement( - parser::SQLStatement *tree, bool &is_ddl_stmt, - concurrency::TransactionContext *txn); + std::unique_ptr HandleUtilStatement( + parser::SQLStatement *tree, concurrency::TransactionContext *txn); /* TransformQueryTree - create an initial operator tree for the given query * to be used in performing optimization. diff --git a/src/include/planner/explain_plan.h b/src/include/planner/explain_plan.h new file mode 100644 index 00000000000..372b491ee2f --- /dev/null +++ b/src/include/planner/explain_plan.h @@ -0,0 +1,60 @@ + +//===----------------------------------------------------------------------===// +// +// Peloton +// +// explain_plan.h +// +// Identification: src/include/planner/analyze_plan.h +// +// Copyright (c) 2015-18, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "planner/abstract_plan.h" + +#include + +namespace peloton { +namespace storage { +class DataTable; +} +namespace parser { +class AnalyzeStatement; +} +namespace catalog { +class Schema; +} +namespace concurrency { +class TransactionContext; +} + +namespace planner { +class ExplainPlan : public AbstractPlan { + public: + ExplainPlan(const ExplainPlan &) = delete; + ExplainPlan &operator=(const ExplainPlan &) = delete; + ExplainPlan(ExplainPlan &&) = delete; + ExplainPlan &operator=(ExplainPlan &&) = delete; + + explicit ExplainPlan(parser::SQLStatement *sql_stmt) : sql_stmt(sql_stmt){}; + + inline PlanNodeType GetPlanNodeType() const { return PlanNodeType::EXPLAIN; } + + const std::string GetInfo() const { return "Explain table"; } + + inline std::unique_ptr Copy() const { + return std::unique_ptr(new ExplainPlan(sql_stmt)); + } + + private: + /** + * @brief The SQL statement to explain (owned by the AST) + */ + parser::SQLStatement *sql_stmt; +}; + +} // namespace planner +} // namespace peloton diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index 62f813ec876..8a8277fe5de 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -37,6 +37,7 @@ #include "planner/create_function_plan.h" #include "planner/create_plan.h" #include "planner/drop_plan.h" +#include "planner/explain_plan.h" #include "planner/order_by_plan.h" #include "planner/populate_index_plan.h" #include "planner/projection_plan.h" @@ -103,10 +104,9 @@ shared_ptr Optimizer::BuildPelotonPlanTree( unique_ptr child_plan = nullptr; // Handle ddl statement - bool is_ddl_stmt; - auto ddl_plan = HandleDDLStatement(parse_tree, is_ddl_stmt, txn); - if (is_ddl_stmt) { - return move(ddl_plan); + auto util_plan = HandleUtilStatement(parse_tree, txn); + if (util_plan != nullptr) { + return move(util_plan); } metadata_.txn = txn; @@ -138,11 +138,9 @@ shared_ptr Optimizer::BuildPelotonPlanTree( void Optimizer::Reset() { metadata_ = OptimizerMetadata(); } -unique_ptr Optimizer::HandleDDLStatement( - parser::SQLStatement *tree, bool &is_ddl_stmt, - concurrency::TransactionContext *txn) { +unique_ptr Optimizer::HandleUtilStatement( + parser::SQLStatement *tree, concurrency::TransactionContext *txn) { unique_ptr ddl_plan = nullptr; - is_ddl_stmt = true; auto stmt_type = tree->GetType(); switch (stmt_type) { case StatementType::DROP: { @@ -221,8 +219,14 @@ unique_ptr Optimizer::HandleDDLStatement( ddl_plan = util::CreateCopyPlan(copy_parse_tree); break; } + case StatementType::EXPLAIN: { + LOG_TRACE("Adding Explain plan..."); + // Pass the sql statement to explain to the plan node + ddl_plan.reset(new planner::ExplainPlan( + static_cast(tree)->real_sql_stmt.get())); + } default: - is_ddl_stmt = false; + break; } return ddl_plan; } @@ -238,29 +242,29 @@ shared_ptr Optimizer::InsertQueryTree( } QueryInfo Optimizer::GetQueryInfo(parser::SQLStatement *tree) { - auto GetQueryInfoHelper = - [](std::vector> &select_list, - std::unique_ptr &order_info, - std::vector &output_exprs, - std::shared_ptr &physical_props) { - // Extract output column - for (auto &expr : select_list) output_exprs.push_back(expr.get()); - - // Extract sort property - if (order_info != nullptr) { - std::vector sort_exprs; - std::vector sort_ascending; - for (auto &expr : order_info->exprs) { - sort_exprs.push_back(expr.get()); - } - for (auto &type : order_info->types) { - sort_ascending.push_back(type == parser::kOrderAsc); - } - if (!sort_exprs.empty()) - physical_props->AddProperty( - std::make_shared(sort_exprs, sort_ascending)); - } - }; + auto GetQueryInfoHelper = []( + std::vector> &select_list, + std::unique_ptr &order_info, + std::vector &output_exprs, + std::shared_ptr &physical_props) { + // Extract output column + for (auto &expr : select_list) output_exprs.push_back(expr.get()); + + // Extract sort property + if (order_info != nullptr) { + std::vector sort_exprs; + std::vector sort_ascending; + for (auto &expr : order_info->exprs) { + sort_exprs.push_back(expr.get()); + } + for (auto &type : order_info->types) { + sort_ascending.push_back(type == parser::kOrderAsc); + } + if (!sort_exprs.empty()) + physical_props->AddProperty( + std::make_shared(sort_exprs, sort_ascending)); + } + }; std::vector output_exprs; std::shared_ptr physical_props = std::make_shared(); @@ -278,8 +282,7 @@ QueryInfo Optimizer::GetQueryInfo(parser::SQLStatement *tree) { output_exprs, physical_props); break; } - default: - ; + default:; } return QueryInfo(output_exprs, physical_props); From 7e87de0c2e2124f5438ff29329d46ce96b13068c Mon Sep 17 00:00:00 2001 From: Tianyi Chen Date: Mon, 7 May 2018 09:45:47 -0400 Subject: [PATCH 02/13] Refactor the execute method interface for traffic cop. --- .../network/postgres_protocol_handler.h | 3 -- src/include/traffic_cop/traffic_cop.h | 18 ++++++------ src/network/postgres_protocol_handler.cpp | 25 ++++++++--------- src/traffic_cop/traffic_cop.cpp | 20 ++++++++----- test/sql/testing_sql_util.cpp | 28 ++++++++++++------- 5 files changed, 52 insertions(+), 42 deletions(-) diff --git a/src/include/network/postgres_protocol_handler.h b/src/include/network/postgres_protocol_handler.h index ef75f0a4cb1..672ab8c29c6 100644 --- a/src/include/network/postgres_protocol_handler.h +++ b/src/include/network/postgres_protocol_handler.h @@ -215,9 +215,6 @@ class PostgresProtocolHandler : public ProtocolHandler { // Portals std::unordered_map> portals_; - // packets ready for read - size_t pkt_cntr_; - // Manage parameter types for unnamed statement stats::QueryMetric::QueryParamBuf unnamed_stmt_param_types_; diff --git a/src/include/traffic_cop/traffic_cop.h b/src/include/traffic_cop/traffic_cop.h index e324b87fe82..a4e932558ff 100644 --- a/src/include/traffic_cop/traffic_cop.h +++ b/src/include/traffic_cop/traffic_cop.h @@ -65,12 +65,16 @@ class TrafficCop { void Reset(); // Execute a statement - ResultType ExecuteStatement( - const std::shared_ptr &statement, - const std::vector ¶ms, const bool unnamed, - std::shared_ptr param_stats, - const std::vector &result_format, std::vector &result, - size_t thread_id = 0); + ResultType ExecuteStatement(std::shared_ptr param_stats, + const std::vector &result_format, + size_t thread_id); + + ResultType ExecuteStatement(const std::shared_ptr &statement, + const std::vector ¶ms, + std::shared_ptr param_stats, + const std::vector &result_format, + std::vector &result, + size_t thread_id); // Helper to handle txn-specifics for the plan-tree of a statement. executor::ExecutionResult ExecuteHelper( @@ -156,8 +160,6 @@ class TrafficCop { std::vector param_values_; - std::vector results_; - // This save currnet statement in the traffic cop std::shared_ptr statement_; diff --git a/src/network/postgres_protocol_handler.cpp b/src/network/postgres_protocol_handler.cpp index ffbb786b88e..7ddce1f605a 100644 --- a/src/network/postgres_protocol_handler.cpp +++ b/src/network/postgres_protocol_handler.cpp @@ -212,10 +212,9 @@ ProcessResult PostgresProtocolHandler::ExecQueryMessage( return ProcessResult::COMPLETE; } - bool unnamed = false; - auto status = traffic_cop_->ExecuteStatement( - traffic_cop_->GetStatement(), traffic_cop_->GetParamVal(), unnamed, - nullptr, result_format_, traffic_cop_->GetResult(), thread_id); + auto status = traffic_cop_->ExecuteStatement(nullptr, + result_format_, + thread_id); if (traffic_cop_->GetQueuing()) { return ProcessResult::PROCESSING; } @@ -229,25 +228,24 @@ ProcessResult PostgresProtocolHandler::ExecQueryMessage( return ProcessResult::COMPLETE; } default: { - std::string stmt_name = "unamed"; + std::string stmt_name = ""; std::unique_ptr unnamed_sql_stmt_list( new parser::SQLStatementList()); unnamed_sql_stmt_list->PassInStatement(std::move(sql_stmt)); traffic_cop_->SetStatement(traffic_cop_->PrepareStatement( stmt_name, query, std::move(unnamed_sql_stmt_list))); - if (traffic_cop_->GetStatement().get() == nullptr) { + if (traffic_cop_->GetStatement() == nullptr) { SendErrorResponse({{NetworkMessageType::HUMAN_READABLE_ERROR, traffic_cop_->GetErrorMessage()}}); SendReadyForQuery(NetworkTransactionStateType::IDLE); return ProcessResult::COMPLETE; } traffic_cop_->SetParamVal(std::vector()); - bool unnamed = false; result_format_ = std::vector( traffic_cop_->GetStatement()->GetTupleDescriptor().size(), 0); - auto status = traffic_cop_->ExecuteStatement( - traffic_cop_->GetStatement(), traffic_cop_->GetParamVal(), unnamed, - nullptr, result_format_, traffic_cop_->GetResult(), thread_id); + auto status = traffic_cop_->ExecuteStatement(nullptr, + result_format_, + thread_id); if (traffic_cop_->GetQueuing()) { return ProcessResult::PROCESSING; } @@ -807,12 +805,11 @@ ProcessResult PostgresProtocolHandler::ExecExecuteMessage( } auto statement_name = traffic_cop_->GetStatement()->GetStatementName(); - bool unnamed = statement_name.empty(); traffic_cop_->SetParamVal(portal->GetParameters()); - auto status = traffic_cop_->ExecuteStatement( - traffic_cop_->GetStatement(), traffic_cop_->GetParamVal(), unnamed, - param_stat, result_format_, traffic_cop_->GetResult(), thread_id); + auto status = traffic_cop_->ExecuteStatement(param_stat, + result_format_, + thread_id); if (traffic_cop_->GetQueuing()) { return ProcessResult::PROCESSING; } diff --git a/src/traffic_cop/traffic_cop.cpp b/src/traffic_cop/traffic_cop.cpp index a87d99c0ac5..6e173308c95 100644 --- a/src/traffic_cop/traffic_cop.cpp +++ b/src/traffic_cop/traffic_cop.cpp @@ -44,7 +44,7 @@ void TrafficCop::Reset() { // clear out the stack swap(tcop_txn_state_, new_tcop_txn_state); optimizer_->Reset(); - results_.clear(); + result_.clear(); param_values_.clear(); setRowsAffected(0); } @@ -543,12 +543,18 @@ FieldInfo TrafficCop::GetColumnFieldForValueType(std::string column_name, field_size); } -ResultType TrafficCop::ExecuteStatement( - const std::shared_ptr &statement, - const std::vector ¶ms, UNUSED_ATTRIBUTE bool unnamed, - std::shared_ptr param_stats, - const std::vector &result_format, std::vector &result, - size_t thread_id) { +ResultType TrafficCop::ExecuteStatement(std::shared_ptr param_stats, + const std::vector &result_format, + size_t thread_id) { + return ExecuteStatement(statement_, param_values_, param_stats, result_format, result_, thread_id); +} + +ResultType TrafficCop::ExecuteStatement(const std::shared_ptr &statement, + const std::vector ¶ms, + std::shared_ptr param_stats, + const std::vector &result_format, + std::vector &result, + size_t thread_id) { // TODO(Tianyi) Further simplify this API if (static_cast(settings::SettingsManager::GetInt( settings::SettingId::stats_mode)) != StatsType::INVALID) { diff --git a/test/sql/testing_sql_util.cpp b/test/sql/testing_sql_util.cpp index 220fa558686..b17130d3892 100644 --- a/test/sql/testing_sql_util.cpp +++ b/test/sql/testing_sql_util.cpp @@ -76,12 +76,15 @@ ResultType TestingSQLUtil::ExecuteSQLQuery( } // ExecuteStatment std::vector param_values; - bool unnamed = false; std::vector result_format(statement->GetTupleDescriptor().size(), 0); // SetTrafficCopCounter(); counter_.store(1); - auto status = traffic_cop_.ExecuteStatement(statement, param_values, unnamed, - nullptr, result_format, result); + auto status = traffic_cop_.ExecuteStatement(statement, + param_values, + nullptr, + result_format, + result, + 0); if (traffic_cop_.GetQueuing()) { ContinueAfterComplete(); traffic_cop_.ExecuteStatementPlanGetResult(); @@ -177,12 +180,15 @@ ResultType TestingSQLUtil::ExecuteSQLQuery(const std::string query, } // ExecuteStatment std::vector param_values; - bool unnamed = false; std::vector result_format(statement->GetTupleDescriptor().size(), 0); // SetTrafficCopCounter(); counter_.store(1); - auto status = traffic_cop_.ExecuteStatement(statement, param_values, unnamed, - nullptr, result_format, result); + auto status = traffic_cop_.ExecuteStatement(statement, + param_values, + nullptr, + result_format, + result, + 0); if (traffic_cop_.GetQueuing()) { ContinueAfterComplete(); traffic_cop_.ExecuteStatementPlanGetResult(); @@ -216,12 +222,14 @@ ResultType TestingSQLUtil::ExecuteSQLQuery(const std::string query) { } // ExecuteStatment std::vector param_values; - bool unnamed = false; std::vector result_format(statement->GetTupleDescriptor().size(), 0); - // SetTrafficCopCounter(); counter_.store(1); - auto status = traffic_cop_.ExecuteStatement(statement, param_values, unnamed, - nullptr, result_format, result); + auto status = traffic_cop_.ExecuteStatement(statement, + param_values, + nullptr, + result_format, + result, + 0); if (traffic_cop_.GetQueuing()) { ContinueAfterComplete(); traffic_cop_.ExecuteStatementPlanGetResult(); From 5ba06db3a1fb3537ba9f807a0ce29b61a4980140 Mon Sep 17 00:00:00 2001 From: Tianyi Chen Date: Mon, 7 May 2018 11:03:41 -0400 Subject: [PATCH 03/13] Unify traffic_cop getResult interface --- src/include/traffic_cop/traffic_cop.h | 7 --- src/network/connection_handle.cpp | 1 - src/network/postgres_protocol_handler.cpp | 1 - src/traffic_cop/traffic_cop.cpp | 59 +++++++++++------------ test/binder/binder_test.cpp | 3 +- test/executor/copy_test.cpp | 3 +- test/executor/create_index_test.cpp | 9 ++-- test/executor/delete_test.cpp | 21 +++----- test/executor/update_test.cpp | 15 ++---- test/optimizer/old_optimizer_test.cpp | 9 ++-- test/optimizer/optimizer_test.cpp | 15 ++---- test/sql/testing_sql_util.cpp | 13 ++--- 12 files changed, 58 insertions(+), 98 deletions(-) diff --git a/src/include/traffic_cop/traffic_cop.h b/src/include/traffic_cop/traffic_cop.h index a4e932558ff..98f6592203d 100644 --- a/src/include/traffic_cop/traffic_cop.h +++ b/src/include/traffic_cop/traffic_cop.h @@ -104,7 +104,6 @@ class TrafficCop { ResultType CommitQueryHelper(); - void ExecuteStatementPlanGetResult(); ResultType ExecuteStatementGetResult(); @@ -135,8 +134,6 @@ class TrafficCop { param_values_ = std::move(param_values); } - std::vector &GetParamVal() { return param_values_; } - std::string &GetErrorMessage() { return error_message_; } void SetQueuing(bool is_queuing) { is_queuing_ = is_queuing; } @@ -149,10 +146,6 @@ class TrafficCop { default_database_name_ = std::move(default_database_name); } - // TODO: this member variable should be in statement_ after parser part - // finished - std::string query_; - private: bool is_queuing_; diff --git a/src/network/connection_handle.cpp b/src/network/connection_handle.cpp index e79564b5c4d..3b1918e0d36 100644 --- a/src/network/connection_handle.cpp +++ b/src/network/connection_handle.cpp @@ -692,7 +692,6 @@ Transition ConnectionHandle::GetResult() { PELOTON_ASSERT(false); } protocol_handler_->GetResult(); - traffic_cop_.SetQueuing(false); return Transition::PROCEED; } } // namespace network diff --git a/src/network/postgres_protocol_handler.cpp b/src/network/postgres_protocol_handler.cpp index 7ddce1f605a..c3593e027d2 100644 --- a/src/network/postgres_protocol_handler.cpp +++ b/src/network/postgres_protocol_handler.cpp @@ -859,7 +859,6 @@ void PostgresProtocolHandler::ExecExecuteMessageGetResult(ResultType status) { } void PostgresProtocolHandler::GetResult() { - traffic_cop_->ExecuteStatementPlanGetResult(); auto status = traffic_cop_->ExecuteStatementGetResult(); switch (protocol_type_) { case NetworkProtocolType::POSTGRES_JDBC: diff --git a/src/traffic_cop/traffic_cop.cpp b/src/traffic_cop/traffic_cop.cpp index 6e173308c95..7ba9fe051ac 100644 --- a/src/traffic_cop/traffic_cop.cpp +++ b/src/traffic_cop/traffic_cop.cpp @@ -133,10 +133,38 @@ ResultType TrafficCop::AbortQueryHelper() { ResultType TrafficCop::ExecuteStatementGetResult() { LOG_TRACE("Statement executed. Result: %s", - ResultTypeToString(p_status_.m_result).c_str()); + ResultTypeToString(p_status_.m_result).c_str()); setRowsAffected(p_status_.m_processed); LOG_TRACE("rows_changed %d", p_status_.m_processed); is_queuing_ = false; + + if (p_status_.m_result == ResultType::FAILURE) return p_status_.m_result; + + auto txn_result = GetCurrentTxnState().first->GetResult(); + if (single_statement_txn_ || txn_result == ResultType::FAILURE) { + LOG_TRACE("About to commit/abort: single stmt: %d,txn_result: %s", + single_statement_txn_, ResultTypeToString(txn_result).c_str()); + switch (txn_result) { + case ResultType::SUCCESS: + // Commit single statement + LOG_TRACE("Commit Transaction"); + p_status_.m_result = CommitQueryHelper(); + break; + + case ResultType::FAILURE: + default: + // Abort + LOG_TRACE("Abort Transaction"); + if (single_statement_txn_) { + LOG_TRACE("Tcop_txn_state size: %lu", tcop_txn_state_.size()); + p_status_.m_result = AbortQueryHelper(); + } else { + tcop_txn_state_.top().second = ResultType::ABORTED; + p_status_.m_result = ResultType::ABORTED; + } + } + } + return p_status_.m_result; } @@ -203,35 +231,6 @@ executor::ExecutionResult TrafficCop::ExecuteHelper( return p_status_; } -void TrafficCop::ExecuteStatementPlanGetResult() { - if (p_status_.m_result == ResultType::FAILURE) return; - - auto txn_result = GetCurrentTxnState().first->GetResult(); - if (single_statement_txn_ || txn_result == ResultType::FAILURE) { - LOG_TRACE("About to commit/abort: single stmt: %d,txn_result: %s", - single_statement_txn_, ResultTypeToString(txn_result).c_str()); - switch (txn_result) { - case ResultType::SUCCESS: - // Commit single statement - LOG_TRACE("Commit Transaction"); - p_status_.m_result = CommitQueryHelper(); - break; - - case ResultType::FAILURE: - default: - // Abort - LOG_TRACE("Abort Transaction"); - if (single_statement_txn_) { - LOG_TRACE("Tcop_txn_state size: %lu", tcop_txn_state_.size()); - p_status_.m_result = AbortQueryHelper(); - } else { - tcop_txn_state_.top().second = ResultType::ABORTED; - p_status_.m_result = ResultType::ABORTED; - } - } - } -} - /* * Prepare a statement based on parse tree. Begin a transaction if necessary. * If the query is not issued in a transaction (if txn_stack is empty and it's diff --git a/test/binder/binder_test.cpp b/test/binder/binder_test.cpp index b82df1ec72a..7d93c443827 100644 --- a/test/binder/binder_test.cpp +++ b/test/binder/binder_test.cpp @@ -91,9 +91,8 @@ void SetupTables(std::string database_name) { result, result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Table create result: %s", ResultTypeToString(status.m_result).c_str()); diff --git a/test/executor/copy_test.cpp b/test/executor/copy_test.cpp index 77c1c9eecc9..0274925a93c 100644 --- a/test/executor/copy_test.cpp +++ b/test/executor/copy_test.cpp @@ -97,9 +97,8 @@ TEST_F(CopyTests, Copying) { if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } EXPECT_EQ(status.m_result, peloton::ResultType::SUCCESS); diff --git a/test/executor/create_index_test.cpp b/test/executor/create_index_test.cpp index 034eca553fa..68f51456e23 100644 --- a/test/executor/create_index_test.cpp +++ b/test/executor/create_index_test.cpp @@ -104,9 +104,8 @@ TEST_F(CreateIndexTests, CreatingIndex) { if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", @@ -152,9 +151,8 @@ TEST_F(CreateIndexTests, CreatingIndex) { if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -194,9 +192,8 @@ TEST_F(CreateIndexTests, CreatingIndex) { if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); diff --git a/test/executor/delete_test.cpp b/test/executor/delete_test.cpp index f081b766720..1fa29a6a70c 100644 --- a/test/executor/delete_test.cpp +++ b/test/executor/delete_test.cpp @@ -84,9 +84,8 @@ void ShowTable(std::string database_name, std::string table_name) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } traffic_cop.CommitQueryHelper(); } @@ -165,9 +164,8 @@ TEST_F(DeleteTests, VariousOperations) { statement->GetPlanTree(), params, result, result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -206,9 +204,8 @@ TEST_F(DeleteTests, VariousOperations) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -247,9 +244,8 @@ TEST_F(DeleteTests, VariousOperations) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -290,9 +286,8 @@ TEST_F(DeleteTests, VariousOperations) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -328,9 +323,8 @@ TEST_F(DeleteTests, VariousOperations) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -368,9 +362,8 @@ TEST_F(DeleteTests, VariousOperations) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); diff --git a/test/executor/update_test.cpp b/test/executor/update_test.cpp index f8f3c12d0a2..3c16ae8b532 100644 --- a/test/executor/update_test.cpp +++ b/test/executor/update_test.cpp @@ -231,9 +231,8 @@ TEST_F(UpdateTests, UpdatingOld) { statement->GetPlanTree(), params, result, result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -275,9 +274,8 @@ TEST_F(UpdateTests, UpdatingOld) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -320,9 +318,8 @@ TEST_F(UpdateTests, UpdatingOld) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -359,9 +356,8 @@ TEST_F(UpdateTests, UpdatingOld) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -401,9 +397,8 @@ TEST_F(UpdateTests, UpdatingOld) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); diff --git a/test/optimizer/old_optimizer_test.cpp b/test/optimizer/old_optimizer_test.cpp index 1069ab87909..b1060503812 100644 --- a/test/optimizer/old_optimizer_test.cpp +++ b/test/optimizer/old_optimizer_test.cpp @@ -91,9 +91,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { statement->GetPlanTree(), params, result, result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_TRACE("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -128,9 +127,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_TRACE("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -160,9 +158,8 @@ TEST_F(OldOptimizerTests, UpdateDelWithIndexScanTest) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_TRACE("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); diff --git a/test/optimizer/optimizer_test.cpp b/test/optimizer/optimizer_test.cpp index dae410999d6..09acba53398 100644 --- a/test/optimizer/optimizer_test.cpp +++ b/test/optimizer/optimizer_test.cpp @@ -110,9 +110,8 @@ TEST_F(OptimizerTests, HashJoinTest) { statement->GetPlanTree(), params, result, result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -146,9 +145,8 @@ TEST_F(OptimizerTests, HashJoinTest) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -182,9 +180,8 @@ TEST_F(OptimizerTests, HashJoinTest) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -212,9 +209,8 @@ TEST_F(OptimizerTests, HashJoinTest) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); @@ -241,9 +237,8 @@ TEST_F(OptimizerTests, HashJoinTest) { result_format); if (traffic_cop.GetQueuing()) { TestingSQLUtil::ContinueAfterComplete(); - traffic_cop.ExecuteStatementPlanGetResult(); + traffic_cop.ExecuteStatementGetResult(); status = traffic_cop.p_status_; - traffic_cop.SetQueuing(false); } LOG_INFO("Statement executed. Result: %s", ResultTypeToString(status.m_result).c_str()); diff --git a/test/sql/testing_sql_util.cpp b/test/sql/testing_sql_util.cpp index b17130d3892..b7546870e51 100644 --- a/test/sql/testing_sql_util.cpp +++ b/test/sql/testing_sql_util.cpp @@ -87,9 +87,7 @@ ResultType TestingSQLUtil::ExecuteSQLQuery( 0); if (traffic_cop_.GetQueuing()) { ContinueAfterComplete(); - traffic_cop_.ExecuteStatementPlanGetResult(); status = traffic_cop_.ExecuteStatementGetResult(); - traffic_cop_.SetQueuing(false); } if (status == ResultType::SUCCESS) { tuple_descriptor = statement->GetTupleDescriptor(); @@ -128,11 +126,11 @@ ResultType TestingSQLUtil::ExecuteSQLQueryWithOptimizer( counter_.store(1); auto status = traffic_cop_.ExecuteHelper(plan, params, result, result_format); + if (traffic_cop_.GetQueuing()) { - TestingSQLUtil::ContinueAfterComplete(); - traffic_cop_.ExecuteStatementPlanGetResult(); + ContinueAfterComplete(); + traffic_cop_.ExecuteStatementGetResult(); status = traffic_cop_.p_status_; - traffic_cop_.SetQueuing(false); } rows_changed = status.m_processed; LOG_INFO("Statement executed. Result: %s", @@ -191,9 +189,7 @@ ResultType TestingSQLUtil::ExecuteSQLQuery(const std::string query, 0); if (traffic_cop_.GetQueuing()) { ContinueAfterComplete(); - traffic_cop_.ExecuteStatementPlanGetResult(); status = traffic_cop_.ExecuteStatementGetResult(); - traffic_cop_.SetQueuing(false); } if (status == ResultType::SUCCESS) { tuple_descriptor = statement->GetTupleDescriptor(); @@ -232,10 +228,9 @@ ResultType TestingSQLUtil::ExecuteSQLQuery(const std::string query) { 0); if (traffic_cop_.GetQueuing()) { ContinueAfterComplete(); - traffic_cop_.ExecuteStatementPlanGetResult(); status = traffic_cop_.ExecuteStatementGetResult(); - traffic_cop_.SetQueuing(false); } + if (status == ResultType::SUCCESS) { tuple_descriptor = statement->GetTupleDescriptor(); } From d0b9ae247be7f95094d357d8a418ab705a1cd3a9 Mon Sep 17 00:00:00 2001 From: Tianyi Chen Date: Mon, 7 May 2018 16:05:57 -0400 Subject: [PATCH 04/13] Naming fix --- src/include/planner/explain_plan.h | 2 +- src/optimizer/optimizer.cpp | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/include/planner/explain_plan.h b/src/include/planner/explain_plan.h index 372b491ee2f..1de7f65b55c 100644 --- a/src/include/planner/explain_plan.h +++ b/src/include/planner/explain_plan.h @@ -5,7 +5,7 @@ // // explain_plan.h // -// Identification: src/include/planner/analyze_plan.h +// Identification: src/include/planner/explain_plan.h // // Copyright (c) 2015-18, Carnegie Mellon University Database Group // diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index 8a8277fe5de..35fdfacc4a4 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -140,14 +140,14 @@ void Optimizer::Reset() { metadata_ = OptimizerMetadata(); } unique_ptr Optimizer::HandleUtilStatement( parser::SQLStatement *tree, concurrency::TransactionContext *txn) { - unique_ptr ddl_plan = nullptr; + unique_ptr util_plan = nullptr; auto stmt_type = tree->GetType(); switch (stmt_type) { case StatementType::DROP: { LOG_TRACE("Adding Drop plan..."); unique_ptr drop_plan( new planner::DropPlan((parser::DropStatement *)tree)); - ddl_plan = move(drop_plan); + util_plan = move(drop_plan); break; } @@ -158,7 +158,7 @@ unique_ptr Optimizer::HandleUtilStatement( auto create_plan = new planner::CreatePlan((parser::CreateStatement *)tree); std::unique_ptr child_CreatePlan(create_plan); - ddl_plan = move(child_CreatePlan); + util_plan = move(child_CreatePlan); if (create_plan->GetCreateType() == peloton::CreateType::INDEX) { auto create_stmt = (parser::CreateStatement *)tree; @@ -184,14 +184,14 @@ unique_ptr Optimizer::HandleUtilStatement( std::unique_ptr child_SeqScanPlan( new planner::SeqScanPlan(target_table, nullptr, column_ids, false)); - child_SeqScanPlan->AddChild(std::move(ddl_plan)); - ddl_plan = std::move(child_SeqScanPlan); + child_SeqScanPlan->AddChild(std::move(util_plan)); + util_plan = std::move(child_SeqScanPlan); // Create a plan to add data to index std::unique_ptr child_PopulateIndexPlan( new planner::PopulateIndexPlan(target_table, column_ids)); - child_PopulateIndexPlan->AddChild(std::move(ddl_plan)); + child_PopulateIndexPlan->AddChild(std::move(util_plan)); create_plan->SetKeyAttrs(column_ids); - ddl_plan = std::move(child_PopulateIndexPlan); + util_plan = std::move(child_PopulateIndexPlan); } break; } @@ -203,32 +203,32 @@ unique_ptr Optimizer::HandleUtilStatement( unique_ptr create_func_plan( new planner::CreateFunctionPlan( (parser::CreateFunctionStatement *)tree)); - ddl_plan = move(create_func_plan); + util_plan = move(create_func_plan); } break; case StatementType::ANALYZE: { LOG_TRACE("Adding Analyze plan..."); unique_ptr analyze_plan(new planner::AnalyzePlan( static_cast(tree), txn)); - ddl_plan = move(analyze_plan); + util_plan = move(analyze_plan); break; } case StatementType::COPY: { LOG_TRACE("Adding Copy plan..."); parser::CopyStatement *copy_parse_tree = static_cast(tree); - ddl_plan = util::CreateCopyPlan(copy_parse_tree); + util_plan = util::CreateCopyPlan(copy_parse_tree); break; } case StatementType::EXPLAIN: { LOG_TRACE("Adding Explain plan..."); // Pass the sql statement to explain to the plan node - ddl_plan.reset(new planner::ExplainPlan( + util_plan.reset(new planner::ExplainPlan( static_cast(tree)->real_sql_stmt.get())); } default: break; } - return ddl_plan; + return util_plan; } shared_ptr Optimizer::InsertQueryTree( From 5d8919d3fa8caad61b32445dec5e8a20a7db2146 Mon Sep 17 00:00:00 2001 From: vagrant <411468452@qq.com> Date: Mon, 7 May 2018 23:30:50 -0400 Subject: [PATCH 05/13] Add explain support in executor, not tested yet --- src/binder/bind_node_visitor.cpp | 4 +- src/executor/explain_executor.cpp | 72 +++++++++++++++++++++++++ src/executor/plan_executor.cpp | 3 ++ src/include/binder/bind_node_visitor.h | 1 + src/include/executor/executors.h | 1 + src/include/executor/explain_executor.h | 46 ++++++++++++++++ src/include/parser/explain_statement.h | 6 +++ src/include/planner/explain_plan.h | 17 ++++-- src/optimizer/optimizer.cpp | 6 ++- src/planner/analyze_plan.cpp | 2 +- 10 files changed, 151 insertions(+), 7 deletions(-) create mode 100644 src/executor/explain_executor.cpp create mode 100644 src/include/executor/explain_executor.h diff --git a/src/binder/bind_node_visitor.cpp b/src/binder/bind_node_visitor.cpp index a6ffe17b322..3aca3f9071d 100644 --- a/src/binder/bind_node_visitor.cpp +++ b/src/binder/bind_node_visitor.cpp @@ -191,7 +191,9 @@ void BindNodeVisitor::Visit(parser::AnalyzeStatement *node) { node->TryBindDatabaseName(default_database_name_); } -// void BindNodeVisitor::Visit(const parser::ConstantValueExpression *) {} +void BindNodeVisitor::Visit(parser::ExplainStatement *node) { + node->default_database_name = default_database_name_; +} void BindNodeVisitor::Visit(expression::TupleValueExpression *expr) { if (!expr->GetIsBound()) { diff --git a/src/executor/explain_executor.cpp b/src/executor/explain_executor.cpp new file mode 100644 index 00000000000..4bc7ceb9880 --- /dev/null +++ b/src/executor/explain_executor.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// explain_executor.cpp +// +// Identification: src/executor/explain_executor.cpp +// +// Copyright (c) 2015-18, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include + +#include "binder/bind_node_visitor.h" +#include "catalog/catalog.h" +#include "catalog/column.h" +#include "catalog/schema.h" +#include "concurrency/transaction_manager_factory.h" +#include "common/logger.h" +#include "executor/explain_executor.h" +#include "executor/executor_context.h" +#include "executor/logical_tile_factory.h" +#include "optimizer/optimizer.h" +#include "storage/tile.h" +#include "type/type.h" + +namespace peloton { +namespace executor { + +bool ExplainExecutor::DInit() { + LOG_TRACE("Initializing explain executor..."); + LOG_TRACE("Explain executor initialized!"); + return true; +} + +bool ExplainExecutor::DExecute() { + LOG_TRACE("Executing Explain..."); + + const planner::ExplainPlan &node = GetPlanNode(); + + parser::SQLStatement *sql_stmt = node.GetSQLStatement(); + + // LOG_TRACE("Analyzing column size %lu", target_columns.size()); + + auto current_txn = executor_context_->GetTransaction(); + + auto bind_node_visitor = + binder::BindNodeVisitor(current_txn, node.GetDatabaseName()); + + // Bind, optimize and return the plan as a string + bind_node_visitor.BindNameToNode(sql_stmt); + std::unique_ptr optimizer(new optimizer::Optimizer()); + std::unique_ptr stmt_list( + new parser::SQLStatementList(sql_stmt)); + auto plan = optimizer->BuildPelotonPlanTree(stmt_list, current_txn); + const catalog::Schema schema({catalog::Column( + type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), + "Query Plan")}); + std::shared_ptr dest_tile( + storage::TileFactory::GetTempTile(schema, 1)); + std::unique_ptr buffer(new storage::Tuple(&schema, true)); + buffer->SetValue(0, type::ValueFactory::GetVarcharValue(plan->GetInfo())); + dest_tile->InsertTuple(0, buffer.get()); + SetOutput(LogicalTileFactory::WrapTiles({dest_tile})); + + LOG_TRACE("Explain finished!"); + return false; +} + +} // namespace executor +} // namespace peloton diff --git a/src/executor/plan_executor.cpp b/src/executor/plan_executor.cpp index 104aff1351c..9191fbf83bc 100644 --- a/src/executor/plan_executor.cpp +++ b/src/executor/plan_executor.cpp @@ -336,6 +336,9 @@ executor::AbstractExecutor *BuildExecutorTree( child_executor = new executor::PopulateIndexExecutor(plan, executor_context); break; + case PlanNodeType::EXPLAIN: + child_executor = + new executor::ExplainExecutor(plan, executor_context); default: LOG_ERROR("Unsupported plan node type : %s", diff --git a/src/include/binder/bind_node_visitor.h b/src/include/binder/bind_node_visitor.h index 9ca09c68693..5f24ea27563 100644 --- a/src/include/binder/bind_node_visitor.h +++ b/src/include/binder/bind_node_visitor.h @@ -67,6 +67,7 @@ class BindNodeVisitor : public SqlNodeVisitor { void Visit(parser::UpdateStatement *) override; void Visit(parser::CopyStatement *) override; void Visit(parser::AnalyzeStatement *) override; + void Visit(parser::ExplainStatement *) override; void Visit(expression::CaseExpression *expr) override; void Visit(expression::SubqueryExpression *expr) override; diff --git a/src/include/executor/executors.h b/src/include/executor/executors.h index 16614120444..fbfb77860d2 100644 --- a/src/include/executor/executors.h +++ b/src/include/executor/executors.h @@ -21,6 +21,7 @@ #include "executor/copy_executor.h" #include "executor/create_executor.h" #include "executor/create_function_executor.h" +#include "executor/explain_executor.h" #include "executor/delete_executor.h" #include "executor/drop_executor.h" #include "executor/hash_executor.h" diff --git a/src/include/executor/explain_executor.h b/src/include/executor/explain_executor.h new file mode 100644 index 00000000000..f5e6bb4f2ae --- /dev/null +++ b/src/include/executor/explain_executor.h @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// explain_executor.h +// +// Identification: src/include/executor/explain_executor.h +// +// Copyright (c) 2015-18, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "executor/abstract_executor.h" +#include "planner/explain_plan.h" + +namespace peloton { + +namespace storage { +class DataTable; +} + +namespace executor { + +class ExplainExecutor : public AbstractExecutor { + public: + ExplainExecutor(const ExplainExecutor &) = delete; + ExplainExecutor &operator=(const ExplainExecutor &) = delete; + ExplainExecutor(ExplainExecutor &&) = delete; + ExplainExecutor &operator=(ExplainExecutor &&) = delete; + + ExplainExecutor(const planner::AbstractPlan *node, + ExecutorContext *executor_context) + : AbstractExecutor(node, executor_context) {} + + ~ExplainExecutor() {} + + protected: + bool DInit(); + + bool DExecute(); +}; + +} // namespace executor +} // namespace peloton diff --git a/src/include/parser/explain_statement.h b/src/include/parser/explain_statement.h index 5d3e763f9dc..e0497a60484 100644 --- a/src/include/parser/explain_statement.h +++ b/src/include/parser/explain_statement.h @@ -29,6 +29,12 @@ class ExplainStatement : public SQLStatement { void Accept(SqlNodeVisitor *v) override { v->Visit(this); } std::unique_ptr real_sql_stmt; + + /** + * @brief Should be set by the binder, used in the executor to bind the stmt + * being explained + */ + std::string default_database_name; }; } // namespace parser diff --git a/src/include/planner/explain_plan.h b/src/include/planner/explain_plan.h index 1de7f65b55c..b517809535f 100644 --- a/src/include/planner/explain_plan.h +++ b/src/include/planner/explain_plan.h @@ -39,21 +39,32 @@ class ExplainPlan : public AbstractPlan { ExplainPlan(ExplainPlan &&) = delete; ExplainPlan &operator=(ExplainPlan &&) = delete; - explicit ExplainPlan(parser::SQLStatement *sql_stmt) : sql_stmt(sql_stmt){}; + explicit ExplainPlan(parser::SQLStatement *sql_stmt, + std::string default_database_name) + : sql_stmt_(sql_stmt), default_database_name_(default_database_name){}; inline PlanNodeType GetPlanNodeType() const { return PlanNodeType::EXPLAIN; } const std::string GetInfo() const { return "Explain table"; } inline std::unique_ptr Copy() const { - return std::unique_ptr(new ExplainPlan(sql_stmt)); + return std::unique_ptr( + new ExplainPlan(sql_stmt_, default_database_name_)); } + parser::SQLStatement *GetSQLStatement() const { return sql_stmt_; } + + std::string GetDatabaseName() const { return default_database_name_; } + private: /** * @brief The SQL statement to explain (owned by the AST) */ - parser::SQLStatement *sql_stmt; + parser::SQLStatement *sql_stmt_; + /** + * @brief The database name to be used in the binder + */ + std::string default_database_name_; }; } // namespace planner diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index 35fdfacc4a4..76195ae7193 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -222,8 +222,10 @@ unique_ptr Optimizer::HandleUtilStatement( case StatementType::EXPLAIN: { LOG_TRACE("Adding Explain plan..."); // Pass the sql statement to explain to the plan node - util_plan.reset(new planner::ExplainPlan( - static_cast(tree)->real_sql_stmt.get())); + auto *explain_parse_tree = static_cast(tree); + util_plan.reset( + new planner::ExplainPlan(explain_parse_tree->real_sql_stmt.get(), + explain_parse_tree->default_database_name)); } default: break; diff --git a/src/planner/analyze_plan.cpp b/src/planner/analyze_plan.cpp index 5de53476b14..07c200d2b98 100644 --- a/src/planner/analyze_plan.cpp +++ b/src/planner/analyze_plan.cpp @@ -4,7 +4,7 @@ // // analyze_plan.cpp // -// Identification: src/planner/Analyze_plan.cpp +// Identification: src/planner/analyze_plan.cpp // // Copyright (c) 2015-16, Carnegie Mellon University Database Group // From f4fdd3994f2bb1f8f6cb10457a844784b9c15d0a Mon Sep 17 00:00:00 2001 From: vagrant <411468452@qq.com> Date: Tue, 8 May 2018 14:23:11 -0400 Subject: [PATCH 06/13] Add a test and fix several bugs, still breaking because the ownership of the sql statement's not correctly set --- src/common/internal_types.cpp | 3 ++ src/executor/explain_executor.cpp | 4 +- src/executor/plan_executor.cpp | 2 +- src/include/planner/explain_plan.h | 24 +++++----- src/optimizer/optimizer.cpp | 5 ++- src/traffic_cop/traffic_cop.cpp | 33 +++++++++----- test/sql/explain_sql_test.cpp | 72 ++++++++++++++++++++++++++++++ 7 files changed, 113 insertions(+), 30 deletions(-) create mode 100644 test/sql/explain_sql_test.cpp diff --git a/src/common/internal_types.cpp b/src/common/internal_types.cpp index 6d95bf1a35c..3899daad63e 100644 --- a/src/common/internal_types.cpp +++ b/src/common/internal_types.cpp @@ -1391,6 +1391,9 @@ std::string PlanNodeTypeToString(PlanNodeType type) { case PlanNodeType::ANALYZE: { return ("ANALYZE"); } + case PlanNodeType::EXPLAIN: { + return ("EXPLAIN"); + } default: { throw ConversionException( StringUtil::Format("No string conversion for PlanNodeType value '%d'", diff --git a/src/executor/explain_executor.cpp b/src/executor/explain_executor.cpp index 4bc7ceb9880..d190117b760 100644 --- a/src/executor/explain_executor.cpp +++ b/src/executor/explain_executor.cpp @@ -41,7 +41,7 @@ bool ExplainExecutor::DExecute() { parser::SQLStatement *sql_stmt = node.GetSQLStatement(); - // LOG_TRACE("Analyzing column size %lu", target_columns.size()); + LOG_TRACE("EXPLAIN : %s", sql_stmt->GetInfo().c_str()); auto current_txn = executor_context_->GetTransaction(); @@ -65,7 +65,7 @@ bool ExplainExecutor::DExecute() { SetOutput(LogicalTileFactory::WrapTiles({dest_tile})); LOG_TRACE("Explain finished!"); - return false; + return true; } } // namespace executor diff --git a/src/executor/plan_executor.cpp b/src/executor/plan_executor.cpp index 9191fbf83bc..7d9a0640c8f 100644 --- a/src/executor/plan_executor.cpp +++ b/src/executor/plan_executor.cpp @@ -339,7 +339,7 @@ executor::AbstractExecutor *BuildExecutorTree( case PlanNodeType::EXPLAIN: child_executor = new executor::ExplainExecutor(plan, executor_context); - + break; default: LOG_ERROR("Unsupported plan node type : %s", PlanNodeTypeToString(plan_node_type).c_str()); diff --git a/src/include/planner/explain_plan.h b/src/include/planner/explain_plan.h index b517809535f..30d9dfd8c28 100644 --- a/src/include/planner/explain_plan.h +++ b/src/include/planner/explain_plan.h @@ -13,20 +13,12 @@ #pragma once +#include "parser/sql_statement.h" #include "planner/abstract_plan.h" #include namespace peloton { -namespace storage { -class DataTable; -} -namespace parser { -class AnalyzeStatement; -} -namespace catalog { -class Schema; -} namespace concurrency { class TransactionContext; } @@ -39,20 +31,26 @@ class ExplainPlan : public AbstractPlan { ExplainPlan(ExplainPlan &&) = delete; ExplainPlan &operator=(ExplainPlan &&) = delete; - explicit ExplainPlan(parser::SQLStatement *sql_stmt, + explicit ExplainPlan(std::unique_ptr sql_stmt, + std::string default_database_name) + : sql_stmt_(sql_stmt.release()), + default_database_name_(default_database_name){}; + + explicit ExplainPlan(std::shared_ptr sql_stmt, std::string default_database_name) : sql_stmt_(sql_stmt), default_database_name_(default_database_name){}; inline PlanNodeType GetPlanNodeType() const { return PlanNodeType::EXPLAIN; } - const std::string GetInfo() const { return "Explain table"; } + const std::string GetInfo() const { return std::string("Explain") + sql_stmt_->GetInfo(); } inline std::unique_ptr Copy() const { + // FIXME: support deep copy for sql statement, then use a unique_ptr here return std::unique_ptr( new ExplainPlan(sql_stmt_, default_database_name_)); } - parser::SQLStatement *GetSQLStatement() const { return sql_stmt_; } + parser::SQLStatement *GetSQLStatement() const { return sql_stmt_.get(); } std::string GetDatabaseName() const { return default_database_name_; } @@ -60,7 +58,7 @@ class ExplainPlan : public AbstractPlan { /** * @brief The SQL statement to explain (owned by the AST) */ - parser::SQLStatement *sql_stmt_; + std::shared_ptr sql_stmt_; /** * @brief The database name to be used in the binder */ diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index 76195ae7193..30ea3072915 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -222,9 +222,10 @@ unique_ptr Optimizer::HandleUtilStatement( case StatementType::EXPLAIN: { LOG_TRACE("Adding Explain plan..."); // Pass the sql statement to explain to the plan node - auto *explain_parse_tree = static_cast(tree); + auto *explain_parse_tree = + reinterpret_cast(tree); util_plan.reset( - new planner::ExplainPlan(explain_parse_tree->real_sql_stmt.get(), + new planner::ExplainPlan(std::move(explain_parse_tree->real_sql_stmt), explain_parse_tree->default_database_name)); } default: diff --git a/src/traffic_cop/traffic_cop.cpp b/src/traffic_cop/traffic_cop.cpp index 7ba9fe051ac..fe47dd2a78f 100644 --- a/src/traffic_cop/traffic_cop.cpp +++ b/src/traffic_cop/traffic_cop.cpp @@ -133,7 +133,7 @@ ResultType TrafficCop::AbortQueryHelper() { ResultType TrafficCop::ExecuteStatementGetResult() { LOG_TRACE("Statement executed. Result: %s", - ResultTypeToString(p_status_.m_result).c_str()); + ResultTypeToString(p_status_.m_result).c_str()); setRowsAffected(p_status_.m_processed); LOG_TRACE("rows_changed %d", p_status_.m_processed); is_queuing_ = false; @@ -441,7 +441,15 @@ void TrafficCop::GetTableColumns(parser::TableRef *from_table, std::vector TrafficCop::GenerateTupleDescriptor( parser::SQLStatement *sql_stmt) { std::vector tuple_descriptor; - if (sql_stmt->GetType() != StatementType::SELECT) return tuple_descriptor; + // EXPLAIN returns a the query plan string as a tuple + if (sql_stmt->GetType() == StatementType::EXPLAIN) { + tuple_descriptor.push_back( + GetColumnFieldForValueType("Query Plan", type::TypeId::VARCHAR)); + return tuple_descriptor; + } + if (sql_stmt->GetType() != StatementType::SELECT) { + return tuple_descriptor; + } auto select_stmt = (parser::SelectStatement *)sql_stmt; // TODO: this is a hack which I don't have time to fix now @@ -542,18 +550,19 @@ FieldInfo TrafficCop::GetColumnFieldForValueType(std::string column_name, field_size); } -ResultType TrafficCop::ExecuteStatement(std::shared_ptr param_stats, - const std::vector &result_format, - size_t thread_id) { - return ExecuteStatement(statement_, param_values_, param_stats, result_format, result_, thread_id); +ResultType TrafficCop::ExecuteStatement( + std::shared_ptr param_stats, + const std::vector &result_format, size_t thread_id) { + return ExecuteStatement(statement_, param_values_, param_stats, result_format, + result_, thread_id); } -ResultType TrafficCop::ExecuteStatement(const std::shared_ptr &statement, - const std::vector ¶ms, - std::shared_ptr param_stats, - const std::vector &result_format, - std::vector &result, - size_t thread_id) { +ResultType TrafficCop::ExecuteStatement( + const std::shared_ptr &statement, + const std::vector ¶ms, + std::shared_ptr param_stats, + const std::vector &result_format, std::vector &result, + size_t thread_id) { // TODO(Tianyi) Further simplify this API if (static_cast(settings::SettingsManager::GetInt( settings::SettingId::stats_mode)) != StatsType::INVALID) { diff --git a/test/sql/explain_sql_test.cpp b/test/sql/explain_sql_test.cpp new file mode 100644 index 00000000000..09c91bf42b5 --- /dev/null +++ b/test/sql/explain_sql_test.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// explain_sql_test.cpp +// +// Identification: test/sql/explain_sql_test.cpp +// +// Copyright (c) 2015-18, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include + +#include "catalog/catalog.h" +#include "catalog/column_stats_catalog.h" +#include "common/harness.h" +#include "common/internal_types.h" +#include "concurrency/transaction_manager_factory.h" +#include "executor/create_executor.h" +#include "optimizer/optimizer.h" +#include "planner/create_plan.h" +#include "sql/testing_sql_util.h" + +namespace peloton { +namespace test { + +class ExplainSQLTests : public PelotonTest {}; + +void CreateAndLoadTable() { + // Create a table first + TestingSQLUtil::ExecuteSQLQuery( + "CREATE TABLE test(a INT PRIMARY KEY, b INT, c INT, d VARCHAR);"); + + // Insert tuples into table + TestingSQLUtil::ExecuteSQLQuery( + "INSERT INTO test VALUES (1, 22, 333, 'abcd');"); + TestingSQLUtil::ExecuteSQLQuery( + "INSERT INTO test VALUES (2, 22, 333, 'abc');"); + TestingSQLUtil::ExecuteSQLQuery( + "INSERT INTO test VALUES (3, 11, 222, 'abcd');"); +} + +TEST_F(ExplainSQLTests, ExplainSelectTest) { + auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance(); + auto txn = txn_manager.BeginTransaction(); + catalog::Catalog::GetInstance()->CreateDatabase(DEFAULT_DB_NAME, txn); + txn_manager.CommitTransaction(txn); + + CreateAndLoadTable(); + std::unique_ptr optimizer( + new optimizer::Optimizer()); + const std::string query = "EXPLAIN SELECT * FROM test"; + std::vector result; + std::vector tuple_descriptor; + int rows_changed; + std::string error_message; + // Execute explain + TestingSQLUtil::ExecuteSQLQueryWithOptimizer( + optimizer, query, result, tuple_descriptor, rows_changed, error_message); + + EXPECT_EQ(result.size(), 1); + EXPECT_EQ(result[0], ""); + + // Free the database + txn = txn_manager.BeginTransaction(); + catalog::Catalog::GetInstance()->DropDatabaseWithName(DEFAULT_DB_NAME, txn); + txn_manager.CommitTransaction(txn); +} + +} // namespace test +} // namespace peloton From fa2f942cb04347f832cf53d26f6f6a81f5db41f5 Mon Sep 17 00:00:00 2001 From: vagrant <411468452@qq.com> Date: Wed, 9 May 2018 21:50:55 -0400 Subject: [PATCH 07/13] Fix double delete in the test case, the cause is not clear though --- src/executor/explain_executor.cpp | 4 ++-- src/include/planner/explain_plan.h | 22 ++++++++-------------- src/optimizer/optimizer.cpp | 5 ++++- test/sql/explain_sql_test.cpp | 2 +- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/executor/explain_executor.cpp b/src/executor/explain_executor.cpp index d190117b760..30dd4283c4f 100644 --- a/src/executor/explain_executor.cpp +++ b/src/executor/explain_executor.cpp @@ -64,8 +64,8 @@ bool ExplainExecutor::DExecute() { dest_tile->InsertTuple(0, buffer.get()); SetOutput(LogicalTileFactory::WrapTiles({dest_tile})); - LOG_TRACE("Explain finished!"); - return true; + LOG_TRACE("Explain finished!, plan : %s", plan->GetInfo().c_str()); + return false; } } // namespace executor diff --git a/src/include/planner/explain_plan.h b/src/include/planner/explain_plan.h index 30d9dfd8c28..98390508d5e 100644 --- a/src/include/planner/explain_plan.h +++ b/src/include/planner/explain_plan.h @@ -19,9 +19,6 @@ #include namespace peloton { -namespace concurrency { -class TransactionContext; -} namespace planner { class ExplainPlan : public AbstractPlan { @@ -31,34 +28,31 @@ class ExplainPlan : public AbstractPlan { ExplainPlan(ExplainPlan &&) = delete; ExplainPlan &operator=(ExplainPlan &&) = delete; - explicit ExplainPlan(std::unique_ptr sql_stmt, - std::string default_database_name) - : sql_stmt_(sql_stmt.release()), - default_database_name_(default_database_name){}; - - explicit ExplainPlan(std::shared_ptr sql_stmt, + explicit ExplainPlan(parser::SQLStatement *sql_stmt, std::string default_database_name) : sql_stmt_(sql_stmt), default_database_name_(default_database_name){}; inline PlanNodeType GetPlanNodeType() const { return PlanNodeType::EXPLAIN; } - const std::string GetInfo() const { return std::string("Explain") + sql_stmt_->GetInfo(); } + const std::string GetInfo() const { + return std::string("Explain") + sql_stmt_->GetInfo(); + } inline std::unique_ptr Copy() const { - // FIXME: support deep copy for sql statement, then use a unique_ptr here return std::unique_ptr( new ExplainPlan(sql_stmt_, default_database_name_)); } - parser::SQLStatement *GetSQLStatement() const { return sql_stmt_.get(); } + parser::SQLStatement *GetSQLStatement() const { return sql_stmt_; } std::string GetDatabaseName() const { return default_database_name_; } private: /** - * @brief The SQL statement to explain (owned by the AST) + * @brief The SQL statement to explain, the it should be owned by the + * explain ast */ - std::shared_ptr sql_stmt_; + parser::SQLStatement *sql_stmt_; /** * @brief The database name to be used in the binder */ diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index 30ea3072915..5a2fb2bc434 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -225,7 +225,10 @@ unique_ptr Optimizer::HandleUtilStatement( auto *explain_parse_tree = reinterpret_cast(tree); util_plan.reset( - new planner::ExplainPlan(std::move(explain_parse_tree->real_sql_stmt), + // TODO(boweic): not releasing this unique_ptr here would cause a + // double delete which I still don't know why is happening. + // I believe no one should take the ownership of the pointer here + new planner::ExplainPlan(explain_parse_tree->real_sql_stmt.release(), explain_parse_tree->default_database_name)); } default: diff --git a/test/sql/explain_sql_test.cpp b/test/sql/explain_sql_test.cpp index 09c91bf42b5..93ecba24071 100644 --- a/test/sql/explain_sql_test.cpp +++ b/test/sql/explain_sql_test.cpp @@ -60,7 +60,7 @@ TEST_F(ExplainSQLTests, ExplainSelectTest) { optimizer, query, result, tuple_descriptor, rows_changed, error_message); EXPECT_EQ(result.size(), 1); - EXPECT_EQ(result[0], ""); + EXPECT_EQ(result[0], "SeqScan()"); // Free the database txn = txn_manager.BeginTransaction(); From 3f67dcef32176f2c08dc38c8ae7b85bbe42a0539 Mon Sep 17 00:00:00 2001 From: vagrant <411468452@qq.com> Date: Wed, 9 May 2018 21:56:53 -0400 Subject: [PATCH 08/13] Remove explain hack in the protocol handler --- .../network/postgres_protocol_handler.h | 8 ----- src/network/postgres_protocol_handler.cpp | 30 ------------------- 2 files changed, 38 deletions(-) diff --git a/src/include/network/postgres_protocol_handler.h b/src/include/network/postgres_protocol_handler.h index 672ab8c29c6..b225aa4123d 100644 --- a/src/include/network/postgres_protocol_handler.h +++ b/src/include/network/postgres_protocol_handler.h @@ -31,10 +31,6 @@ namespace peloton { -namespace parser { -class ExplainStatement; -} // namespace parser - namespace network { typedef std::vector> ResponseBuffer; @@ -165,10 +161,6 @@ class PostgresProtocolHandler : public ProtocolHandler { /* Execute a Simple query protocol message */ ProcessResult ExecQueryMessage(InputPacket *pkt, const size_t thread_id); - /* Execute a EXPLAIN query message */ - ResultType ExecQueryExplain(const std::string &query, - parser::ExplainStatement &explain_stmt); - /* Process the PARSE message of the extended query protocol */ void ExecParseMessage(InputPacket *pkt); diff --git a/src/network/postgres_protocol_handler.cpp b/src/network/postgres_protocol_handler.cpp index c3593e027d2..a989bfedf63 100644 --- a/src/network/postgres_protocol_handler.cpp +++ b/src/network/postgres_protocol_handler.cpp @@ -221,12 +221,6 @@ ProcessResult PostgresProtocolHandler::ExecQueryMessage( ExecQueryMessageGetResult(status); return ProcessResult::COMPLETE; }; - case QueryType::QUERY_EXPLAIN: { - auto status = ExecQueryExplain( - query, static_cast(*sql_stmt)); - ExecQueryMessageGetResult(status); - return ProcessResult::COMPLETE; - } default: { std::string stmt_name = ""; std::unique_ptr unnamed_sql_stmt_list( @@ -255,30 +249,6 @@ ProcessResult PostgresProtocolHandler::ExecQueryMessage( } } -ResultType PostgresProtocolHandler::ExecQueryExplain( - const std::string &query, parser::ExplainStatement &explain_stmt) { - std::unique_ptr unnamed_sql_stmt_list( - new parser::SQLStatementList()); - unnamed_sql_stmt_list->PassInStatement(std::move(explain_stmt.real_sql_stmt)); - auto stmt = traffic_cop_->PrepareStatement( - "explain", query, std::move(unnamed_sql_stmt_list)); - ResultType status = ResultType::UNKNOWN; - if (stmt != nullptr) { - traffic_cop_->SetStatement(stmt); - std::vector plan_info = StringUtil::Split( - planner::PlanUtil::GetInfo(stmt->GetPlanTree().get()), '\n'); - const std::vector tuple_descriptor = { - traffic_cop_->GetColumnFieldForValueType("Query plan", - type::TypeId::VARCHAR)}; - stmt->SetTupleDescriptor(tuple_descriptor); - traffic_cop_->SetResult(plan_info); - status = ResultType::SUCCESS; - } else { - status = ResultType::FAILURE; - } - return status; -} - void PostgresProtocolHandler::ExecQueryMessageGetResult(ResultType status) { std::vector tuple_descriptor; if (status == ResultType::SUCCESS) { From 2a3813e368f02d68670a11d8d410f062f41159a7 Mon Sep 17 00:00:00 2001 From: Tianyi Chen Date: Fri, 11 May 2018 00:21:55 -0400 Subject: [PATCH 09/13] Add Explain for query descriptor --- src/traffic_cop/traffic_cop.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/traffic_cop/traffic_cop.cpp b/src/traffic_cop/traffic_cop.cpp index fe47dd2a78f..592ebe1d076 100644 --- a/src/traffic_cop/traffic_cop.cpp +++ b/src/traffic_cop/traffic_cop.cpp @@ -325,7 +325,8 @@ std::shared_ptr TrafficCop::PrepareStatement( planner::PlanUtil::GetTablesReferenced(plan.get()); statement->SetReferencedTables(table_oids); - if (query_type == QueryType::QUERY_SELECT) { + if (query_type == QueryType::QUERY_SELECT || + query_type == QueryType::QUERY_EXPLAIN) { auto tuple_descriptor = GenerateTupleDescriptor( statement->GetStmtParseTreeList()->GetStatement(0)); statement->SetTupleDescriptor(tuple_descriptor); @@ -365,8 +366,8 @@ void TrafficCop::ProcessInvalidStatement() { } bool TrafficCop::BindParamsForCachePlan( - const std::vector> - ¶meters, + const std::vector> & + parameters, const size_t thread_id UNUSED_ATTRIBUTE) { if (tcop_txn_state_.empty()) { single_statement_txn_ = true; From ac7185a9b7420156db9a197b1af73d96a84d579c Mon Sep 17 00:00:00 2001 From: vagrant <411468452@qq.com> Date: Thu, 10 May 2018 12:11:14 -0400 Subject: [PATCH 10/13] Add a network test for EXPLAIN --- src/executor/explain_executor.cpp | 2 +- test/network/explain_test.cpp | 105 ++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 test/network/explain_test.cpp diff --git a/src/executor/explain_executor.cpp b/src/executor/explain_executor.cpp index 30dd4283c4f..88e4fac38b4 100644 --- a/src/executor/explain_executor.cpp +++ b/src/executor/explain_executor.cpp @@ -64,7 +64,7 @@ bool ExplainExecutor::DExecute() { dest_tile->InsertTuple(0, buffer.get()); SetOutput(LogicalTileFactory::WrapTiles({dest_tile})); - LOG_TRACE("Explain finished!, plan : %s", plan->GetInfo().c_str()); + LOG_DEBUG("Explain finished!, plan : %s", plan->GetInfo().c_str()); return false; } diff --git a/test/network/explain_test.cpp b/test/network/explain_test.cpp new file mode 100644 index 00000000000..b6d7f193b7d --- /dev/null +++ b/test/network/explain_test.cpp @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// explain_test.cpp +// +// Identification: test/network/explain_test.cpp +// +// Copyright (c) 2016-18, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include "common/harness.h" +#include "gtest/gtest.h" +#include "common/logger.h" +#include "network/peloton_server.h" +#include "network/protocol_handler_factory.h" +#include "network/connection_handle_factory.h" +#include "util/string_util.h" +#include /* libpqxx is used to instantiate C++ client */ +#include "network/postgres_protocol_handler.h" + +namespace peloton { +namespace test { + +//===--------------------------------------------------------------------===// +// Explain Tests +//===--------------------------------------------------------------------===// + +class ExplainTests : public PelotonTest {}; + +/** + * Explain Test + * Test how the network layer handle explain + */ +void *ExplainTest(int port) { + try { + // forcing the factory to generate psql protocol handler + pqxx::connection C( + StringUtil::Format("host=127.0.0.1 port=%d user=default_database " + "sslmode=disable application_name=psql", + port)); + pqxx::work txn1(C); + peloton::network::ConnectionHandle *conn = + peloton::network::ConnectionHandleFactory::GetInstance() + .ConnectionHandleAt(peloton::network::PelotonServer::recent_connfd) + .get(); + + network::PostgresProtocolHandler *handler = + dynamic_cast( + conn->GetProtocolHandler().get()); + EXPECT_NE(handler, nullptr); + + // create table and insert some data + txn1.exec("DROP TABLE IF EXISTS template;"); + txn1.exec("CREATE TABLE template(id INT);"); + txn1.commit(); + + // Execute EXPLAIN directly + pqxx::work txn2(C); + pqxx::result result1 = txn2.exec("EXPLAIN SELECT * from template;"); + txn2.commit(); + EXPECT_EQ(result1.size(), 1); + + // Execute EXPLAIN through PREPARE statement + pqxx::work txn3(C); + txn3.exec("PREPARE func AS EXPLAIN SELECT * from template;"); + pqxx::result result2 = txn3.exec("EXECUTE func"); + txn3.commit(); + EXPECT_EQ(result2.size(), 1); + } catch (const std::exception &e) { + LOG_INFO("[ExplainTest] Exception occurred: %s", e.what()); + EXPECT_TRUE(false); + } + + LOG_INFO("[ExplainTest] Client has closed"); + return NULL; +} + +TEST_F(ExplainTests, ExplainTest) { + peloton::PelotonInit::Initialize(); + LOG_INFO("Server initialized"); + peloton::network::PelotonServer server; + + int port = 15721; + try { + server.SetPort(port); + server.SetupServer(); + } catch (peloton::ConnectionException &exception) { + LOG_INFO("[LaunchServer] exception when launching server"); + } + std::thread serverThread([&]() { server.ServerLoop(); }); + + // server & client running correctly + ExplainTest(port); + + server.Close(); + serverThread.join(); + LOG_INFO("Peloton is shutting down"); + peloton::PelotonInit::Shutdown(); + LOG_INFO("Peloton has shut down"); +} + +} // namespace test +} // namespace peloton From ae8f0380e46c4f682cb599c0071f0020681bc868 Mon Sep 17 00:00:00 2001 From: vagrant <411468452@qq.com> Date: Thu, 10 May 2018 14:00:59 -0400 Subject: [PATCH 11/13] Fix the newly added test --- src/include/optimizer/optimizer.h | 12 ++++++-- src/include/parser/explain_statement.h | 4 +++ src/optimizer/optimizer.cpp | 41 ++++++++++++++------------ src/parser/explain_statement.cpp | 37 +++++++++++++++++++++++ test/network/explain_test.cpp | 13 +++----- 5 files changed, 76 insertions(+), 31 deletions(-) create mode 100644 src/parser/explain_statement.cpp diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h index baeb8720be3..d5de41412b8 100644 --- a/src/include/optimizer/optimizer.h +++ b/src/include/optimizer/optimizer.h @@ -44,6 +44,11 @@ class OptimizerRuleTests_SimpleAssociativeRuleTest2_Test; namespace optimizer { +struct UtilPlanStatus { + bool has_plan = false; + std::unique_ptr util_plan; +}; + struct QueryInfo { QueryInfo(std::vector &exprs, std::shared_ptr &props) @@ -100,10 +105,11 @@ class Optimizer : public AbstractOptimizer { *support *CREATE), set * tree: a peloton query tree representing a select query - * return: the util plan if it is a util statement + * return: the util plan if it is a util statement, if the sql type + * is not util statements then return with has_plan set to false */ - std::unique_ptr HandleUtilStatement( - parser::SQLStatement *tree, concurrency::TransactionContext *txn); + UtilPlanStatus HandleUtilStatement(parser::SQLStatement *tree, + concurrency::TransactionContext *txn); /* TransformQueryTree - create an initial operator tree for the given query * to be used in performing optimization. diff --git a/src/include/parser/explain_statement.h b/src/include/parser/explain_statement.h index e0497a60484..4a64303f470 100644 --- a/src/include/parser/explain_statement.h +++ b/src/include/parser/explain_statement.h @@ -28,6 +28,10 @@ class ExplainStatement : public SQLStatement { void Accept(SqlNodeVisitor *v) override { v->Visit(this); } + const std::string GetInfo(int num_indent) const override; + + const std::string GetInfo() const override; + std::unique_ptr real_sql_stmt; /** diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index 5a2fb2bc434..bc0dcf3894d 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -101,12 +101,11 @@ shared_ptr Optimizer::BuildPelotonPlanTree( // TODO: support multi-statement queries auto parse_tree = parse_tree_list->GetStatement(0); - unique_ptr child_plan = nullptr; - + LOG_DEBUG("optimizer : %s", parse_tree->GetInfo().c_str()); // Handle ddl statement - auto util_plan = HandleUtilStatement(parse_tree, txn); - if (util_plan != nullptr) { - return move(util_plan); + auto util_plan_status = HandleUtilStatement(parse_tree, txn); + if (util_plan_status.has_plan != false) { + return move(util_plan_status.util_plan); } metadata_.txn = txn; @@ -138,16 +137,17 @@ shared_ptr Optimizer::BuildPelotonPlanTree( void Optimizer::Reset() { metadata_ = OptimizerMetadata(); } -unique_ptr Optimizer::HandleUtilStatement( +UtilPlanStatus Optimizer::HandleUtilStatement( parser::SQLStatement *tree, concurrency::TransactionContext *txn) { - unique_ptr util_plan = nullptr; + UtilPlanStatus util_plan_status; + util_plan_status.has_plan = true; auto stmt_type = tree->GetType(); switch (stmt_type) { case StatementType::DROP: { LOG_TRACE("Adding Drop plan..."); unique_ptr drop_plan( new planner::DropPlan((parser::DropStatement *)tree)); - util_plan = move(drop_plan); + util_plan_status.util_plan = move(drop_plan); break; } @@ -158,7 +158,7 @@ unique_ptr Optimizer::HandleUtilStatement( auto create_plan = new planner::CreatePlan((parser::CreateStatement *)tree); std::unique_ptr child_CreatePlan(create_plan); - util_plan = move(child_CreatePlan); + util_plan_status.util_plan = move(child_CreatePlan); if (create_plan->GetCreateType() == peloton::CreateType::INDEX) { auto create_stmt = (parser::CreateStatement *)tree; @@ -184,14 +184,14 @@ unique_ptr Optimizer::HandleUtilStatement( std::unique_ptr child_SeqScanPlan( new planner::SeqScanPlan(target_table, nullptr, column_ids, false)); - child_SeqScanPlan->AddChild(std::move(util_plan)); - util_plan = std::move(child_SeqScanPlan); + child_SeqScanPlan->AddChild(std::move(util_plan_status.util_plan)); + util_plan_status.util_plan = std::move(child_SeqScanPlan); // Create a plan to add data to index std::unique_ptr child_PopulateIndexPlan( new planner::PopulateIndexPlan(target_table, column_ids)); - child_PopulateIndexPlan->AddChild(std::move(util_plan)); + child_PopulateIndexPlan->AddChild(std::move(util_plan_status.util_plan)); create_plan->SetKeyAttrs(column_ids); - util_plan = std::move(child_PopulateIndexPlan); + util_plan_status.util_plan = std::move(child_PopulateIndexPlan); } break; } @@ -203,20 +203,20 @@ unique_ptr Optimizer::HandleUtilStatement( unique_ptr create_func_plan( new planner::CreateFunctionPlan( (parser::CreateFunctionStatement *)tree)); - util_plan = move(create_func_plan); + util_plan_status.util_plan = move(create_func_plan); } break; case StatementType::ANALYZE: { LOG_TRACE("Adding Analyze plan..."); unique_ptr analyze_plan(new planner::AnalyzePlan( static_cast(tree), txn)); - util_plan = move(analyze_plan); + util_plan_status.util_plan = move(analyze_plan); break; } case StatementType::COPY: { LOG_TRACE("Adding Copy plan..."); parser::CopyStatement *copy_parse_tree = static_cast(tree); - util_plan = util::CreateCopyPlan(copy_parse_tree); + util_plan_status.util_plan = util::CreateCopyPlan(copy_parse_tree); break; } case StatementType::EXPLAIN: { @@ -224,17 +224,20 @@ unique_ptr Optimizer::HandleUtilStatement( // Pass the sql statement to explain to the plan node auto *explain_parse_tree = reinterpret_cast(tree); - util_plan.reset( + util_plan_status.util_plan.reset( // TODO(boweic): not releasing this unique_ptr here would cause a // double delete which I still don't know why is happening. // I believe no one should take the ownership of the pointer here new planner::ExplainPlan(explain_parse_tree->real_sql_stmt.release(), explain_parse_tree->default_database_name)); + break; } - default: + default: { + util_plan_status.has_plan = false; break; + } } - return util_plan; + return util_plan_status; } shared_ptr Optimizer::InsertQueryTree( diff --git a/src/parser/explain_statement.cpp b/src/parser/explain_statement.cpp new file mode 100644 index 00000000000..bd78593debf --- /dev/null +++ b/src/parser/explain_statement.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Peloton +// +// explain_statement.cpp +// +// Identification: src/parser/explain_statement.cpp +// +// Copyright (c) 2015-18, Carnegie Mellon University Database Group +// +//===----------------------------------------------------------------------===// + +#include "parser/explain_statement.h" +#include "parser/select_statement.h" + +namespace peloton { +namespace parser { + +const std::string ExplainStatement::GetInfo(int num_indent) const { + std::ostringstream os; + os << StringUtil::Indent(num_indent) << "ExplainStatement:\n"; + os << real_sql_stmt->GetInfo(num_indent + 1); + return os.str(); +} + +const std::string ExplainStatement::GetInfo() const { + std::ostringstream os; + + os << "SQLStatement[EXPLAIN]\n"; + + os << GetInfo(1); + + return os.str(); +} + +} // namespace parser +} // namespace peloton diff --git a/test/network/explain_test.cpp b/test/network/explain_test.cpp index b6d7f193b7d..2ec6cf8d656 100644 --- a/test/network/explain_test.cpp +++ b/test/network/explain_test.cpp @@ -56,18 +56,13 @@ void *ExplainTest(int port) { txn1.exec("CREATE TABLE template(id INT);"); txn1.commit(); - // Execute EXPLAIN directly + // Try execute EXPLAIN pqxx::work txn2(C); - pqxx::result result1 = txn2.exec("EXPLAIN SELECT * from template;"); + pqxx::result result = txn2.exec("EXPLAIN SELECT * from template;"); txn2.commit(); - EXPECT_EQ(result1.size(), 1); + EXPECT_EQ(result.size(), 1); + EXPECT_EQ(std::string(result[0][0].c_str()), std::string("SeqScan()")); - // Execute EXPLAIN through PREPARE statement - pqxx::work txn3(C); - txn3.exec("PREPARE func AS EXPLAIN SELECT * from template;"); - pqxx::result result2 = txn3.exec("EXECUTE func"); - txn3.commit(); - EXPECT_EQ(result2.size(), 1); } catch (const std::exception &e) { LOG_INFO("[ExplainTest] Exception occurred: %s", e.what()); EXPECT_TRUE(false); From 3b0143ce5a14ceaa351daa3d0de1ef7c74d126eb Mon Sep 17 00:00:00 2001 From: Tianyi Chen Date: Sat, 12 May 2018 11:31:19 -0400 Subject: [PATCH 12/13] reduce log size by changing parse tree printing level to trace --- src/optimizer/optimizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index bc0dcf3894d..265cec4c431 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -101,7 +101,7 @@ shared_ptr Optimizer::BuildPelotonPlanTree( // TODO: support multi-statement queries auto parse_tree = parse_tree_list->GetStatement(0); - LOG_DEBUG("optimizer : %s", parse_tree->GetInfo().c_str()); + LOG_TRACE("optimizer : %s", parse_tree->GetInfo().c_str()); // Handle ddl statement auto util_plan_status = HandleUtilStatement(parse_tree, txn); if (util_plan_status.has_plan != false) { From 21385b2b0f80575874d267ffce4246f305c60ba3 Mon Sep 17 00:00:00 2001 From: vagrant <411468452@qq.com> Date: Wed, 16 May 2018 01:45:50 -0400 Subject: [PATCH 13/13] Fix memory leak --- src/executor/explain_executor.cpp | 2 ++ src/include/planner/explain_plan.h | 11 ++++++++--- src/optimizer/optimizer.cpp | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/executor/explain_executor.cpp b/src/executor/explain_executor.cpp index 88e4fac38b4..2414b9a936b 100644 --- a/src/executor/explain_executor.cpp +++ b/src/executor/explain_executor.cpp @@ -54,6 +54,8 @@ bool ExplainExecutor::DExecute() { std::unique_ptr stmt_list( new parser::SQLStatementList(sql_stmt)); auto plan = optimizer->BuildPelotonPlanTree(stmt_list, current_txn); + // Release the ptr to prevent double delete + stmt_list->PassOutStatement(0).release(); const catalog::Schema schema({catalog::Column( type::TypeId::VARCHAR, type::Type::GetTypeSize(type::TypeId::VARCHAR), "Query Plan")}); diff --git a/src/include/planner/explain_plan.h b/src/include/planner/explain_plan.h index 98390508d5e..912d28a4ebf 100644 --- a/src/include/planner/explain_plan.h +++ b/src/include/planner/explain_plan.h @@ -28,7 +28,12 @@ class ExplainPlan : public AbstractPlan { ExplainPlan(ExplainPlan &&) = delete; ExplainPlan &operator=(ExplainPlan &&) = delete; - explicit ExplainPlan(parser::SQLStatement *sql_stmt, + explicit ExplainPlan(std::unique_ptr sql_stmt, + std::string default_database_name) + : sql_stmt_(sql_stmt.release()), + default_database_name_(default_database_name){}; + + explicit ExplainPlan(std::shared_ptr sql_stmt, std::string default_database_name) : sql_stmt_(sql_stmt), default_database_name_(default_database_name){}; @@ -43,7 +48,7 @@ class ExplainPlan : public AbstractPlan { new ExplainPlan(sql_stmt_, default_database_name_)); } - parser::SQLStatement *GetSQLStatement() const { return sql_stmt_; } + parser::SQLStatement *GetSQLStatement() const { return sql_stmt_.get(); } std::string GetDatabaseName() const { return default_database_name_; } @@ -52,7 +57,7 @@ class ExplainPlan : public AbstractPlan { * @brief The SQL statement to explain, the it should be owned by the * explain ast */ - parser::SQLStatement *sql_stmt_; + std::shared_ptr sql_stmt_; /** * @brief The database name to be used in the binder */ diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index 265cec4c431..a3cb06e550d 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -228,7 +228,7 @@ UtilPlanStatus Optimizer::HandleUtilStatement( // TODO(boweic): not releasing this unique_ptr here would cause a // double delete which I still don't know why is happening. // I believe no one should take the ownership of the pointer here - new planner::ExplainPlan(explain_parse_tree->real_sql_stmt.release(), + new planner::ExplainPlan(std::move(explain_parse_tree->real_sql_stmt), explain_parse_tree->default_database_name)); break; }