| 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 | |