Skip to content
This repository was archived by the owner on Sep 27, 2019. It is now read-only.

Handle EXPLAIN in the optimizer and executor #1357

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/binder/bind_node_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
3 changes: 3 additions & 0 deletions src/common/internal_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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'",
Expand Down
74 changes: 74 additions & 0 deletions src/executor/explain_executor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//===----------------------------------------------------------------------===//
//
// Peloton
//
// explain_executor.cpp
//
// Identification: src/executor/explain_executor.cpp
//
// Copyright (c) 2015-18, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <vector>

#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<planner::ExplainPlan>();

parser::SQLStatement *sql_stmt = node.GetSQLStatement();

LOG_TRACE("EXPLAIN : %s", sql_stmt->GetInfo().c_str());

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::Optimizer> optimizer(new optimizer::Optimizer());
std::unique_ptr<parser::SQLStatementList> 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")});
std::shared_ptr<storage::Tile> dest_tile(
storage::TileFactory::GetTempTile(schema, 1));
std::unique_ptr<storage::Tuple> 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_DEBUG("Explain finished!, plan : %s", plan->GetInfo().c_str());
return false;
}

} // namespace executor
} // namespace peloton
5 changes: 4 additions & 1 deletion src/executor/plan_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,10 @@ executor::AbstractExecutor *BuildExecutorTree(
child_executor =
new executor::PopulateIndexExecutor(plan, executor_context);
break;

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());
Expand Down
1 change: 1 addition & 0 deletions src/include/binder/bind_node_visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/include/common/internal_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@ enum class PlanNodeType {
RESULT = 70,
COPY = 71,
CREATE_FUNC = 72,
EXPLAIN = 73,

// Test
MOCK = 80
Expand Down
1 change: 1 addition & 0 deletions src/include/executor/executors.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
46 changes: 46 additions & 0 deletions src/include/executor/explain_executor.h
Original file line number Diff line number Diff line change
@@ -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
11 changes: 0 additions & 11 deletions src/include/network/postgres_protocol_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@

namespace peloton {

namespace parser {
class ExplainStatement;
} // namespace parser

namespace network {

typedef std::vector<std::unique_ptr<OutputPacket>> ResponseBuffer;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -215,9 +207,6 @@ class PostgresProtocolHandler : public ProtocolHandler {
// Portals
std::unordered_map<std::string, std::shared_ptr<Portal>> portals_;

// packets ready for read
size_t pkt_cntr_;

// Manage parameter types for unnamed statement
stats::QueryMetric::QueryParamBuf unnamed_stmt_param_types_;

Expand Down
36 changes: 21 additions & 15 deletions src/include/optimizer/optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,17 @@ class TransactionContext;
}

namespace test {
class OptimizerRuleTests_SimpleAssociativeRuleTest_Test;
class OptimizerRuleTests_SimpleAssociativeRuleTest2_Test;
}
class OptimizerRuleTests_SimpleAssociativeRuleTest_Test;
class OptimizerRuleTests_SimpleAssociativeRuleTest2_Test;
}

namespace optimizer {

struct UtilPlanStatus {
bool has_plan = false;
std::unique_ptr<planner::AbstractPlan> util_plan;
};

struct QueryInfo {
QueryInfo(std::vector<expression::AbstractExpression *> &exprs,
std::shared_ptr<PropertySet> &props)
Expand All @@ -60,8 +65,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;
Expand All @@ -83,27 +90,26 @@ class Optimizer : public AbstractOptimizer {
OptimizerMetadata &GetMetadata() { return metadata_; }

/* For test purposes only */
std::shared_ptr<GroupExpression> TestInsertQueryTree(parser::SQLStatement *tree,
concurrency::TransactionContext *txn) {
std::shared_ptr<GroupExpression> 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<OptimizeContext> root_context) {
std::shared_ptr<OptimizeContext> 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, if the sql type
* is not util statements then return with has_plan set to false
*/
std::unique_ptr<planner::AbstractPlan> HandleDDLStatement(
parser::SQLStatement *tree, bool &is_ddl_stmt,
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.
Expand Down
10 changes: 10 additions & 0 deletions src/include/parser/explain_statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,17 @@ 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<parser::SQLStatement> 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
Expand Down
68 changes: 68 additions & 0 deletions src/include/planner/explain_plan.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@

//===----------------------------------------------------------------------===//
//
// Peloton
//
// explain_plan.h
//
// Identification: src/include/planner/explain_plan.h
//
// Copyright (c) 2015-18, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#pragma once

#include "parser/sql_statement.h"
#include "planner/abstract_plan.h"

#include <memory>

namespace peloton {

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(std::unique_ptr<parser::SQLStatement> sql_stmt,
std::string default_database_name)
: sql_stmt_(sql_stmt.release()),
default_database_name_(default_database_name){};

explicit ExplainPlan(std::shared_ptr<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();
}

inline std::unique_ptr<AbstractPlan> Copy() const {
return std::unique_ptr<AbstractPlan>(
new ExplainPlan(sql_stmt_, default_database_name_));
}

parser::SQLStatement *GetSQLStatement() const { return sql_stmt_.get(); }

std::string GetDatabaseName() const { return default_database_name_; }

private:
/**
* @brief The SQL statement to explain, the it should be owned by the
* explain ast
*/
std::shared_ptr<parser::SQLStatement> sql_stmt_;
/**
* @brief The database name to be used in the binder
*/
std::string default_database_name_;
};

} // namespace planner
} // namespace peloton
Loading