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.
- package/package.json +1 -1
- package/src/duckdb/src/function/scalar/struct/struct_extract.cpp +1 -1
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +4 -2
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +2 -2
- package/src/duckdb/src/include/duckdb/planner/binder.hpp +3 -1
- package/src/duckdb/src/include/duckdb/planner/expression_binder/base_select_binder.hpp +64 -0
- package/src/duckdb/src/include/duckdb/planner/expression_binder/having_binder.hpp +2 -2
- package/src/duckdb/src/include/duckdb/planner/expression_binder/qualify_binder.hpp +2 -2
- package/src/duckdb/src/include/duckdb/planner/expression_binder/select_binder.hpp +9 -38
- package/src/duckdb/src/include/duckdb/planner/expression_binder.hpp +1 -1
- package/src/duckdb/src/include/duckdb/planner/query_node/bound_select_node.hpp +8 -2
- package/src/duckdb/src/parser/tableref/pivotref.cpp +35 -11
- package/src/duckdb/src/parser/transform/statement/transform_pivot_stmt.cpp +10 -6
- package/src/duckdb/src/parser/transform/tableref/transform_pivot.cpp +19 -3
- package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +2 -2
- package/src/duckdb/src/planner/binder/expression/bind_function_expression.cpp +1 -8
- package/src/duckdb/src/planner/binder/expression/bind_unnest_expression.cpp +163 -24
- package/src/duckdb/src/planner/binder/expression/bind_window_expression.cpp +2 -2
- package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +23 -3
- package/src/duckdb/src/planner/binder/query_node/plan_select_node.cpp +9 -3
- package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +7 -7
- package/src/duckdb/src/planner/expression_binder/base_select_binder.cpp +146 -0
- package/src/duckdb/src/planner/expression_binder/having_binder.cpp +3 -3
- package/src/duckdb/src/planner/expression_binder/qualify_binder.cpp +3 -3
- package/src/duckdb/src/planner/expression_binder/select_binder.cpp +1 -132
- package/src/duckdb/src/planner/expression_binder.cpp +9 -2
- package/src/duckdb/src/planner/expression_iterator.cpp +12 -10
- package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +1 -0
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +14579 -14017
- 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
|
-
|
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
|
-
|
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 (
|
35
|
-
|
36
|
-
|
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
|
-
|
44
|
-
|
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
|
-
|
51
|
-
|
116
|
+
idx_t list_unnests;
|
117
|
+
idx_t struct_unnests = 0;
|
52
118
|
|
53
|
-
auto
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
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
|
122
|
+
BindResult BaseSelectBinder::BindWindow(WindowExpression &window, idx_t depth) {
|
123
123
|
auto name = window.GetName();
|
124
124
|
|
125
|
-
QueryErrorContext error_context(binder.
|
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 (
|
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
|
-
|
92
|
-
auto
|
93
|
-
|
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.
|
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 =
|
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.
|
130
|
-
|
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.
|
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.
|
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.
|
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
|
-
:
|
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::
|
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::
|
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
|
-
:
|
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::
|
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::
|
46
|
+
return duckdb::BaseSelectBinder::BindExpression(expr_ptr, depth);
|
47
47
|
}
|
48
48
|
}
|
49
49
|
|