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
18namespace duckdb {
19
20class Binder;
21class ClientContext;
22class QueryNode;
23
24class ScalarFunctionCatalogEntry;
25class AggregateFunctionCatalogEntry;
26class ScalarMacroCatalogEntry;
27class CatalogEntry;
28class SimpleFunction;
29
30struct DummyBinding;
31
32struct BoundColumnReferenceInfo {
33 string name;
34 idx_t query_location;
35};
36
37struct 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
53class ExpressionBinder {
54public:
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
65public:
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> CreateStructExtract(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 ExtractCorrelatedExpressions(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
113protected:
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
137protected:
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 &macro, 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