duckdb 0.7.2-dev886.0 → 0.7.2-dev899.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/package.json +1 -1
  2. package/src/duckdb/src/function/scalar/struct/struct_extract.cpp +1 -1
  3. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  4. package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +4 -2
  5. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +2 -2
  6. package/src/duckdb/src/include/duckdb/planner/binder.hpp +3 -1
  7. package/src/duckdb/src/include/duckdb/planner/expression_binder/base_select_binder.hpp +64 -0
  8. package/src/duckdb/src/include/duckdb/planner/expression_binder/having_binder.hpp +2 -2
  9. package/src/duckdb/src/include/duckdb/planner/expression_binder/qualify_binder.hpp +2 -2
  10. package/src/duckdb/src/include/duckdb/planner/expression_binder/select_binder.hpp +9 -38
  11. package/src/duckdb/src/include/duckdb/planner/expression_binder.hpp +1 -1
  12. package/src/duckdb/src/include/duckdb/planner/query_node/bound_select_node.hpp +8 -2
  13. package/src/duckdb/src/parser/tableref/pivotref.cpp +35 -11
  14. package/src/duckdb/src/parser/transform/statement/transform_pivot_stmt.cpp +10 -6
  15. package/src/duckdb/src/parser/transform/tableref/transform_pivot.cpp +19 -3
  16. package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +2 -2
  17. package/src/duckdb/src/planner/binder/expression/bind_function_expression.cpp +1 -8
  18. package/src/duckdb/src/planner/binder/expression/bind_unnest_expression.cpp +163 -24
  19. package/src/duckdb/src/planner/binder/expression/bind_window_expression.cpp +2 -2
  20. package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +23 -3
  21. package/src/duckdb/src/planner/binder/query_node/plan_select_node.cpp +9 -3
  22. package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +7 -7
  23. package/src/duckdb/src/planner/expression_binder/base_select_binder.cpp +146 -0
  24. package/src/duckdb/src/planner/expression_binder/having_binder.cpp +3 -3
  25. package/src/duckdb/src/planner/expression_binder/qualify_binder.cpp +3 -3
  26. package/src/duckdb/src/planner/expression_binder/select_binder.cpp +1 -132
  27. package/src/duckdb/src/planner/expression_binder.cpp +9 -2
  28. package/src/duckdb/src/planner/expression_iterator.cpp +12 -10
  29. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +1 -0
  30. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +14579 -14017
  31. package/src/duckdb/ub_src_planner_expression_binder.cpp +2 -0
@@ -3,21 +3,86 @@
3
3
  #include "duckdb/parser/expression/function_expression.hpp"
4
4
  #include "duckdb/planner/expression/bound_aggregate_expression.hpp"
5
5
  #include "duckdb/planner/expression/bound_columnref_expression.hpp"
6
+ #include "duckdb/planner/expression/bound_constant_expression.hpp"
7
+ #include "duckdb/planner/expression/bound_function_expression.hpp"
6
8
  #include "duckdb/planner/expression/bound_parameter_expression.hpp"
7
9
  #include "duckdb/planner/expression_binder/aggregate_binder.hpp"
8
10
  #include "duckdb/planner/expression_binder/select_binder.hpp"
9
11
  #include "duckdb/planner/query_node/bound_select_node.hpp"
10
12
  #include "duckdb/planner/expression/bound_unnest_expression.hpp"
11
13
  #include "duckdb/planner/binder.hpp"
14
+ #include "duckdb/function/scalar/nested_functions.hpp"
15
+ #include "duckdb/execution/expression_executor.hpp"
12
16
 
