1#include "duckdb/planner/planner.hpp"
2
3#include "duckdb/common/serializer.hpp"
4#include "duckdb/main/client_context.hpp"
5#include "duckdb/main/database.hpp"
6#include "duckdb/parser/statement/pragma_statement.hpp"
7#include "duckdb/parser/statement/prepare_statement.hpp"
8#include "duckdb/planner/binder.hpp"
9#include "duckdb/planner/expression/bound_parameter_expression.hpp"
10#include "duckdb/planner/operator/logical_prepare.hpp"
11#include "duckdb/planner/query_node/bound_select_node.hpp"
12#include "duckdb/planner/query_node/bound_set_operation_node.hpp"
13#include "duckdb/planner/pragma_handler.hpp"
14#include "duckdb/parser/parsed_data/drop_info.hpp"
15
16using namespace duckdb;
17using namespace std;
18
19Planner::Planner(ClientContext &context) : binder(context), context(context) {
20}
21
22void Planner::CreatePlan(SQLStatement &statement) {
23 vector<BoundParameterExpression *> bound_parameters;
24
25 // first bind the tables and columns to the catalog
26 context.profiler.StartPhase("binder");
27 binder.parameters = &bound_parameters;
28 auto bound_statement = binder.Bind(statement);
29 context.profiler.EndPhase();
30
31 // VerifyQuery(*bound_statement);
32
33 this->read_only = binder.read_only;
34 this->requires_valid_transaction = binder.requires_valid_transaction;
35 this->names = bound_statement.names;
36 this->sql_types = bound_statement.types;
37 this->plan = move(bound_statement.plan);
38
39 // now create a logical query plan from the query
40 // context.profiler.StartPhase("logical_planner");
41 // LogicalPlanGenerator logical_planner(binder, context);
42 // this->plan = logical_planner.CreatePlan(*bound_statement);
43 // context.profiler.EndPhase();
44
45 // set up a map of parameter number -> value entries
46 for (auto &expr : bound_parameters) {
47 // check if the type of the parameter could be resolved
48 if (expr->return_type == TypeId::INVALID) {
49 throw BinderException("Could not determine type of parameters: try adding explicit type casts");
50 }
51 auto value = make_unique<Value>(expr->return_type);
52 expr->value = value.get();
53 // check if the parameter number has been used before
54 if (value_map.find(expr->parameter_nr) != value_map.end()) {
55 throw BinderException("Duplicate parameter index. Use $1, $2 etc. to differentiate.");
56 }
57 PreparedValueEntry entry;
58 entry.value = move(value);
59 entry.target_type = expr->sql_type;
60 value_map[expr->parameter_nr] = move(entry);
61 }
62}
63
64void Planner::CreatePlan(unique_ptr<SQLStatement> statement) {
65 assert(statement);
66 switch (statement->type) {
67 case StatementType::SELECT_STATEMENT:
68 case StatementType::INSERT_STATEMENT:
69 case StatementType::COPY_STATEMENT:
70 case StatementType::DELETE_STATEMENT:
71 case StatementType::UPDATE_STATEMENT:
72 case StatementType::CREATE_STATEMENT:
73 case StatementType::EXECUTE_STATEMENT:
74 case StatementType::DROP_STATEMENT:
75 case StatementType::ALTER_STATEMENT:
76 case StatementType::TRANSACTION_STATEMENT:
77 case StatementType::EXPLAIN_STATEMENT:
78 case StatementType::VACUUM_STATEMENT:
79 case StatementType::RELATION_STATEMENT:
80 CreatePlan(*statement);
81 break;
82 case StatementType::PRAGMA_STATEMENT: {
83 auto &stmt = *reinterpret_cast<PragmaStatement *>(statement.get());
84 PragmaHandler handler(context);
85 // some pragma statements have a "replacement" SQL statement that will be executed instead
86 // use the PragmaHandler to get the (potential) replacement SQL statement
87 auto new_stmt = handler.HandlePragma(*stmt.info);
88 if (new_stmt) {
89 CreatePlan(move(new_stmt));
90 } else {
91 CreatePlan(stmt);
92 }
93 break;
94 }
95 case StatementType::PREPARE_STATEMENT: {
96 auto &stmt = *reinterpret_cast<PrepareStatement *>(statement.get());
97 auto statement_type = stmt.statement->type;
98 // create a plan of the underlying statement
99 CreatePlan(move(stmt.statement));
100 // now create the logical prepare
101 auto prepared_data = make_unique<PreparedStatementData>(statement_type);
102 prepared_data->names = names;
103 prepared_data->sql_types = sql_types;
104 prepared_data->value_map = move(value_map);
105 prepared_data->read_only = this->read_only;
106 prepared_data->requires_valid_transaction = this->requires_valid_transaction;
107
108 this->read_only = true;
109 this->requires_valid_transaction = false;
110
111 auto prepare = make_unique<LogicalPrepare>(stmt.name, move(prepared_data), move(plan));
112 names = {"Success"};
113 sql_types = {SQLType(SQLTypeId::BOOLEAN)};
114 plan = move(prepare);
115 break;
116 }
117 default:
118 throw NotImplementedException("Cannot plan statement of type %s!",
119 StatementTypeToString(statement->type).c_str());
120 }
121}
122
123// void Planner::VerifyQuery(BoundSQLStatement &statement) {
124// if (!context.query_verification_enabled) {
125// return;
126// }
127// if (statement.type != StatementType::SELECT_STATEMENT) {
128// return;
129// }
130// auto &select = (BoundSelectStatement &)statement;
131// VerifyNode(*select.node);
132// }
133
134// void Planner::VerifyNode(BoundQueryNode &node) {
135// if (node.type == QueryNodeType::SELECT_NODE) {
136// auto &select_node = (BoundSelectNode &)node;
137// vector<unique_ptr<Expression>> copies;
138// for (auto &expr : select_node.select_list) {
139// VerifyExpression(*expr, copies);
140// }
141// if (select_node.where_clause) {
142// VerifyExpression(*select_node.where_clause, copies);
143// }
144// for (auto &expr : select_node.groups) {
145// VerifyExpression(*expr, copies);
146// }
147// if (select_node.having) {
148// VerifyExpression(*select_node.having, copies);
149// }
150// for (auto &aggr : select_node.aggregates) {
151// VerifyExpression(*aggr, copies);
152// }
153// for (auto &window : select_node.windows) {
154// VerifyExpression(*window, copies);
155// }
156
157// // double loop to verify that (in)equality of hashes
158// for (idx_t i = 0; i < copies.size(); i++) {
159// auto outer_hash = copies[i]->Hash();
160// for (idx_t j = 0; j < copies.size(); j++) {
161// auto inner_hash = copies[j]->Hash();
162// if (outer_hash != inner_hash) {
163// // if hashes are not equivalent the expressions should not be equivalent
164// assert(!Expression::Equals(copies[i].get(), copies[j].get()));
165// }
166// }
167// }
168// } else {
169// assert(node.type == QueryNodeType::SET_OPERATION_NODE);
170// auto &setop_node = (BoundSetOperationNode &)node;
171// VerifyNode(*setop_node.left);
172// VerifyNode(*setop_node.right);
173// }
174// }
175
176// void Planner::VerifyExpression(Expression &expr, vector<unique_ptr<Expression>> &copies) {
177// if (expr.HasSubquery()) {
178// // can't copy subqueries
179// return;
180// }
181// // verify that the copy of expressions works
182// auto copy = expr.Copy();
183// // copy should have identical hash and identical equality function
184// assert(copy->Hash() == expr.Hash());
185// assert(Expression::Equals(copy.get(), &expr));
186// copies.push_back(move(copy));
187// }
188