1 | #include "duckdb/planner/expression_binder/base_select_binder.hpp" |
2 | |
3 | #include "duckdb/parser/expression/columnref_expression.hpp" |
4 | #include "duckdb/parser/expression/window_expression.hpp" |
5 | #include "duckdb/parser/parsed_expression_iterator.hpp" |
6 | #include "duckdb/planner/expression/bound_columnref_expression.hpp" |
7 | #include "duckdb/planner/expression/bound_window_expression.hpp" |
8 | #include "duckdb/planner/expression_binder/aggregate_binder.hpp" |
9 | #include "duckdb/planner/query_node/bound_select_node.hpp" |
10 | #include "duckdb/parser/expression/operator_expression.hpp" |
11 | #include "duckdb/common/string_util.hpp" |
12 | #include "duckdb/planner/binder.hpp" |
13 | |
14 | namespace duckdb { |
15 | |
16 | BaseSelectBinder::BaseSelectBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, |
17 | BoundGroupInformation &info, case_insensitive_map_t<idx_t> alias_map) |
18 | : ExpressionBinder(binder, context), inside_window(false), node(node), info(info), alias_map(std::move(alias_map)) { |
19 | } |
20 | |
21 | BaseSelectBinder::BaseSelectBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, |
22 | BoundGroupInformation &info) |
23 | : BaseSelectBinder(binder, context, node, info, case_insensitive_map_t<idx_t>()) { |
24 | } |
25 | |
26 | BindResult BaseSelectBinder::BindExpression(unique_ptr<ParsedExpression> &expr_ptr, idx_t depth, bool root_expression) { |
27 | auto &expr = *expr_ptr; |
28 | // check if the expression binds to one of the groups |
29 | auto group_index = TryBindGroup(expr, depth); |
30 | if (group_index != DConstants::INVALID_INDEX) { |
31 | return BindGroup(expr, depth, group_index); |
32 | } |
33 | switch (expr.expression_class) { |
34 | case ExpressionClass::COLUMN_REF: |
35 | return BindColumnRef(expr_ptr, depth); |
36 | case ExpressionClass::DEFAULT: |
37 | return BindResult("SELECT clause cannot contain DEFAULT clause" ); |
38 | case ExpressionClass::WINDOW: |
39 | return BindWindow(expr&: expr.Cast<WindowExpression>(), depth); |
40 | default: |
41 | return ExpressionBinder::BindExpression(expr_ptr, depth, root_expression); |
42 | } |
43 | } |
44 | |
45 | idx_t BaseSelectBinder::TryBindGroup(ParsedExpression &expr, idx_t depth) { |
46 | // first check the group alias map, if expr is a ColumnRefExpression |
47 | if (expr.type == ExpressionType::COLUMN_REF) { |
48 | auto &colref = expr.Cast<ColumnRefExpression>(); |
49 | if (!colref.IsQualified()) { |
50 | auto alias_entry = info.alias_map.find(x: colref.column_names[0]); |
51 | if (alias_entry != info.alias_map.end()) { |
52 | // found entry! |
53 | return alias_entry->second; |
54 | } |
55 | } |
56 | } |
57 | // no alias reference found |
58 | // check the list of group columns for a match |
59 | auto entry = info.map.find(x: expr); |
60 | if (entry != info.map.end()) { |
61 | return entry->second; |
62 | } |
63 | #ifdef DEBUG |
64 | for (auto entry : info.map) { |
65 | D_ASSERT(!entry.first.get().Equals(expr)); |
66 | D_ASSERT(!expr.Equals(entry.first.get())); |
67 | } |
68 | #endif |
69 | return DConstants::INVALID_INDEX; |
70 | } |
71 | |
72 | BindResult BaseSelectBinder::BindColumnRef(unique_ptr<ParsedExpression> &expr_ptr, idx_t depth) { |
73 | // first try to bind the column reference regularly |
74 | auto result = ExpressionBinder::BindExpression(expr_ptr, depth); |
75 | if (!result.HasError()) { |
76 | return result; |
77 | } |
78 | // binding failed |
79 | // check in the alias map |
80 | auto &colref = (expr_ptr.get())->Cast<ColumnRefExpression>(); |
81 | if (!colref.IsQualified()) { |
82 | auto alias_entry = alias_map.find(x: colref.column_names[0]); |
83 | if (alias_entry != alias_map.end()) { |
84 | // found entry! |
85 | auto index = alias_entry->second; |
86 | if (index >= node.select_list.size()) { |
87 | throw BinderException("Column \"%s\" referenced that exists in the SELECT clause - but this column " |
88 | "cannot be referenced before it is defined" , |
89 | colref.column_names[0]); |
90 | } |
91 | if (node.select_list[index]->HasSideEffects()) { |
92 | throw BinderException("Alias \"%s\" referenced in a SELECT clause - but the expression has side " |
93 | "effects. This is not yet supported." , |
94 | colref.column_names[0]); |
95 | } |
96 | if (node.select_list[index]->HasSubquery()) { |
97 | throw BinderException("Alias \"%s\" referenced in a SELECT clause - but the expression has a subquery." |
98 | " This is not yet supported." , |
99 | colref.column_names[0]); |
100 | } |
101 | auto result = BindResult(node.select_list[index]->Copy()); |
102 | if (result.expression->type == ExpressionType::BOUND_COLUMN_REF) { |
103 | auto &result_expr = result.expression->Cast<BoundColumnRefExpression>(); |
104 | result_expr.depth = depth; |
105 | } |
106 | return result; |
107 | } |
108 | } |
109 | // entry was not found in the alias map: return the original error |
110 | return result; |
111 | } |
112 | |
113 | BindResult BaseSelectBinder::BindGroupingFunction(OperatorExpression &op, idx_t depth) { |
114 | if (op.children.empty()) { |
115 | throw InternalException("GROUPING requires at least one child" ); |
116 | } |
117 | if (node.groups.group_expressions.empty()) { |
118 | return BindResult(binder.FormatError(expr_context&: op, message: "GROUPING statement cannot be used without groups" )); |
119 | } |
120 | if (op.children.size() >= 64) { |
121 | return BindResult(binder.FormatError(expr_context&: op, message: "GROUPING statement cannot have more than 64 groups" )); |
122 | } |
123 | vector<idx_t> group_indexes; |
124 | group_indexes.reserve(n: op.children.size()); |
125 | for (auto &child : op.children) { |
126 | ExpressionBinder::QualifyColumnNames(binder, expr&: child); |
127 | auto idx = TryBindGroup(expr&: *child, depth); |
128 | if (idx == DConstants::INVALID_INDEX) { |
129 | return BindResult(binder.FormatError( |
130 | expr_context&: op, message: StringUtil::Format(fmt_str: "GROUPING child \"%s\" must be a grouping column" , params: child->GetName()))); |
131 | } |
132 | group_indexes.push_back(x: idx); |
133 | } |
134 | auto col_idx = node.grouping_functions.size(); |
135 | node.grouping_functions.push_back(x: std::move(group_indexes)); |
136 | return BindResult(make_uniq<BoundColumnRefExpression>(args: op.GetName(), args: LogicalType::BIGINT, |
137 | args: ColumnBinding(node.groupings_index, col_idx), args&: depth)); |
138 | } |
139 | |
140 | BindResult BaseSelectBinder::BindGroup(ParsedExpression &expr, idx_t depth, idx_t group_index) { |
141 | auto &group = node.groups.group_expressions[group_index]; |
142 | return BindResult(make_uniq<BoundColumnRefExpression>(args: expr.GetName(), args&: group->return_type, |
143 | args: ColumnBinding(node.group_index, group_index), args&: depth)); |
144 | } |
145 | |
146 | bool BaseSelectBinder::QualifyColumnAlias(const ColumnRefExpression &colref) { |
147 | if (!colref.IsQualified()) { |
148 | return alias_map.find(x: colref.column_names[0]) != alias_map.end() ? true : false; |
149 | } |
150 | return false; |
151 | } |
152 | |
153 | } // namespace duckdb |
154 | |