13
17
  namespace duckdb {
14
18
 
15
- BindResult SelectBinder::BindUnnest(FunctionExpression &function, idx_t depth) {
19
+ unique_ptr<Expression> CreateBoundStructExtract(ClientContext &context, unique_ptr<Expression> expr, string key) {
20
+ vector<unique_ptr<Expression>> arguments;
21
+ arguments.push_back(std::move(expr));
22
+ arguments.push_back(make_unique<BoundConstantExpression>(Value(key)));
23
+ auto extract_function = StructExtractFun::GetFunction();
24
+ auto bind_info = extract_function.bind(context, extract_function, arguments);
25
+ auto return_type = extract_function.return_type;
26
+ auto result = make_unique<BoundFunctionExpression>(return_type, std::move(extract_function), std::move(arguments),
27
+ std::move(bind_info));
28
+ result->alias = std::move(key);
29
+ return std::move(result);
30
+ }
31
+
32
+ BindResult SelectBinder::BindUnnest(FunctionExpression &function, idx_t depth, bool root_expression) {
16
33
  // bind the children of the function expression
34
+ if (depth > 0) {
35
+ return BindResult(binder.FormatError(function, "UNNEST() for correlated expressions is not supported yet"));
36
+ }
17
37
  string error;
38
+ if (function.children.empty()) {
39
+ return BindResult(binder.FormatError(function, "UNNEST() requires a single argument"));
40
+ }
41
+ idx_t max_depth = 1;
18
42
  if (function.children.size() != 1) {
19
- return BindResult(binder.FormatError(function, "Unnest() needs exactly one child expressions"));
43
+ bool has_parameter = false;
44
+ bool supported_argument = false;
45
+ for (idx_t i = 1; i < function.children.size(); i++) {
46
+ if (has_parameter) {
47
+ return BindResult(binder.FormatError(function, "UNNEST() only supports a single additional argument"));
48
+ }
49
+ if (function.children[i]->HasParameter()) {
50
+ throw ParameterNotAllowedException("Parameter not allowed in unnest parameter");
51
+ }
52
+ if (!function.children[i]->IsScalar()) {
53
+ break;
54
+ }
55
+ auto alias = function.children[i]->alias;
56
+ BindChild(function.children[i], depth, error);
57
+ if (!error.empty()) {
58
+ return BindResult(error);
59
+ }
60
+ auto &const_child = (BoundExpression &)*function.children[i];
61
+ auto value = ExpressionExecutor::EvaluateScalar(context, *const_child.expr, true);
62
+ if (alias == "recursive") {
63
+ auto recursive = value.GetValue<bool>();
64
+ if (recursive) {
65
+ max_depth = NumericLimits<idx_t>::Maximum();
66
+ }
67
+ } else if (alias == "max_depth") {
68
+ max_depth = value.GetValue<uint32_t>();
69
+ if (max_depth == 0) {
70
+ throw BinderException("UNNEST cannot have a max depth of 0");
71
+ }
72
+ } else if (!alias.empty()) {
73
+ throw BinderException("Unsupported parameter \"%s\" for unnest", alias);
74
+ } else {
75
+ break;
76
+ }
77
+ has_parameter = true;
78
+ supported_argument = true;
79
+ }
80
+ if (!supported_argument) {
81
+ return BindResult(binder.FormatError(function, "UNNEST - unsupported extra argument, unnest only supports "
82
+ "recursive := [true/false] or max_depth := #"));
83
+ }
20
84
  }
85
+ unnest_level++;
21
86
  BindChild(function.children[0], depth, error);
22
87
  if (!error.empty()) {
23
88
  // failed to bind
@@ -30,37 +95,111 @@ BindResult SelectBinder::BindUnnest(FunctionExpression &function, idx_t depth) {
30
95
  }
31
96
  auto &child = (BoundExpression &)*function.children[0];
32
97
  auto &child_type = child.expr->return_type;
98
+ unnest_level--;
33
99
 
34
- if (child_type.id() != LogicalTypeId::LIST && child_type.id() != LogicalTypeId::SQLNULL &&
35
- child_type.id() != LogicalTypeId::UNKNOWN) {
36
- return BindResult(binder.FormatError(function, "Unnest() can only be applied to lists and NULL"));
37
- }
38
-
39
- if (depth > 0) {
40
- throw BinderException(binder.FormatError(function, "Unnest() for correlated expressions is not supported yet"));
100
+ if (unnest_level > 0) {
101
+ throw BinderException(
102
+ "Nested UNNEST calls are not supported - use UNNEST(x, recursive := true) to unnest multiple levels");
41
103
  }
42
104
 
43
- auto return_type = LogicalType(LogicalTypeId::SQLNULL);
44
- if (child_type.id() == LogicalTypeId::LIST) {
45
- return_type = ListType::GetChildType(child_type);
46
- } else if (child_type.id() == LogicalTypeId::UNKNOWN) {
105
+ switch (child_type.id()) {
106
+ case LogicalTypeId::UNKNOWN:
47
107
  throw ParameterNotResolvedException();
108
+ case LogicalTypeId::LIST:
109
+ case LogicalTypeId::STRUCT:
110
+ case LogicalTypeId::SQLNULL:
111
+ break;
112
+ default:
113
+ return BindResult(binder.FormatError(function, "UNNEST() can only be applied to lists, structs and NULL"));
48
114
  }
49
115
 
50
- auto result = make_unique<BoundUnnestExpression>(return_type);
51
- result->child = std::move(child.expr);
116
+ idx_t list_unnests;
117
+ idx_t struct_unnests = 0;
52
118
 
53
- auto unnest_index = node.unnests.size();
54
- node.unnests.push_back(std::move(result));
55
-
56
- // TODO what if we have multiple unnests in the same projection list? ignore for now
119
+ auto unnest_expr = std::move(child.expr);
120
+ if (child_type.id() == LogicalTypeId::SQLNULL) {
121
+ list_unnests = 1;
122
+ } else {
123
+ // first do all of the list unnests
124
+ auto type = child_type;
125
+ list_unnests = 0;
126
+ while (type.id() == LogicalTypeId::LIST) {
127
+ type = ListType::GetChildType(type);
128
+ list_unnests++;
129
+ if (list_unnests >= max_depth) {
130
+ break;
131
+ }
132
+ }
133
+ // unnest structs all the way afterwards, if there are any
134
+ if (type.id() == LogicalTypeId::STRUCT) {
135
+ struct_unnests = max_depth - list_unnests;
136
+ }
137
+ }
138
+ if (struct_unnests > 0 && !root_expression) {
139
+ return BindResult(binder.FormatError(
140
+ function, "UNNEST() on a struct column can only be applied as the root element of a SELECT expression"));
141
+ }
142
+ // perform all of the list unnests first
143
+ auto return_type = child_type;
144
+ for (idx_t current_depth = 0; current_depth < list_unnests; current_depth++) {
145
+ if (return_type.id() == LogicalTypeId::LIST) {
146
+ return_type = ListType::GetChildType(return_type);
147
+ }
148
+ auto result = make_unique<BoundUnnestExpression>(return_type);
149
+ result->child = std::move(unnest_expr);
150
+ auto alias = function.alias.empty() ? result->ToString() : function.alias;
57
151
 
58
- // now create a column reference referring to the unnest
59
- auto colref = make_unique<BoundColumnRefExpression>(
60
- function.alias.empty() ? node.unnests[unnest_index]->ToString() : function.alias, return_type,
61
- ColumnBinding(node.unnest_index, unnest_index), depth);
152
+ auto current_level = unnest_level + list_unnests - current_depth - 1;
153
+ auto entry = node.unnests.find(current_level);
154
+ idx_t unnest_table_index;
155
+ idx_t unnest_column_index;
156
+ if (entry == node.unnests.end()) {
157
+ BoundUnnestNode unnest_node;
158
+ unnest_node.index = binder.GenerateTableIndex();
159
+ unnest_node.expressions.push_back(std::move(result));
160
+ unnest_table_index = unnest_node.index;
161
+ unnest_column_index = 0;
162
+ node.unnests.insert(make_pair(current_level, std::move(unnest_node)));
163
+ } else {
164
+ unnest_table_index = entry->second.index;
165
+ unnest_column_index = entry->second.expressions.size();
166
+ entry->second.expressions.push_back(std::move(result));
167
+ }
168
+ // now create a column reference referring to the unnest
169
+ unnest_expr = make_unique<BoundColumnRefExpression>(
170
+ std::move(alias), return_type, ColumnBinding(unnest_table_index, unnest_column_index), depth);
171
+ }
172
+ // now perform struct unnests, if any
173
+ if (struct_unnests > 0) {
174
+ vector<unique_ptr<Expression>> struct_expressions;
175
+ struct_expressions.push_back(std::move(unnest_expr));
62
176
 
63
- return BindResult(std::move(colref));
177
+ for (idx_t i = 0; i < struct_unnests; i++) {
178
+ vector<unique_ptr<Expression>> new_expressions;
179
+ // check if there are any structs left
180
+ bool has_structs = false;
181
+ for (auto &expr : struct_expressions) {
182
+ if (expr->return_type.id() == LogicalTypeId::STRUCT) {
183
+ // struct! push a struct_extract
184
+ auto &child_types = StructType::GetChildTypes(expr->return_type);
185
+ for (auto &entry : child_types) {
186
+ new_expressions.push_back(CreateBoundStructExtract(context, expr->Copy(), entry.first));
187
+ }
188
+ has_structs = true;
189
+ } else {
190
+ // not a struct - push as-is
191
+ new_expressions.push_back(std::move(expr));
192
+ }
193
+ }
194
+ struct_expressions = std::move(new_expressions);
195
+ if (!has_structs) {
196
+ break;
197
+ }
198
+ }
199
+ expanded_expressions = std::move(struct_expressions);
200
+ unnest_expr = make_unique<BoundConstantExpression>(Value(42));
201
+ }
202
+ return BindResult(std::move(unnest_expr));
64
203
  }
65
204
 
66
205
  } // namespace duckdb
@@ -119,10 +119,10 @@ static LogicalType BindRangeExpression(ClientContext &context, const string &nam
119
119
  return bound.expr->return_type;
120
120
  }
121
121
 
122
- BindResult SelectBinder::BindWindow(WindowExpression &window, idx_t depth) {
122
+ BindResult BaseSelectBinder::BindWindow(WindowExpression &window, idx_t depth) {
123
123
  auto name = window.GetName();
124
124
 
125
- QueryErrorContext error_context(binder.root_statement, window.query_location);
125
+ QueryErrorContext error_context(binder.GetRootStatement(), window.query_location);
126
126
  if (inside_window) {
127
127
  throw BinderException(error_context.FormatError("window function calls cannot be nested"));
128
128
  }
@@ -316,7 +316,6 @@ unique_ptr<BoundQueryNode> Binder::BindSelectNode(SelectNode &statement, unique_
316
316
  result->aggregate_index = GenerateTableIndex();
317
317
  result->groupings_index = GenerateTableIndex();
318
318
  result->window_index = GenerateTableIndex();
319
- result->unnest_index = GenerateTableIndex();
320
319
  result->prune_index = GenerateTableIndex();
321
320
 
322
321
  result->from_table = std::move(from_table);
@@ -427,14 +426,32 @@ unique_ptr<BoundQueryNode> Binder::BindSelectNode(SelectNode &statement, unique_
427
426
  SelectBinder select_binder(*this, context, *result, info, alias_map);
428
427
  vector<LogicalType> internal_sql_types;
429
428
  vector<idx_t> group_by_all_indexes;
429
+ vector<string> new_names;
430
430
  for (idx_t i = 0; i < statement.select_list.size(); i++) {
431
431
  bool is_window = statement.select_list[i]->IsWindow();
432
432
  idx_t unnest_count = result->unnests.size();
433
433
  LogicalType result_type;
434
- auto expr = select_binder.Bind(statement.select_list[i], &result_type);
434
+ auto expr = select_binder.Bind(statement.select_list[i], &result_type, true);
435
435
  bool is_original_column = i < result->column_count;
436
436
  bool can_group_by_all =
437
437
  statement.aggregate_handling == AggregateHandling::FORCE_AGGREGATES && is_original_column;
438
+ if (select_binder.HasExpandedExpressions()) {
439
+ if (!is_original_column) {
440
+ throw InternalException("Only original columns can have expanded expressions");
441
+ }
442
+ if (statement.aggregate_handling == AggregateHandling::FORCE_AGGREGATES) {
443
+ throw BinderException("UNNEST of struct cannot be combined with GROUP BY ALL");
444
+ }
445
+ auto &struct_expressions = select_binder.ExpandedExpressions();
446
+ D_ASSERT(!struct_expressions.empty());
447
+ for (auto &struct_expr : struct_expressions) {
448
+ new_names.push_back(struct_expr->GetName());
449
+ result->types.push_back(struct_expr->return_type);
450
+ result->select_list.push_back(std::move(struct_expr));
451
+ }
452
+ struct_expressions.clear();
453
+ continue;
454
+ }
438
455
  if (can_group_by_all && select_binder.HasBoundColumns()) {
439
456
  if (select_binder.BoundAggregates()) {
440
457
  throw BinderException("Cannot mix aggregates with non-aggregated columns!");
@@ -450,7 +467,8 @@ unique_ptr<BoundQueryNode> Binder::BindSelectNode(SelectNode &statement, unique_
450
467
  group_by_all_indexes.push_back(i);
451
468
  }
452
469
  result->select_list.push_back(std::move(expr));
453
- if (i < result->column_count) {
470
+ if (is_original_column) {
471
+ new_names.push_back(std::move(result->names[i]));
454
472
  result->types.push_back(result_type);
455
473
  }
456
474
  internal_sql_types.push_back(result_type);
@@ -466,6 +484,8 @@ unique_ptr<BoundQueryNode> Binder::BindSelectNode(SelectNode &statement, unique_
466
484
  result->groups.group_expressions.push_back(std::move(expr));
467
485
  expr = std::move(group_ref);
468
486
  }
487
+ result->column_count = new_names.size();
488
+ result->names = std::move(new_names);
469
489
  result->need_prune = result->select_list.size() > result->column_count;
470
490
 
471
491
  // in the normal select binder, we bind columns as if there is no aggregation
@@ -88,9 +88,15 @@ unique_ptr<LogicalOperator> Binder::CreatePlan(BoundSelectNode &statement) {
88
88
  root = std::move(qualify);
89
89
  }
90
90
 
91
- if (!statement.unnests.empty()) {
92
- auto unnest = make_unique<LogicalUnnest>(statement.unnest_index);
93
- unnest->expressions = std::move(statement.unnests);
91
+ for (idx_t i = statement.unnests.size(); i > 0; i--) {
92
+ auto unnest_level = i - 1;
93
+ auto entry = statement.unnests.find(unnest_level);
94
+ if (entry == statement.unnests.end()) {
95
+ throw InternalException("unnests specified at level %d but none were found", unnest_level);
96
+ }
97
+ auto &unnest_node = entry->second;
98
+ auto unnest = make_unique<LogicalUnnest>(unnest_node.index);
99
+ unnest->expressions = std::move(unnest_node.expressions);
94
100
  // visit the unnest expressions
95
101
  for (auto &expr : unnest->expressions) {
96
102
  PlanSubqueries(&expr, &root);
@@ -25,10 +25,10 @@ static void ConstructPivots(PivotRef &ref, idx_t pivot_idx, vector<unique_ptr<Pa
25
25
  for (auto &entry : pivot.entries) {
26
26
  unique_ptr<ParsedExpression> expr = current_expr ? current_expr->Copy() : nullptr;
27
27
  string name = entry.alias;
28
- D_ASSERT(entry.values.size() == pivot.names.size());
28
+ D_ASSERT(entry.values.size() == pivot.pivot_expressions.size());
29
29
  for (idx_t v = 0; v < entry.values.size(); v++) {
30
30
  auto &value = entry.values[v];
31
- auto column_ref = make_unique<ColumnRefExpression>(pivot.names[v]);
31
+ auto column_ref = pivot.pivot_expressions[v]->Copy();
32
32
  auto constant_value = make_unique<ConstantExpression>(value);
33
33
  auto comp_expr = make_unique<ComparisonExpression>(ExpressionType::COMPARE_NOT_DISTINCT_FROM,
34
34
  std::move(column_ref), std::move(constant_value));
@@ -126,8 +126,8 @@ unique_ptr<SelectNode> Binder::BindPivot(PivotRef &ref, vector<unique_ptr<Parsed
126
126
  }
127
127
  total_pivots *= pivot.entries.size();
128
128
  // add the pivoted column to the columns that have been handled
129
- for (auto &pivot_name : pivot.names) {
130
- handled_columns.insert(pivot_name);
129
+ for (auto &pivot_name : pivot.pivot_expressions) {
130
+ ExtractPivotExpressions(*pivot_name, handled_columns);
131
131
  }
132
132
  value_set_t pivots;
133
133
  for (auto &entry : pivot.entries) {
@@ -143,9 +143,9 @@ unique_ptr<SelectNode> Binder::BindPivot(PivotRef &ref, vector<unique_ptr<Parsed
143
143
  ref, StringUtil::Format("The value \"%s\" was specified multiple times in the IN clause",
144
144
  val.ToString())));
145
145
  }
146
- if (entry.values.size() != pivot.names.size()) {
146
+ if (entry.values.size() != pivot.pivot_expressions.size()) {
147
147
  throw ParserException("PIVOT IN list - inconsistent amount of rows - expected %d but got %d",
148
- pivot.names.size(), entry.values.size());
148
+ pivot.pivot_expressions.size(), entry.values.size());
149
149
  }
150
150
  pivots.insert(val);
151
151
  }
@@ -284,7 +284,7 @@ unique_ptr<SelectNode> Binder::BindUnpivot(Binder &child_binder, PivotRef &ref,
284
284
  vector<unique_ptr<ParsedExpression>> unnest_name_children;
285
285
  unnest_name_children.push_back(std::move(unpivot_name_expr));
286
286
  auto unnest_name_expr = make_unique<FunctionExpression>("unnest", std::move(unnest_name_children));
287
- unnest_name_expr->alias = unpivot.names[0];
287
+ unnest_name_expr->alias = unpivot.unpivot_names[0];
288
288
  select_node->select_list.push_back(std::move(unnest_name_expr));
289
289
 
290
290
  // construct the UNNEST expression for the set of unpivoted columns
@@ -0,0 +1,146 @@
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((WindowExpression &)expr, 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 = (ColumnRefExpression &)expr;
49
+ if (!colref.IsQualified()) {
50
+ auto alias_entry = info.alias_map.find(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(&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->Equals(&expr));
66
+ D_ASSERT(!expr.Equals(entry.first));
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 = (ColumnRefExpression &)**expr_ptr;
81
+ if (!colref.IsQualified()) {
82
+ auto alias_entry = alias_map.find(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 = (BoundColumnRefExpression &)*result.expression;
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(op, "GROUPING statement cannot be used without groups"));
119
+ }
120
+ if (op.children.size() >= 64) {
121
+ return BindResult(binder.FormatError(op, "GROUPING statement cannot have more than 64 groups"));
122
+ }
123
+ vector<idx_t> group_indexes;
124
+ group_indexes.reserve(op.children.size());
125
+ for (auto &child : op.children) {
126
+ ExpressionBinder::QualifyColumnNames(binder, child);
127
+ auto idx = TryBindGroup(*child, depth);
128
+ if (idx == DConstants::INVALID_INDEX) {
129
+ return BindResult(binder.FormatError(
130
+ op, StringUtil::Format("GROUPING child \"%s\" must be a grouping column", child->GetName())));
131
+ }
132
+ group_indexes.push_back(idx);
133
+ }
134
+ auto col_idx = node.grouping_functions.size();
135
+ node.grouping_functions.push_back(std::move(group_indexes));
136
+ return BindResult(make_unique<BoundColumnRefExpression>(op.GetName(), LogicalType::BIGINT,
137
+ ColumnBinding(node.groupings_index, col_idx), 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_unique<BoundColumnRefExpression>(expr.GetName(), group->return_type,
143
+ ColumnBinding(node.group_index, group_index), depth));
144
+ }
145
+
146
+ } // namespace duckdb
@@ -10,7 +10,7 @@ namespace duckdb {
10
10
 
11
11
  HavingBinder::HavingBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info,
12
12
  case_insensitive_map_t<idx_t> &alias_map, AggregateHandling aggregate_handling)
13
- : SelectBinder(binder, context, node, info), column_alias_binder(node, alias_map),
13
+ : BaseSelectBinder(binder, context, node, info), column_alias_binder(node, alias_map),
14
14
  aggregate_handling(aggregate_handling) {
15
15
  target_type = LogicalType(LogicalTypeId::BOOLEAN);
16
16
  }
@@ -28,7 +28,7 @@ BindResult HavingBinder::BindColumnRef(unique_ptr<ParsedExpression> *expr_ptr, i
28
28
  if (depth > 0) {
29
29
  throw BinderException("Having clause cannot reference column in correlated subquery and group by all");
30
30
  }
31
- auto expr = duckdb::SelectBinder::BindExpression(expr_ptr, depth);
31
+ auto expr = duckdb::BaseSelectBinder::BindExpression(expr_ptr, depth);
32
32
  if (expr.HasError()) {
33
33
  return expr;
34
34
  }
@@ -54,7 +54,7 @@ BindResult HavingBinder::BindExpression(unique_ptr<ParsedExpression> *expr_ptr,
54
54
  case ExpressionClass::COLUMN_REF:
55
55
  return BindColumnRef(expr_ptr, depth, root_expression);
56
56
  default:
57
- return duckdb::SelectBinder::BindExpression(expr_ptr, depth);
57
+ return duckdb::BaseSelectBinder::BindExpression(expr_ptr, depth);
58
58
  }
59
59
  }
60
60
 
@@ -10,13 +10,13 @@ namespace duckdb {
10
10
 
11
11
  QualifyBinder::QualifyBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info,
12
12
  case_insensitive_map_t<idx_t> &alias_map)
13
- : SelectBinder(binder, context, node, info), column_alias_binder(node, alias_map) {
13
+ : BaseSelectBinder(binder, context, node, info), column_alias_binder(node, alias_map) {
14
14
  target_type = LogicalType(LogicalTypeId::BOOLEAN);
15
15
  }
16
16
 
17
17
  BindResult QualifyBinder::BindColumnRef(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth, bool root_expression) {
18
18
  auto &expr = (ColumnRefExpression &)**expr_ptr;
19
- auto result = duckdb::SelectBinder::BindExpression(expr_ptr, depth);
19
+ auto result = duckdb::BaseSelectBinder::BindExpression(expr_ptr, depth);
20
20
  if (!result.HasError()) {
21
21
  return result;
22
22
  }
@@ -43,7 +43,7 @@ BindResult QualifyBinder::BindExpression(unique_ptr<ParsedExpression> *expr_ptr,
43
43
  case ExpressionClass::COLUMN_REF:
44
44
  return BindColumnRef(expr_ptr, depth, root_expression);
45
45
  default:
46
- return duckdb::SelectBinder::BindExpression(expr_ptr, depth);
46
+ return duckdb::BaseSelectBinder::BindExpression(expr_ptr, depth);
47
47
  }
48
48
  }
49
49