1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/parser/transformer.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/common/constants.hpp"
12#include "duckdb/common/enums/expression_type.hpp"
13#include "duckdb/common/types.hpp"
14#include "duckdb/common/unordered_map.hpp"
15#include "duckdb/parser/qualified_name.hpp"
16#include "duckdb/parser/tokens.hpp"
17#include "duckdb/parser/parsed_data/create_info.hpp"
18#include "duckdb/parser/group_by_node.hpp"
19#include "duckdb/parser/query_node.hpp"
20#include "duckdb/common/case_insensitive_map.hpp"
21
22#include "pg_definitions.hpp"
23#include "nodes/parsenodes.hpp"
24#include "nodes/primnodes.hpp"
25
26namespace duckdb {
27
28class ColumnDefinition;
29class StackChecker;
30struct OrderByNode;
31struct CopyInfo;
32struct CommonTableExpressionInfo;
33struct GroupingExpressionMap;
34class OnConflictInfo;
35class UpdateSetInfo;
36struct ParserOptions;
37struct PivotColumn;
38
39//! The transformer class is responsible for transforming the internal Postgres
40//! parser representation into the DuckDB representation
41class Transformer {
42 friend class StackChecker;
43
44 struct CreatePivotEntry {
45 string enum_name;
46 unique_ptr<SelectNode> base;
47 unique_ptr<ParsedExpression> column;
48 unique_ptr<QueryNode> subquery;
49 };
50
51public:
52 explicit Transformer(ParserOptions &options);
53 explicit Transformer(Transformer &parent);
54 ~Transformer();
55
56 //! Transforms a Postgres parse tree into a set of SQL Statements
57 bool TransformParseTree(duckdb_libpgquery::PGList *tree, vector<unique_ptr<SQLStatement>> &statements);
58 string NodetypeToString(duckdb_libpgquery::PGNodeTag type);
59
60 idx_t ParamCount() const;
61
62private:
63 optional_ptr<Transformer> parent;
64 //! Parser options
65 ParserOptions &options;
66 //! The current prepared statement parameter index
67 idx_t prepared_statement_parameter_index = 0;
68 //! Map from named parameter to parameter index;
69 case_insensitive_map_t<idx_t> named_param_map;
70 //! Holds window expressions defined by name. We need those when transforming the expressions referring to them.
71 unordered_map<string, duckdb_libpgquery::PGWindowDef *> window_clauses;
72 //! The set of pivot entries to create
73 vector<unique_ptr<CreatePivotEntry>> pivot_entries;
74 //! Sets of stored CTEs, if any
75 vector<CommonTableExpressionMap *> stored_cte_map;
76 //! Whether or not we are currently binding a window definition
77 bool in_window_definition = false;
78
79 void Clear();
80 bool InWindowDefinition();
81
82 Transformer &RootTransformer();
83 const Transformer &RootTransformer() const;
84 void SetParamCount(idx_t new_count);
85 void SetNamedParam(const string &name, int32_t index);
86 bool GetNamedParam(const string &name, int32_t &index);
87 bool HasNamedParameters() const;
88
89 void AddPivotEntry(string enum_name, unique_ptr<SelectNode> source, unique_ptr<ParsedExpression> column,
90 unique_ptr<QueryNode> subquery);
91 unique_ptr<SQLStatement> GenerateCreateEnumStmt(unique_ptr<CreatePivotEntry> entry);
92 bool HasPivotEntries();
93 idx_t PivotEntryCount();
94 vector<unique_ptr<CreatePivotEntry>> &GetPivotEntries();
95 void PivotEntryCheck(const string &type);
96 void ExtractCTEsRecursive(CommonTableExpressionMap &cte_map);
97
98private:
99 //! Transforms a Postgres statement into a single SQL statement
100 unique_ptr<SQLStatement> TransformStatement(duckdb_libpgquery::PGNode &stmt);
101 //! Transforms a Postgres statement into a single SQL statement
102 unique_ptr<SQLStatement> TransformStatementInternal(duckdb_libpgquery::PGNode &stmt);
103 //===--------------------------------------------------------------------===//
104 // Statement transformation
105 //===--------------------------------------------------------------------===//
106 //! Transform a Postgres duckdb_libpgquery::T_PGSelectStmt node into a SelectStatement
107 unique_ptr<SelectStatement> TransformSelect(optional_ptr<duckdb_libpgquery::PGNode> node, bool is_select = true);
108 //! Transform a Postgres duckdb_libpgquery::T_PGSelectStmt node into a SelectStatement
109 unique_ptr<SelectStatement> TransformSelect(duckdb_libpgquery::PGSelectStmt &select, bool is_select = true);
110 //! Transform a Postgres T_AlterStmt node into a AlterStatement
111 unique_ptr<AlterStatement> TransformAlter(duckdb_libpgquery::PGAlterTableStmt &stmt);
112 //! Transform a Postgres duckdb_libpgquery::T_PGRenameStmt node into a RenameStatement
113 unique_ptr<AlterStatement> TransformRename(duckdb_libpgquery::PGRenameStmt &stmt);
114 //! Transform a Postgres duckdb_libpgquery::T_PGCreateStmt node into a CreateStatement
115 unique_ptr<CreateStatement> TransformCreateTable(duckdb_libpgquery::PGCreateStmt &node);
116 //! Transform a Postgres duckdb_libpgquery::T_PGCreateStmt node into a CreateStatement
117 unique_ptr<CreateStatement> TransformCreateTableAs(duckdb_libpgquery::PGCreateTableAsStmt &stmt);
118 //! Transform a Postgres node into a CreateStatement
119 unique_ptr<CreateStatement> TransformCreateSchema(duckdb_libpgquery::PGCreateSchemaStmt &stmt);
120 //! Transform a Postgres duckdb_libpgquery::T_PGCreateSeqStmt node into a CreateStatement
121 unique_ptr<CreateStatement> TransformCreateSequence(duckdb_libpgquery::PGCreateSeqStmt &node);
122 //! Transform a Postgres duckdb_libpgquery::T_PGViewStmt node into a CreateStatement
123 unique_ptr<CreateStatement> TransformCreateView(duckdb_libpgquery::PGViewStmt &node);
124 //! Transform a Postgres duckdb_libpgquery::T_PGIndexStmt node into CreateStatement
125 unique_ptr<CreateStatement> TransformCreateIndex(duckdb_libpgquery::PGIndexStmt &stmt);
126 //! Transform a Postgres duckdb_libpgquery::T_PGCreateFunctionStmt node into CreateStatement
127 unique_ptr<CreateStatement> TransformCreateFunction(duckdb_libpgquery::PGCreateFunctionStmt &stmt);
128 //! Transform a Postgres duckdb_libpgquery::T_PGCreateTypeStmt node into CreateStatement
129 unique_ptr<CreateStatement> TransformCreateType(duckdb_libpgquery::PGCreateTypeStmt &stmt);
130 //! Transform a Postgres duckdb_libpgquery::T_PGAlterSeqStmt node into CreateStatement
131 unique_ptr<AlterStatement> TransformAlterSequence(duckdb_libpgquery::PGAlterSeqStmt &stmt);
132 //! Transform a Postgres duckdb_libpgquery::T_PGDropStmt node into a Drop[Table,Schema]Statement
133 unique_ptr<SQLStatement> TransformDrop(duckdb_libpgquery::PGDropStmt &stmt);
134 //! Transform a Postgres duckdb_libpgquery::T_PGInsertStmt node into a InsertStatement
135 unique_ptr<InsertStatement> TransformInsert(duckdb_libpgquery::PGInsertStmt &stmt);
136
137 //! Transform a Postgres duckdb_libpgquery::T_PGOnConflictClause node into a OnConflictInfo
138 unique_ptr<OnConflictInfo> TransformOnConflictClause(duckdb_libpgquery::PGOnConflictClause *node,
139 const string &relname);
140 //! Transform a ON CONFLICT shorthand into a OnConflictInfo
141 unique_ptr<OnConflictInfo> DummyOnConflictClause(duckdb_libpgquery::PGOnConflictActionAlias type,
142 const string &relname);
143 //! Transform a Postgres duckdb_libpgquery::T_PGCopyStmt node into a CopyStatement
144 unique_ptr<CopyStatement> TransformCopy(duckdb_libpgquery::PGCopyStmt &stmt);
145 void TransformCopyOptions(CopyInfo &info, optional_ptr<duckdb_libpgquery::PGList> options);
146 //! Transform a Postgres duckdb_libpgquery::T_PGTransactionStmt node into a TransactionStatement
147 unique_ptr<TransactionStatement> TransformTransaction(duckdb_libpgquery::PGTransactionStmt &stmt);
148 //! Transform a Postgres T_DeleteStatement node into a DeleteStatement
149 unique_ptr<DeleteStatement> TransformDelete(duckdb_libpgquery::PGDeleteStmt &stmt);
150 //! Transform a Postgres duckdb_libpgquery::T_PGUpdateStmt node into a UpdateStatement
151 unique_ptr<UpdateStatement> TransformUpdate(duckdb_libpgquery::PGUpdateStmt &stmt);
152 //! Transform a Postgres duckdb_libpgquery::T_PGPragmaStmt node into a PragmaStatement
153 unique_ptr<SQLStatement> TransformPragma(duckdb_libpgquery::PGPragmaStmt &stmt);
154 //! Transform a Postgres duckdb_libpgquery::T_PGExportStmt node into a ExportStatement
155 unique_ptr<ExportStatement> TransformExport(duckdb_libpgquery::PGExportStmt &stmt);
156 //! Transform a Postgres duckdb_libpgquery::T_PGImportStmt node into a PragmaStatement
157 unique_ptr<PragmaStatement> TransformImport(duckdb_libpgquery::PGImportStmt &stmt);
158 unique_ptr<ExplainStatement> TransformExplain(duckdb_libpgquery::PGExplainStmt &stmt);
159 unique_ptr<SQLStatement> TransformVacuum(duckdb_libpgquery::PGVacuumStmt &stmt);
160 unique_ptr<SQLStatement> TransformShow(duckdb_libpgquery::PGVariableShowStmt &stmt);
161 unique_ptr<ShowStatement> TransformShowSelect(duckdb_libpgquery::PGVariableShowSelectStmt &stmt);
162 unique_ptr<AttachStatement> TransformAttach(duckdb_libpgquery::PGAttachStmt &stmt);
163 unique_ptr<DetachStatement> TransformDetach(duckdb_libpgquery::PGDetachStmt &stmt);
164 unique_ptr<SetStatement> TransformUse(duckdb_libpgquery::PGUseStmt &stmt);
165
166 unique_ptr<PrepareStatement> TransformPrepare(duckdb_libpgquery::PGPrepareStmt &stmt);
167 unique_ptr<ExecuteStatement> TransformExecute(duckdb_libpgquery::PGExecuteStmt &stmt);
168 unique_ptr<CallStatement> TransformCall(duckdb_libpgquery::PGCallStmt &stmt);
169 unique_ptr<DropStatement> TransformDeallocate(duckdb_libpgquery::PGDeallocateStmt &stmt);
170 unique_ptr<QueryNode> TransformPivotStatement(duckdb_libpgquery::PGSelectStmt &select);
171 unique_ptr<SQLStatement> CreatePivotStatement(unique_ptr<SQLStatement> statement);
172 PivotColumn TransformPivotColumn(duckdb_libpgquery::PGPivot &pivot);
173 vector<PivotColumn> TransformPivotList(duckdb_libpgquery::PGList &list);
174
175 //===--------------------------------------------------------------------===//
176 // SetStatement Transform
177 //===--------------------------------------------------------------------===//
178 unique_ptr<SetStatement> TransformSet(duckdb_libpgquery::PGVariableSetStmt &set);
179 unique_ptr<SetStatement> TransformSetVariable(duckdb_libpgquery::PGVariableSetStmt &stmt);
180 unique_ptr<SetStatement> TransformResetVariable(duckdb_libpgquery::PGVariableSetStmt &stmt);
181
182 unique_ptr<SQLStatement> TransformCheckpoint(duckdb_libpgquery::PGCheckPointStmt &stmt);
183 unique_ptr<LoadStatement> TransformLoad(duckdb_libpgquery::PGLoadStmt &stmt);
184
185 //===--------------------------------------------------------------------===//
186 // Query Node Transform
187 //===--------------------------------------------------------------------===//
188 //! Transform a Postgres duckdb_libpgquery::T_PGSelectStmt node into a QueryNode
189 unique_ptr<QueryNode> TransformSelectNode(duckdb_libpgquery::PGSelectStmt &select);
190 unique_ptr<QueryNode> TransformSelectInternal(duckdb_libpgquery::PGSelectStmt &select);
191 void TransformModifiers(duckdb_libpgquery::PGSelectStmt &stmt, QueryNode &node);
192
193 //===--------------------------------------------------------------------===//
194 // Expression Transform
195 //===--------------------------------------------------------------------===//
196 //! Transform a Postgres boolean expression into an Expression
197 unique_ptr<ParsedExpression> TransformBoolExpr(duckdb_libpgquery::PGBoolExpr &root);
198 //! Transform a Postgres case expression into an Expression
199 unique_ptr<ParsedExpression> TransformCase(duckdb_libpgquery::PGCaseExpr &root);
200 //! Transform a Postgres type cast into an Expression
201 unique_ptr<ParsedExpression> TransformTypeCast(duckdb_libpgquery::PGTypeCast &root);
202 //! Transform a Postgres coalesce into an Expression
203 unique_ptr<ParsedExpression> TransformCoalesce(duckdb_libpgquery::PGAExpr &root);
204 //! Transform a Postgres column reference into an Expression
205 unique_ptr<ParsedExpression> TransformColumnRef(duckdb_libpgquery::PGColumnRef &root);
206 //! Transform a Postgres constant value into an Expression
207 unique_ptr<ConstantExpression> TransformValue(duckdb_libpgquery::PGValue val);
208 //! Transform a Postgres operator into an Expression
209 unique_ptr<ParsedExpression> TransformAExpr(duckdb_libpgquery::PGAExpr &root);
210 unique_ptr<ParsedExpression> TransformAExprInternal(duckdb_libpgquery::PGAExpr &root);
211 //! Transform a Postgres abstract expression into an Expression
212 unique_ptr<ParsedExpression> TransformExpression(optional_ptr<duckdb_libpgquery::PGNode> node);
213 unique_ptr<ParsedExpression> TransformExpression(duckdb_libpgquery::PGNode &node);
214 //! Transform a Postgres function call into an Expression
215 unique_ptr<ParsedExpression> TransformFuncCall(duckdb_libpgquery::PGFuncCall &root);
216 //! Transform a Postgres boolean expression into an Expression
217 unique_ptr<ParsedExpression> TransformInterval(duckdb_libpgquery::PGIntervalConstant &root);
218 //! Transform a Postgres lambda node [e.g. (x, y) -> x + y] into a lambda expression
219 unique_ptr<ParsedExpression> TransformLambda(duckdb_libpgquery::PGLambdaFunction &node);
220 //! Transform a Postgres array access node (e.g. x[1] or x[1:3])
221 unique_ptr<ParsedExpression> TransformArrayAccess(duckdb_libpgquery::PGAIndirection &node);
222 //! Transform a positional reference (e.g. #1)
223 unique_ptr<ParsedExpression> TransformPositionalReference(duckdb_libpgquery::PGPositionalReference &node);
224 unique_ptr<ParsedExpression> TransformStarExpression(duckdb_libpgquery::PGAStar &node);
225 unique_ptr<ParsedExpression> TransformBooleanTest(duckdb_libpgquery::PGBooleanTest &node);
226
227 //! Transform a Postgres constant value into an Expression
228 unique_ptr<ParsedExpression> TransformConstant(duckdb_libpgquery::PGAConst &c);
229 unique_ptr<ParsedExpression> TransformGroupingFunction(duckdb_libpgquery::PGGroupingFunc &n);
230 unique_ptr<ParsedExpression> TransformResTarget(duckdb_libpgquery::PGResTarget &root);
231 unique_ptr<ParsedExpression> TransformNullTest(duckdb_libpgquery::PGNullTest &root);
232 unique_ptr<ParsedExpression> TransformParamRef(duckdb_libpgquery::PGParamRef &node);
233 unique_ptr<ParsedExpression> TransformNamedArg(duckdb_libpgquery::PGNamedArgExpr &root);
234
235 unique_ptr<ParsedExpression> TransformSQLValueFunction(duckdb_libpgquery::PGSQLValueFunction &node);
236
237 unique_ptr<ParsedExpression> TransformSubquery(duckdb_libpgquery::PGSubLink &root);
238 //===--------------------------------------------------------------------===//
239 // Constraints transform
240 //===--------------------------------------------------------------------===//
241 unique_ptr<Constraint> TransformConstraint(duckdb_libpgquery::PGListCell *cell);
242
243 unique_ptr<Constraint> TransformConstraint(duckdb_libpgquery::PGListCell *cell, ColumnDefinition &column,
244 idx_t index);
245
246 //===--------------------------------------------------------------------===//
247 // Update transform
248 //===--------------------------------------------------------------------===//
249 unique_ptr<UpdateSetInfo> TransformUpdateSetInfo(duckdb_libpgquery::PGList *target_list,
250 duckdb_libpgquery::PGNode *where_clause);
251
252 //===--------------------------------------------------------------------===//
253 // Index transform
254 //===--------------------------------------------------------------------===//
255 vector<unique_ptr<ParsedExpression>> TransformIndexParameters(duckdb_libpgquery::PGList &list,
256 const string &relation_name);
257
258 //===--------------------------------------------------------------------===//
259 // Collation transform
260 //===--------------------------------------------------------------------===//
261 unique_ptr<ParsedExpression> TransformCollateExpr(duckdb_libpgquery::PGCollateClause &collate);
262
263 string TransformCollation(optional_ptr<duckdb_libpgquery::PGCollateClause> collate);
264
265 ColumnDefinition TransformColumnDefinition(duckdb_libpgquery::PGColumnDef &cdef);
266 //===--------------------------------------------------------------------===//
267 // Helpers
268 //===--------------------------------------------------------------------===//
269 OnCreateConflict TransformOnConflict(duckdb_libpgquery::PGOnCreateConflict conflict);
270 string TransformAlias(duckdb_libpgquery::PGAlias *root, vector<string> &column_name_alias);
271 vector<string> TransformStringList(duckdb_libpgquery::PGList *list);
272 void TransformCTE(duckdb_libpgquery::PGWithClause &de_with_clause, CommonTableExpressionMap &cte_map);
273 unique_ptr<SelectStatement> TransformRecursiveCTE(duckdb_libpgquery::PGCommonTableExpr &cte,
274 CommonTableExpressionInfo &info);
275
276 unique_ptr<ParsedExpression> TransformUnaryOperator(const string &op, unique_ptr<ParsedExpression> child);
277 unique_ptr<ParsedExpression> TransformBinaryOperator(string op, unique_ptr<ParsedExpression> left,
278 unique_ptr<ParsedExpression> right);
279 //===--------------------------------------------------------------------===//
280 // TableRef transform
281 //===--------------------------------------------------------------------===//
282 //! Transform a Postgres node into a TableRef
283 unique_ptr<TableRef> TransformTableRefNode(duckdb_libpgquery::PGNode &n);
284 //! Transform a Postgres FROM clause into a TableRef
285 unique_ptr<TableRef> TransformFrom(optional_ptr<duckdb_libpgquery::PGList> root);
286 //! Transform a Postgres table reference into a TableRef
287 unique_ptr<TableRef> TransformRangeVar(duckdb_libpgquery::PGRangeVar &root);
288 //! Transform a Postgres table-producing function into a TableRef
289 unique_ptr<TableRef> TransformRangeFunction(duckdb_libpgquery::PGRangeFunction &root);
290 //! Transform a Postgres join node into a TableRef
291 unique_ptr<TableRef> TransformJoin(duckdb_libpgquery::PGJoinExpr &root);
292 //! Transform a Postgres pivot node into a TableRef
293 unique_ptr<TableRef> TransformPivot(duckdb_libpgquery::PGPivotExpr &root);
294 //! Transform a table producing subquery into a TableRef
295 unique_ptr<TableRef> TransformRangeSubselect(duckdb_libpgquery::PGRangeSubselect &root);
296 //! Transform a VALUES list into a set of expressions
297 unique_ptr<TableRef> TransformValuesList(duckdb_libpgquery::PGList *list);
298
299 //! Transform a range var into a (schema) qualified name
300 QualifiedName TransformQualifiedName(duckdb_libpgquery::PGRangeVar &root);
301
302 //! Transform a Postgres TypeName string into a LogicalType
303 LogicalType TransformTypeName(duckdb_libpgquery::PGTypeName &name);
304
305 //! Transform a Postgres GROUP BY expression into a list of Expression
306 bool TransformGroupBy(optional_ptr<duckdb_libpgquery::PGList> group, SelectNode &result);
307 void TransformGroupByNode(duckdb_libpgquery::PGNode &n, GroupingExpressionMap &map, SelectNode &result,
308 vector<GroupingSet> &result_sets);
309 void AddGroupByExpression(unique_ptr<ParsedExpression> expression, GroupingExpressionMap &map, GroupByNode &result,
310 vector<idx_t> &result_set);
311 void TransformGroupByExpression(duckdb_libpgquery::PGNode &n, GroupingExpressionMap &map, GroupByNode &result,
312 vector<idx_t> &result_set);
313 //! Transform a Postgres ORDER BY expression into an OrderByDescription
314 bool TransformOrderBy(duckdb_libpgquery::PGList *order, vector<OrderByNode> &result);
315
316 //! Transform a Postgres SELECT clause into a list of Expressions
317 void TransformExpressionList(duckdb_libpgquery::PGList &list, vector<unique_ptr<ParsedExpression>> &result);
318
319 //! Transform a Postgres PARTITION BY/ORDER BY specification into lists of expressions
320 void TransformWindowDef(duckdb_libpgquery::PGWindowDef &window_spec, WindowExpression &expr,
321 const char *window_name = nullptr);
322 //! Transform a Postgres window frame specification into frame expressions
323 void TransformWindowFrame(duckdb_libpgquery::PGWindowDef &window_spec, WindowExpression &expr);
324
325 unique_ptr<SampleOptions> TransformSampleOptions(optional_ptr<duckdb_libpgquery::PGNode> options);
326 //! Returns true if an expression is only a star (i.e. "*", without any other decorators)
327 bool ExpressionIsEmptyStar(ParsedExpression &expr);
328
329 OnEntryNotFound TransformOnEntryNotFound(bool missing_ok);
330
331 Vector PGListToVector(optional_ptr<duckdb_libpgquery::PGList> column_list, idx_t &size);
332 vector<string> TransformConflictTarget(duckdb_libpgquery::PGList &list);
333
334private:
335 //! Current stack depth
336 idx_t stack_depth;
337
338 void InitializeStackCheck();
339 StackChecker StackCheck(idx_t extra_stack = 1);
340
341public:
342 template <class T>
343 static T &PGCast(duckdb_libpgquery::PGNode &node) {
344 return reinterpret_cast<T &>(node);
345 }
346 template <class T>
347 static optional_ptr<T> PGPointerCast(void *ptr) {
348 return optional_ptr<T>(reinterpret_cast<T *>(ptr));
349 }
350};
351
352class StackChecker {
353public:
354 StackChecker(Transformer &transformer, idx_t stack_usage);
355 ~StackChecker();
356 StackChecker(StackChecker &&) noexcept;
357 StackChecker(const StackChecker &) = delete;
358
359private:
360 Transformer &transformer;
361 idx_t stack_usage;
362};
363
364vector<string> ReadPgListToString(duckdb_libpgquery::PGList *column_list);
365
366} // namespace duckdb
367