Skip to content
This repository has been 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
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