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
9namespace duckdb {
10
11StackChecker::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
16StackChecker::~StackChecker() {
17 transformer.stack_depth -= stack_usage;
18}
19
20StackChecker::StackChecker(StackChecker &&other) noexcept
21 : transformer(other.transformer), stack_usage(other.stack_usage) {
22 other.stack_usage = 0;
23}
24
25Transformer::Transformer(ParserOptions &options)
26 : parent(nullptr), options(options), stack_depth(DConstants::INVALID_INDEX) {
27}
28
29Transformer::Transformer(Transformer &parent)
30 : parent(&parent), options(parent.options), stack_depth(DConstants::INVALID_INDEX) {
31}
32
33Transformer::~Transformer() {
34}
35
36void Transformer::Clear() {
37 SetParamCount(0);
38 pivot_entries.clear();
39}
40
41bool 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
57void Transformer::InitializeStackCheck() {
58 stack_depth = 0;
59}
60
61StackChecker Transformer::StackCheck(idx_t extra_stack) {
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
72unique_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
82Transformer &Transformer::RootTransformer() {
83 reference<Transformer> node = *this;
84 while (node.get().parent) {
85 node = *node.get().parent;
86 }
87 return node.get();
88}
89
90const 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
98idx_t Transformer::ParamCount() const {
99 auto &root = RootTransformer();
100 return root.prepared_statement_parameter_index;
101}
102
103void Transformer::SetParamCount(idx_t new_count) {
104 auto &root = RootTransformer();
105 root.prepared_statement_parameter_index = new_count;
106}
107void 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}
112bool 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}
121bool Transformer::HasNamedParameters() const {
122 auto &root = RootTransformer();
123 return !root.named_param_map.empty();
124}
125
126unique_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