1 | #include "duckdb/planner/planner.hpp" |
2 | |
3 | #include "duckdb/common/serializer.hpp" |
4 | #include "duckdb/common/serializer/buffered_deserializer.hpp" |
5 | #include "duckdb/execution/expression_executor.hpp" |
6 | #include "duckdb/main/client_context.hpp" |
7 | #include "duckdb/main/client_data.hpp" |
8 | #include "duckdb/main/database.hpp" |
9 | #include "duckdb/main/prepared_statement_data.hpp" |
10 | #include "duckdb/main/query_profiler.hpp" |
11 | #include "duckdb/planner/binder.hpp" |
12 | #include "duckdb/planner/expression/bound_parameter_expression.hpp" |
13 | #include "duckdb/transaction/meta_transaction.hpp" |
14 | |
15 | namespace duckdb { |
16 | |
17 | Planner::Planner(ClientContext &context) : binder(Binder::CreateBinder(context)), context(context) { |
18 | } |
19 | |
20 | static void CheckTreeDepth(const LogicalOperator &op, idx_t max_depth, idx_t depth = 0) { |
21 | if (depth >= max_depth) { |
22 | throw ParserException("Maximum tree depth of %lld exceeded in logical planner" , max_depth); |
23 | } |
24 | for (auto &child : op.children) { |
25 | CheckTreeDepth(op: *child, max_depth, depth: depth + 1); |
26 | } |
27 | } |
28 | |
29 | void Planner::CreatePlan(SQLStatement &statement) { |
30 | auto &profiler = QueryProfiler::Get(context); |
31 | auto parameter_count = statement.n_param; |
32 | |
33 | BoundParameterMap bound_parameters(parameter_data); |
34 | |
35 | // first bind the tables and columns to the catalog |
36 | bool parameters_resolved = true; |
37 | try { |
38 | profiler.StartPhase(phase: "binder" ); |
39 | binder->parameters = &bound_parameters; |
40 | auto bound_statement = binder->Bind(statement); |
41 | profiler.EndPhase(); |
42 | |
43 | this->names = bound_statement.names; |
44 | this->types = bound_statement.types; |
45 | this->plan = std::move(bound_statement.plan); |
46 | |
47 | auto max_tree_depth = ClientConfig::GetConfig(context).max_expression_depth; |
48 | CheckTreeDepth(op: *plan, max_depth: max_tree_depth); |
49 | } catch (const ParameterNotResolvedException &ex) { |
50 | // parameter types could not be resolved |
51 | this->names = {"unknown" }; |
52 | this->types = {LogicalTypeId::UNKNOWN}; |
53 | this->plan = nullptr; |
54 | parameters_resolved = false; |
55 | } catch (const Exception &ex) { |
56 | auto &config = DBConfig::GetConfig(context); |
57 | |
58 | this->plan = nullptr; |
59 | for (auto &extension_op : config.operator_extensions) { |
60 | auto bound_statement = |
61 | extension_op->Bind(context, *this->binder, extension_op->operator_info.get(), statement); |
62 | if (bound_statement.plan != nullptr) { |
63 | this->names = bound_statement.names; |
64 | this->types = bound_statement.types; |
65 | this->plan = std::move(bound_statement.plan); |
66 | break; |
67 | } |
68 | } |
69 | |
70 | if (!this->plan) { |
71 | throw; |
72 | } |
73 | } catch (std::exception &ex) { |
74 | throw; |
75 | } |
76 | this->properties = binder->properties; |
77 | this->properties.parameter_count = parameter_count; |
78 | properties.bound_all_parameters = parameters_resolved; |
79 | |
80 | Planner::VerifyPlan(context, op&: plan, map: &bound_parameters.parameters); |
81 | |
82 | // set up a map of parameter number -> value entries |
83 | for (auto &kv : bound_parameters.parameters) { |
84 | auto parameter_index = kv.first; |
85 | auto ¶meter_data = kv.second; |
86 | // check if the type of the parameter could be resolved |
87 | if (!parameter_data->return_type.IsValid()) { |
88 | properties.bound_all_parameters = false; |
89 | continue; |
90 | } |
91 | parameter_data->value = Value(parameter_data->return_type); |
92 | value_map[parameter_index] = parameter_data; |
93 | } |
94 | } |
95 | |
96 | shared_ptr<PreparedStatementData> Planner::PrepareSQLStatement(unique_ptr<SQLStatement> statement) { |
97 | auto copied_statement = statement->Copy(); |
98 | // create a plan of the underlying statement |
99 | CreatePlan(statement: std::move(statement)); |
100 | // now create the logical prepare |
101 | auto prepared_data = make_shared<PreparedStatementData>(args&: copied_statement->type); |
102 | prepared_data->unbound_statement = std::move(copied_statement); |
103 | prepared_data->names = names; |
104 | prepared_data->types = types; |
105 | prepared_data->value_map = std::move(value_map); |
106 | prepared_data->properties = properties; |
107 | prepared_data->catalog_version = MetaTransaction::Get(context).catalog_version; |
108 | return prepared_data; |
109 | } |
110 | |
111 | void Planner::CreatePlan(unique_ptr<SQLStatement> statement) { |
112 | D_ASSERT(statement); |
113 | switch (statement->type) { |
114 | case StatementType::SELECT_STATEMENT: |
115 | case StatementType::INSERT_STATEMENT: |
116 | case StatementType::COPY_STATEMENT: |
117 | case StatementType::DELETE_STATEMENT: |
118 | case StatementType::UPDATE_STATEMENT: |
119 | case StatementType::CREATE_STATEMENT: |
120 | case StatementType::DROP_STATEMENT: |
121 | case StatementType::ALTER_STATEMENT: |
122 | case StatementType::TRANSACTION_STATEMENT: |
123 | case StatementType::EXPLAIN_STATEMENT: |
124 | case StatementType::VACUUM_STATEMENT: |
125 | case StatementType::RELATION_STATEMENT: |
126 | case StatementType::CALL_STATEMENT: |
127 | case StatementType::EXPORT_STATEMENT: |
128 | case StatementType::PRAGMA_STATEMENT: |
129 | case StatementType::SHOW_STATEMENT: |
130 | case StatementType::SET_STATEMENT: |
131 | case StatementType::LOAD_STATEMENT: |
132 | case StatementType::EXTENSION_STATEMENT: |
133 | case StatementType::PREPARE_STATEMENT: |
134 | case StatementType::EXECUTE_STATEMENT: |
135 | case StatementType::LOGICAL_PLAN_STATEMENT: |
136 | case StatementType::ATTACH_STATEMENT: |
137 | case StatementType::DETACH_STATEMENT: |
138 | CreatePlan(statement&: *statement); |
139 | break; |
140 | default: |
141 | throw NotImplementedException("Cannot plan statement of type %s!" , StatementTypeToString(type: statement->type)); |
142 | } |
143 | } |
144 | |
145 | static bool OperatorSupportsSerialization(LogicalOperator &op) { |
146 | for (auto &child : op.children) { |
147 | if (!OperatorSupportsSerialization(op&: *child)) { |
148 | return false; |
149 | } |
150 | } |
151 | return op.SupportSerialization(); |
152 | } |
153 | |
154 | void Planner::VerifyPlan(ClientContext &context, unique_ptr<LogicalOperator> &op, bound_parameter_map_t *map) { |
155 | #ifdef DUCKDB_ALTERNATIVE_VERIFY |
156 | // if alternate verification is enabled we run the original operator |
157 | return; |
158 | #endif |
159 | if (!op || !ClientConfig::GetConfig(context).verify_serializer) { |
160 | return; |
161 | } |
162 | //! SELECT only for now |
163 | if (!OperatorSupportsSerialization(op&: *op)) { |
164 | return; |
165 | } |
166 | |
167 | BufferedSerializer serializer; |
168 | serializer.is_query_plan = true; |
169 | try { |
170 | op->Serialize(serializer); |
171 | } catch (NotImplementedException &ex) { |
172 | // ignore for now (FIXME) |
173 | return; |
174 | } |
175 | auto data = serializer.GetData(); |
176 | auto deserializer = BufferedContextDeserializer(context, data.data.get(), data.size); |
177 | |
178 | PlanDeserializationState state(context); |
179 | auto new_plan = LogicalOperator::Deserialize(deserializer, gstate&: state); |
180 | if (map) { |
181 | *map = std::move(state.parameter_data); |
182 | } |
183 | op = std::move(new_plan); |
184 | } |
185 | |
186 | } // namespace duckdb |
187 | |