1 | //===----------------------------------------------------------------------===// |
2 | // DuckDB |
3 | // |
4 | // duckdb/planner/expression_binder.hpp |
5 | // |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #pragma once |
10 | |
11 | #include "duckdb/common/exception.hpp" |
12 | #include "duckdb/parser/expression/bound_expression.hpp" |
13 | #include "duckdb/parser/parsed_expression.hpp" |
14 | #include "duckdb/parser/tokens.hpp" |
15 | #include "duckdb/planner/expression.hpp" |
16 | #include "duckdb/common/unordered_map.hpp" |
17 | |
18 | namespace duckdb { |
19 | |
20 | class Binder; |
21 | class ClientContext; |
22 | class QueryNode; |
23 | |
24 | class ScalarFunctionCatalogEntry; |
25 | class AggregateFunctionCatalogEntry; |
26 | class ScalarMacroCatalogEntry; |
27 | class CatalogEntry; |
28 | class SimpleFunction; |
29 | |
30 | struct DummyBinding; |
31 | |
32 | struct BoundColumnReferenceInfo { |
33 | string name; |
34 | idx_t query_location; |
35 | }; |
36 | |
37 | struct BindResult { |
38 | BindResult() { |
39 | } |
40 | explicit BindResult(string error) : error(error) { |
41 | } |
42 | explicit BindResult(unique_ptr<Expression> expr) : expression(std::move(expr)) { |
43 | } |
44 | |
45 | bool HasError() { |
46 | return !error.empty(); |
47 | } |
48 | |
49 | unique_ptr<Expression> expression; |
50 | string error; |
51 | }; |
52 | |
53 | class ExpressionBinder { |
54 | public: |
55 | ExpressionBinder(Binder &binder, ClientContext &context, bool replace_binder = false); |
56 | virtual ~ExpressionBinder(); |
57 | |
58 | //! The target type that should result from the binder. If the result is not of this type, a cast to this type will |
59 | //! be added. Defaults to INVALID. |
60 | LogicalType target_type; |
61 | |
62 | optional_ptr<DummyBinding> macro_binding; |
63 | optional_ptr<vector<DummyBinding>> lambda_bindings; |
64 | |
65 | public: |
66 | unique_ptr<Expression> Bind(unique_ptr<ParsedExpression> &expr, optional_ptr<LogicalType> result_type = nullptr, |
67 | bool root_expression = true); |
68 | |
69 | //! Returns whether or not any columns have been bound by the expression binder |
70 | bool HasBoundColumns() { |
71 | return !bound_columns.empty(); |
72 | } |
73 | const vector<BoundColumnReferenceInfo> &GetBoundColumns() { |
74 | return bound_columns; |
75 | } |
76 | |
77 | string Bind(unique_ptr<ParsedExpression> &expr, idx_t depth, bool root_expression = false); |
78 | |
79 | unique_ptr<ParsedExpression> (unique_ptr<ParsedExpression> base, string field_name); |
80 | unique_ptr<ParsedExpression> CreateStructPack(ColumnRefExpression &colref); |
81 | BindResult BindQualifiedColumnName(ColumnRefExpression &colref, const string &table_name); |
82 | |
83 | unique_ptr<ParsedExpression> QualifyColumnName(const string &column_name, string &error_message); |
84 | unique_ptr<ParsedExpression> QualifyColumnName(ColumnRefExpression &colref, string &error_message); |
85 | |
86 | // Bind table names to ColumnRefExpressions |
87 | void QualifyColumnNames(unique_ptr<ParsedExpression> &expr); |
88 | static void QualifyColumnNames(Binder &binder, unique_ptr<ParsedExpression> &expr); |
89 | |
90 | static unique_ptr<Expression> PushCollation(ClientContext &context, unique_ptr<Expression> source, |
91 | const string &collation, bool equality_only = false); |
92 | static void TestCollation(ClientContext &context, const string &collation); |
93 | |
94 | bool BindCorrelatedColumns(unique_ptr<ParsedExpression> &expr); |
95 | |
96 | void BindChild(unique_ptr<ParsedExpression> &expr, idx_t depth, string &error); |
97 | static void (Binder &binder, Expression &expr); |
98 | |
99 | static bool ContainsNullType(const LogicalType &type); |
100 | static LogicalType ExchangeNullType(const LogicalType &type); |
101 | static bool ContainsType(const LogicalType &type, LogicalTypeId target); |
102 | static LogicalType ExchangeType(const LogicalType &type, LogicalTypeId target, LogicalType new_type); |
103 | |
104 | virtual bool QualifyColumnAlias(const ColumnRefExpression &colref); |
105 | |
106 | //! Bind the given expresion. Unlike Bind(), this does *not* mute the given ParsedExpression. |
107 | //! Exposed to be used from sub-binders that aren't subclasses of ExpressionBinder. |
108 | virtual BindResult BindExpression(unique_ptr<ParsedExpression> &expr_ptr, idx_t depth, |
109 | bool root_expression = false); |
110 | |
111 | void ReplaceMacroParametersRecursive(unique_ptr<ParsedExpression> &expr); |
112 | |
113 | protected: |
114 | BindResult BindExpression(BetweenExpression &expr, idx_t depth); |
115 | BindResult BindExpression(CaseExpression &expr, idx_t depth); |
116 | BindResult BindExpression(CollateExpression &expr, idx_t depth); |
117 | BindResult BindExpression(CastExpression &expr, idx_t depth); |
118 | BindResult BindExpression(ColumnRefExpression &expr, idx_t depth); |
119 | BindResult BindExpression(ComparisonExpression &expr, idx_t depth); |
120 | BindResult BindExpression(ConjunctionExpression &expr, idx_t depth); |
121 | BindResult BindExpression(ConstantExpression &expr, idx_t depth); |
122 | BindResult BindExpression(FunctionExpression &expr, idx_t depth, unique_ptr<ParsedExpression> &expr_ptr); |
123 | BindResult BindExpression(LambdaExpression &expr, idx_t depth, const bool is_lambda, |
124 | const LogicalType &list_child_type); |
125 | BindResult BindExpression(OperatorExpression &expr, idx_t depth); |
126 | BindResult BindExpression(ParameterExpression &expr, idx_t depth); |
127 | BindResult BindExpression(SubqueryExpression &expr, idx_t depth); |
128 | BindResult BindPositionalReference(unique_ptr<ParsedExpression> &expr, idx_t depth, bool root_expression); |
129 | |
130 | void TransformCapturedLambdaColumn(unique_ptr<Expression> &original, unique_ptr<Expression> &replacement, |
131 | vector<unique_ptr<Expression>> &captures, LogicalType &list_child_type); |
132 | void CaptureLambdaColumns(vector<unique_ptr<Expression>> &captures, LogicalType &list_child_type, |
133 | unique_ptr<Expression> &expr); |
134 | |
135 | static unique_ptr<ParsedExpression> GetSQLValueFunction(const string &column_name); |
136 | |
137 | protected: |
138 | virtual BindResult BindGroupingFunction(OperatorExpression &op, idx_t depth); |
139 | virtual BindResult BindFunction(FunctionExpression &expr, ScalarFunctionCatalogEntry &function, idx_t depth); |
140 | virtual BindResult BindLambdaFunction(FunctionExpression &expr, ScalarFunctionCatalogEntry &function, idx_t depth); |
141 | virtual BindResult BindAggregate(FunctionExpression &expr, AggregateFunctionCatalogEntry &function, idx_t depth); |
142 | virtual BindResult BindUnnest(FunctionExpression &expr, idx_t depth, bool root_expression); |
143 | virtual BindResult BindMacro(FunctionExpression &expr, ScalarMacroCatalogEntry ¯o, idx_t depth, |
144 | unique_ptr<ParsedExpression> &expr_ptr); |
145 | |
146 | virtual string UnsupportedAggregateMessage(); |
147 | virtual string UnsupportedUnnestMessage(); |
148 | |
149 | Binder &binder; |
150 | ClientContext &context; |
151 | optional_ptr<ExpressionBinder> stored_binder; |
152 | vector<BoundColumnReferenceInfo> bound_columns; |
153 | }; |
154 | |
155 | } // namespace duckdb |
156 | |