| 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 | |
| 26 | namespace duckdb { |
| 27 | |
| 28 | class ColumnDefinition; |
| 29 | class StackChecker; |
| 30 | struct OrderByNode; |
| 31 | struct CopyInfo; |
| 32 | struct CommonTableExpressionInfo; |
| 33 | struct GroupingExpressionMap; |
| 34 | class OnConflictInfo; |
| 35 | class UpdateSetInfo; |
| 36 | struct ParserOptions; |
| 37 | struct PivotColumn; |
| 38 | |
| 39 | //! The transformer class is responsible for transforming the internal Postgres |
| 40 | //! parser representation into the DuckDB representation |
| 41 | class 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 | |
| 51 | public: |
| 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 | |
| 62 | private: |
| 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 (CommonTableExpressionMap &cte_map); |
| 97 | |
| 98 | private: |
| 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 | |
| 334 | private: |
| 335 | //! Current stack depth |
| 336 | idx_t stack_depth; |
| 337 | |
| 338 | void InitializeStackCheck(); |
| 339 | StackChecker StackCheck(idx_t = 1); |
| 340 | |
| 341 | public: |
| 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 | |
| 352 | class StackChecker { |
| 353 | public: |
| 354 | StackChecker(Transformer &transformer, idx_t stack_usage); |
| 355 | ~StackChecker(); |
| 356 | StackChecker(StackChecker &&) noexcept; |
| 357 | StackChecker(const StackChecker &) = delete; |
| 358 | |
| 359 | private: |
| 360 | Transformer &transformer; |
| 361 | idx_t stack_usage; |
| 362 | }; |
| 363 | |
| 364 | vector<string> ReadPgListToString(duckdb_libpgquery::PGList *column_list); |
| 365 | |
| 366 | } // namespace duckdb |
| 367 | |