1 | #include "duckdb/parser/transformer.hpp" |
2 | |
3 | #include "duckdb/parser/expression/list.hpp" |
4 | #include "duckdb/parser/statement/list.hpp" |
5 | #include "duckdb/parser/tableref/emptytableref.hpp" |
6 | #include "duckdb/parser/query_node/select_node.hpp" |
7 | #include "duckdb/parser/parser_options.hpp" |
8 | |
9 | namespace duckdb { |
10 | |
11 | StackChecker::StackChecker(Transformer &transformer_p, idx_t stack_usage_p) |
12 | : transformer(transformer_p), stack_usage(stack_usage_p) { |
13 | transformer.stack_depth += stack_usage; |
14 | } |
15 | |
16 | StackChecker::~StackChecker() { |
17 | transformer.stack_depth -= stack_usage; |
18 | } |
19 | |
20 | StackChecker::StackChecker(StackChecker &&other) noexcept |
21 | : transformer(other.transformer), stack_usage(other.stack_usage) { |
22 | other.stack_usage = 0; |
23 | } |
24 | |
25 | Transformer::Transformer(ParserOptions &options) |
26 | : parent(nullptr), options(options), stack_depth(DConstants::INVALID_INDEX) { |
27 | } |
28 | |
29 | Transformer::Transformer(Transformer &parent) |
30 | : parent(&parent), options(parent.options), stack_depth(DConstants::INVALID_INDEX) { |
31 | } |
32 | |
33 | Transformer::~Transformer() { |
34 | } |
35 | |
36 | void Transformer::Clear() { |
37 | SetParamCount(0); |
38 | pivot_entries.clear(); |
39 | } |
40 | |
41 | bool Transformer::TransformParseTree(duckdb_libpgquery::PGList *tree, vector<unique_ptr<SQLStatement>> &statements) { |
42 | InitializeStackCheck(); |
43 | for (auto entry = tree->head; entry != nullptr; entry = entry->next) { |
44 | Clear(); |
45 | auto n = PGPointerCast<duckdb_libpgquery::PGNode>(ptr: entry->data.ptr_value); |
46 | auto stmt = TransformStatement(stmt&: *n); |
47 | D_ASSERT(stmt); |
48 | if (HasPivotEntries()) { |
49 | stmt = CreatePivotStatement(statement: std::move(stmt)); |
50 | } |
51 | stmt->n_param = ParamCount(); |
52 | statements.push_back(x: std::move(stmt)); |
53 | } |
54 | return true; |
55 | } |
56 | |
57 | void Transformer::InitializeStackCheck() { |
58 | stack_depth = 0; |
59 | } |
60 | |
61 | StackChecker Transformer::StackCheck(idx_t ) { |
62 | auto &root = RootTransformer(); |
63 | D_ASSERT(root.stack_depth != DConstants::INVALID_INDEX); |
64 | if (root.stack_depth + extra_stack >= options.max_expression_depth) { |
65 | throw ParserException("Max expression depth limit of %lld exceeded. Use \"SET max_expression_depth TO x\" to " |
66 | "increase the maximum expression depth." , |
67 | options.max_expression_depth); |
68 | } |
69 | return StackChecker(root, extra_stack); |
70 | } |
71 | |
72 | unique_ptr<SQLStatement> Transformer::TransformStatement(duckdb_libpgquery::PGNode &stmt) { |
73 | auto result = TransformStatementInternal(stmt); |
74 | result->n_param = ParamCount(); |
75 | if (!named_param_map.empty()) { |
76 | // Avoid overriding a previous move with nothing |
77 | result->named_param_map = std::move(named_param_map); |
78 | } |
79 | return result; |
80 | } |
81 | |
82 | Transformer &Transformer::RootTransformer() { |
83 | reference<Transformer> node = *this; |
84 | while (node.get().parent) { |
85 | node = *node.get().parent; |
86 | } |
87 | return node.get(); |
88 | } |
89 | |
90 | const Transformer &Transformer::RootTransformer() const { |
91 | reference<const Transformer> node = *this; |
92 | while (node.get().parent) { |
93 | node = *node.get().parent; |
94 | } |
95 | return node.get(); |
96 | } |
97 | |
98 | idx_t Transformer::ParamCount() const { |
99 | auto &root = RootTransformer(); |
100 | return root.prepared_statement_parameter_index; |
101 | } |
102 | |
103 | void Transformer::SetParamCount(idx_t new_count) { |
104 | auto &root = RootTransformer(); |
105 | root.prepared_statement_parameter_index = new_count; |
106 | } |
107 | void Transformer::SetNamedParam(const string &name, int32_t index) { |
108 | auto &root = RootTransformer(); |
109 | D_ASSERT(!root.named_param_map.count(name)); |
110 | root.named_param_map[name] = index; |
111 | } |
112 | bool Transformer::GetNamedParam(const string &name, int32_t &index) { |
113 | auto &root = RootTransformer(); |
114 | auto entry = root.named_param_map.find(x: name); |
115 | if (entry == root.named_param_map.end()) { |
116 | return false; |
117 | } |
118 | index = entry->second; |
119 | return true; |
120 | } |
121 | bool Transformer::HasNamedParameters() const { |
122 | auto &root = RootTransformer(); |
123 | return !root.named_param_map.empty(); |
124 | } |
125 | |
126 | unique_ptr<SQLStatement> Transformer::TransformStatementInternal(duckdb_libpgquery::PGNode &stmt) { |
127 | switch (stmt.type) { |
128 | case duckdb_libpgquery::T_PGRawStmt: { |
129 | auto &raw_stmt = PGCast<duckdb_libpgquery::PGRawStmt>(node&: stmt); |
130 | auto result = TransformStatement(stmt&: *raw_stmt.stmt); |
131 | if (result) { |
132 | result->stmt_location = raw_stmt.stmt_location; |
133 | result->stmt_length = raw_stmt.stmt_len; |
134 | } |
135 | return result; |
136 | } |
137 | case duckdb_libpgquery::T_PGSelectStmt: |
138 | return TransformSelect(select&: PGCast<duckdb_libpgquery::PGSelectStmt>(node&: stmt)); |
139 | case duckdb_libpgquery::T_PGCreateStmt: |
140 | return TransformCreateTable(node&: PGCast<duckdb_libpgquery::PGCreateStmt>(node&: stmt)); |
141 | case duckdb_libpgquery::T_PGCreateSchemaStmt: |
142 | return TransformCreateSchema(stmt&: PGCast<duckdb_libpgquery::PGCreateSchemaStmt>(node&: stmt)); |
143 | case duckdb_libpgquery::T_PGViewStmt: |
144 | return TransformCreateView(node&: PGCast<duckdb_libpgquery::PGViewStmt>(node&: stmt)); |
145 | case duckdb_libpgquery::T_PGCreateSeqStmt: |
146 | return TransformCreateSequence(node&: PGCast<duckdb_libpgquery::PGCreateSeqStmt>(node&: stmt)); |
147 | case duckdb_libpgquery::T_PGCreateFunctionStmt: |
148 | return TransformCreateFunction(stmt&: PGCast<duckdb_libpgquery::PGCreateFunctionStmt>(node&: stmt)); |
149 | case duckdb_libpgquery::T_PGDropStmt: |
150 | return TransformDrop(stmt&: PGCast<duckdb_libpgquery::PGDropStmt>(node&: stmt)); |
151 | case duckdb_libpgquery::T_PGInsertStmt: |
152 | return TransformInsert(stmt&: PGCast<duckdb_libpgquery::PGInsertStmt>(node&: stmt)); |
153 | case duckdb_libpgquery::T_PGCopyStmt: |
154 | return TransformCopy(stmt&: PGCast<duckdb_libpgquery::PGCopyStmt>(node&: stmt)); |
155 | case duckdb_libpgquery::T_PGTransactionStmt: |
156 | return TransformTransaction(stmt&: PGCast<duckdb_libpgquery::PGTransactionStmt>(node&: stmt)); |
157 | case duckdb_libpgquery::T_PGDeleteStmt: |
158 | return TransformDelete(stmt&: PGCast<duckdb_libpgquery::PGDeleteStmt>(node&: stmt)); |
159 | case duckdb_libpgquery::T_PGUpdateStmt: |
160 | return TransformUpdate(stmt&: PGCast<duckdb_libpgquery::PGUpdateStmt>(node&: stmt)); |
161 | case duckdb_libpgquery::T_PGIndexStmt: |
162 | return TransformCreateIndex(stmt&: PGCast<duckdb_libpgquery::PGIndexStmt>(node&: stmt)); |
163 | case duckdb_libpgquery::T_PGAlterTableStmt: |
164 | return TransformAlter(stmt&: PGCast<duckdb_libpgquery::PGAlterTableStmt>(node&: stmt)); |
165 | case duckdb_libpgquery::T_PGRenameStmt: |
166 | return TransformRename(stmt&: PGCast<duckdb_libpgquery::PGRenameStmt>(node&: stmt)); |
167 | case duckdb_libpgquery::T_PGPrepareStmt: |
168 | return TransformPrepare(stmt&: PGCast<duckdb_libpgquery::PGPrepareStmt>(node&: stmt)); |
169 | case duckdb_libpgquery::T_PGExecuteStmt: |
170 | return TransformExecute(stmt&: PGCast<duckdb_libpgquery::PGExecuteStmt>(node&: stmt)); |
171 | case duckdb_libpgquery::T_PGDeallocateStmt: |
172 | return TransformDeallocate(stmt&: PGCast<duckdb_libpgquery::PGDeallocateStmt>(node&: stmt)); |
173 | case duckdb_libpgquery::T_PGCreateTableAsStmt: |
174 | return TransformCreateTableAs(stmt&: PGCast<duckdb_libpgquery::PGCreateTableAsStmt>(node&: stmt)); |
175 | case duckdb_libpgquery::T_PGPragmaStmt: |
176 | return TransformPragma(stmt&: PGCast<duckdb_libpgquery::PGPragmaStmt>(node&: stmt)); |
177 | case duckdb_libpgquery::T_PGExportStmt: |
178 | return TransformExport(stmt&: PGCast<duckdb_libpgquery::PGExportStmt>(node&: stmt)); |
179 | case duckdb_libpgquery::T_PGImportStmt: |
180 | return TransformImport(stmt&: PGCast<duckdb_libpgquery::PGImportStmt>(node&: stmt)); |
181 | case duckdb_libpgquery::T_PGExplainStmt: |
182 | return TransformExplain(stmt&: PGCast<duckdb_libpgquery::PGExplainStmt>(node&: stmt)); |
183 | case duckdb_libpgquery::T_PGVacuumStmt: |
184 | return TransformVacuum(stmt&: PGCast<duckdb_libpgquery::PGVacuumStmt>(node&: stmt)); |
185 | case duckdb_libpgquery::T_PGVariableShowStmt: |
186 | return TransformShow(stmt&: PGCast<duckdb_libpgquery::PGVariableShowStmt>(node&: stmt)); |
187 | case duckdb_libpgquery::T_PGVariableShowSelectStmt: |
188 | return TransformShowSelect(stmt&: PGCast<duckdb_libpgquery::PGVariableShowSelectStmt>(node&: stmt)); |
189 | case duckdb_libpgquery::T_PGCallStmt: |
190 | return TransformCall(stmt&: PGCast<duckdb_libpgquery::PGCallStmt>(node&: stmt)); |
191 | case duckdb_libpgquery::T_PGVariableSetStmt: |
192 | return TransformSet(set&: PGCast<duckdb_libpgquery::PGVariableSetStmt>(node&: stmt)); |
193 | case duckdb_libpgquery::T_PGCheckPointStmt: |
194 | return TransformCheckpoint(stmt&: PGCast<duckdb_libpgquery::PGCheckPointStmt>(node&: stmt)); |
195 | case duckdb_libpgquery::T_PGLoadStmt: |
196 | return TransformLoad(stmt&: PGCast<duckdb_libpgquery::PGLoadStmt>(node&: stmt)); |
197 | case duckdb_libpgquery::T_PGCreateTypeStmt: |
198 | return TransformCreateType(stmt&: PGCast<duckdb_libpgquery::PGCreateTypeStmt>(node&: stmt)); |
199 | case duckdb_libpgquery::T_PGAlterSeqStmt: |
200 | return TransformAlterSequence(stmt&: PGCast<duckdb_libpgquery::PGAlterSeqStmt>(node&: stmt)); |
201 | case duckdb_libpgquery::T_PGAttachStmt: |
202 | return TransformAttach(stmt&: PGCast<duckdb_libpgquery::PGAttachStmt>(node&: stmt)); |
203 | case duckdb_libpgquery::T_PGDetachStmt: |
204 | return TransformDetach(stmt&: PGCast<duckdb_libpgquery::PGDetachStmt>(node&: stmt)); |
205 | case duckdb_libpgquery::T_PGUseStmt: |
206 | return TransformUse(stmt&: PGCast<duckdb_libpgquery::PGUseStmt>(node&: stmt)); |
207 | default: |
208 | throw NotImplementedException(NodetypeToString(type: stmt.type)); |
209 | } |
210 | } |
211 | |
212 | } // namespace duckdb |
213 | |