duckdb 0.7.2-dev865.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/catalog/default/default_functions.cpp +3 -0
- package/src/duckdb/src/catalog/duck_catalog.cpp +34 -7
- package/src/duckdb/src/common/box_renderer.cpp +109 -23
- 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/catalog/duck_catalog.hpp +2 -1
- package/src/duckdb/src/include/duckdb/common/box_renderer.hpp +8 -2
- package/src/duckdb/src/include/duckdb/optimizer/filter_pushdown.hpp +2 -0
- 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/optimizer/filter_pushdown.cpp +11 -7
- package/src/duckdb/src/optimizer/pushdown/pushdown_left_join.cpp +1 -10
- package/src/duckdb/src/optimizer/pushdown/pushdown_mark_join.cpp +1 -1
- package/src/duckdb/src/optimizer/pushdown/pushdown_single_join.cpp +1 -1
- package/src/duckdb/src/parser/tableref/pivotref.cpp +35 -11
- package/src/duckdb/src/parser/transform/statement/transform_pivot_stmt.cpp +41 -12
- 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 +8 -8
- 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 +11817 -11167
- package/src/duckdb/ub_src_planner_expression_binder.cpp +2 -0
@@ -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));
|
@@ -56,7 +56,7 @@ static void ConstructPivots(PivotRef &ref, idx_t pivot_idx, vector<unique_ptr<Pa
|
|
56
56
|
auto &function = (FunctionExpression &)*copy;
|
57
57
|
// add the filter and alias to the aggregate function
|
58
58
|
function.filter = expr->Copy();
|
59
|
-
if (ref.aggregates.size() > 1) {
|
59
|
+
if (ref.aggregates.size() > 1 || !function.alias.empty()) {
|
60
60
|
// if there are multiple aggregates specified we add the name of the aggregate as well
|
61
61
|
function.alias = name + "_" + function.GetName();
|
62
62
|
} else {
|
@@ -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
|
|
@@ -1,145 +1,14 @@
|
|
1
1
|
#include "duckdb/planner/expression_binder/select_binder.hpp"
|
2
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
3
|
namespace duckdb {
|
15
4
|
|
16
5
|
SelectBinder::SelectBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info,
|
17
6
|
case_insensitive_map_t<idx_t> alias_map)
|
18
|
-
:
|
7
|
+
: BaseSelectBinder(binder, context, node, info, std::move(alias_map)) {
|
19
8
|
}
|
20
9
|
|
21
10
|
SelectBinder::SelectBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info)
|
22
11
|
: SelectBinder(binder, context, node, info, case_insensitive_map_t<idx_t>()) {
|
23
12
|
}
|
24
13
|
|
25
|
-
BindResult SelectBinder::BindExpression(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth, bool root_expression) {
|
26
|
-
auto &expr = **expr_ptr;
|
27
|
-
// check if the expression binds to one of the groups
|
28
|
-
auto group_index = TryBindGroup(expr, depth);
|
29
|
-
if (group_index != DConstants::INVALID_INDEX) {
|
30
|
-
return BindGroup(expr, depth, group_index);
|
31
|
-
}
|
32
|
-
switch (expr.expression_class) {
|
33
|
-
case ExpressionClass::COLUMN_REF:
|
34
|
-
return BindColumnRef(expr_ptr, depth);
|
35
|
-
case ExpressionClass::DEFAULT:
|
36
|
-
return BindResult("SELECT clause cannot contain DEFAULT clause");
|
37
|
-
case ExpressionClass::WINDOW:
|
38
|
-
return BindWindow((WindowExpression &)expr, depth);
|
39
|
-
default:
|
40
|
-
return ExpressionBinder::BindExpression(expr_ptr, depth);
|
41
|
-
}
|
42
|
-
}
|
43
|
-
|
44
|
-
idx_t SelectBinder::TryBindGroup(ParsedExpression &expr, idx_t depth) {
|
45
|
-
// first check the group alias map, if expr is a ColumnRefExpression
|
46
|
-
if (expr.type == ExpressionType::COLUMN_REF) {
|
47
|
-
auto &colref = (ColumnRefExpression &)expr;
|
48
|
-
if (!colref.IsQualified()) {
|
49
|
-
auto alias_entry = info.alias_map.find(colref.column_names[0]);
|
50
|
-
if (alias_entry != info.alias_map.end()) {
|
51
|
-
// found entry!
|
52
|
-
return alias_entry->second;
|
53
|
-
}
|
54
|
-
}
|
55
|
-
}
|
56
|
-
// no alias reference found
|
57
|
-
// check the list of group columns for a match
|
58
|
-
auto entry = info.map.find(&expr);
|
59
|
-
if (entry != info.map.end()) {
|
60
|
-
return entry->second;
|
61
|
-
}
|
62
|
-
#ifdef DEBUG
|
63
|
-
for (auto entry : info.map) {
|
64
|
-
D_ASSERT(!entry.first->Equals(&expr));
|
65
|
-
D_ASSERT(!expr.Equals(entry.first));
|
66
|
-
}
|
67
|
-
#endif
|
68
|
-
return DConstants::INVALID_INDEX;
|
69
|
-
}
|
70
|
-
|
71
|
-
BindResult SelectBinder::BindColumnRef(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth) {
|
72
|
-
// first try to bind the column reference regularly
|
73
|
-
auto result = ExpressionBinder::BindExpression(expr_ptr, depth);
|
74
|
-
if (!result.HasError()) {
|
75
|
-
return result;
|
76
|
-
}
|
77
|
-
// binding failed
|
78
|
-
// check in the alias map
|
79
|
-
auto &colref = (ColumnRefExpression &)**expr_ptr;
|
80
|
-
if (!colref.IsQualified()) {
|
81
|
-
auto alias_entry = alias_map.find(colref.column_names[0]);
|
82
|
-
if (alias_entry != alias_map.end()) {
|
83
|
-
// found entry!
|
84
|
-
auto index = alias_entry->second;
|
85
|
-
if (index >= node.select_list.size()) {
|
86
|
-
throw BinderException("Column \"%s\" referenced that exists in the SELECT clause - but this column "
|
87
|
-
"cannot be referenced before it is defined",
|
88
|
-
colref.column_names[0]);
|
89
|
-
}
|
90
|
-
if (node.select_list[index]->HasSideEffects()) {
|
91
|
-
throw BinderException("Alias \"%s\" referenced in a SELECT clause - but the expression has side "
|
92
|
-
"effects. This is not yet supported.",
|
93
|
-
colref.column_names[0]);
|
94
|
-
}
|
95
|
-
if (node.select_list[index]->HasSubquery()) {
|
96
|
-
throw BinderException("Alias \"%s\" referenced in a SELECT clause - but the expression has a subquery."
|
97
|
-
" This is not yet supported.",
|
98
|
-
colref.column_names[0]);
|
99
|
-
}
|
100
|
-
auto result = BindResult(node.select_list[index]->Copy());
|
101
|
-
if (result.expression->type == ExpressionType::BOUND_COLUMN_REF) {
|
102
|
-
auto &result_expr = (BoundColumnRefExpression &)*result.expression;
|
103
|
-
result_expr.depth = depth;
|
104
|
-
}
|
105
|
-
return result;
|
106
|
-
}
|
107
|
-
}
|
108
|
-
// entry was not found in the alias map: return the original error
|
109
|
-
return result;
|
110
|
-
}
|
111
|
-
|
112
|
-
BindResult SelectBinder::BindGroupingFunction(OperatorExpression &op, idx_t depth) {
|
113
|
-
if (op.children.empty()) {
|
114
|
-
throw InternalException("GROUPING requires at least one child");
|
115
|
-
}
|
116
|
-
if (node.groups.group_expressions.empty()) {
|
117
|
-
return BindResult(binder.FormatError(op, "GROUPING statement cannot be used without groups"));
|
118
|
-
}
|
119
|
-
if (op.children.size() >= 64) {
|
120
|
-
return BindResult(binder.FormatError(op, "GROUPING statement cannot have more than 64 groups"));
|
121
|
-
}
|
122
|
-
vector<idx_t> group_indexes;
|
123
|
-
group_indexes.reserve(op.children.size());
|
124
|
-
for (auto &child : op.children) {
|
125
|
-
ExpressionBinder::QualifyColumnNames(binder, child);
|
126
|
-
auto idx = TryBindGroup(*child, depth);
|
127
|
-
if (idx == DConstants::INVALID_INDEX) {
|
128
|
-
return BindResult(binder.FormatError(
|
129
|
-
op, StringUtil::Format("GROUPING child \"%s\" must be a grouping column", child->GetName())));
|
130
|
-
}
|
131
|
-
group_indexes.push_back(idx);
|
132
|
-
}
|
133
|
-
auto col_idx = node.grouping_functions.size();
|
134
|
-
node.grouping_functions.push_back(std::move(group_indexes));
|
135
|
-
return BindResult(make_unique<BoundColumnRefExpression>(op.GetName(), LogicalType::BIGINT,
|
136
|
-
ColumnBinding(node.groupings_index, col_idx), depth));
|
137
|
-
}
|
138
|
-
|
139
|
-
BindResult SelectBinder::BindGroup(ParsedExpression &expr, idx_t depth, idx_t group_index) {
|
140
|
-
auto &group = node.groups.group_expressions[group_index];
|
141
|
-
return BindResult(make_unique<BoundColumnRefExpression>(expr.GetName(), group->return_type,
|
142
|
-
ColumnBinding(node.group_index, group_index), depth));
|
143
|
-
}
|
144
|
-
|
145
14
|
} // namespace duckdb
|
@@ -1,6 +1,7 @@
|
|
1
1
|
#include "duckdb/planner/expression_binder.hpp"
|
2
2
|
|
3
3
|
#include "duckdb/parser/expression/columnref_expression.hpp"
|
4
|
+
#include "duckdb/parser/expression/function_expression.hpp"
|
4
5
|
#include "duckdb/parser/expression/positional_reference_expression.hpp"
|
5
6
|
#include "duckdb/parser/expression/subquery_expression.hpp"
|
6
7
|
#include "duckdb/parser/parsed_expression_iterator.hpp"
|
@@ -52,9 +53,15 @@ BindResult ExpressionBinder::BindExpression(unique_ptr<ParsedExpression> *expr,
|
|
52
53
|
return BindExpression((ConjunctionExpression &)expr_ref, depth);
|
53
54
|
case ExpressionClass::CONSTANT:
|
54
55
|
return BindExpression((ConstantExpression &)expr_ref, depth);
|
55
|
-
case ExpressionClass::FUNCTION:
|
56
|
+
case ExpressionClass::FUNCTION: {
|
57
|
+
auto &function = (FunctionExpression &)expr_ref;
|
58
|
+
if (function.function_name == "unnest" || function.function_name == "unlist") {
|
59
|
+
// special case, not in catalog
|
60
|
+
return BindUnnest(function, depth, root_expression);
|
61
|
+
}
|
56
62
|
// binding function expression has extra parameter needed for macro's
|
57
|
-
return BindExpression(
|
63
|
+
return BindExpression(function, depth, expr);
|
64
|
+
}
|
58
65
|
case ExpressionClass::LAMBDA:
|
59
66
|
return BindExpression((LambdaExpression &)expr_ref, depth, false, LogicalTypeId::INVALID);
|
60
67
|
case ExpressionClass::OPERATOR:
|
@@ -200,22 +200,24 @@ void ExpressionIterator::EnumerateQueryNodeChildren(BoundQueryNode &node,
|
|
200
200
|
}
|
201
201
|
case QueryNodeType::SELECT_NODE: {
|
202
202
|
auto &bound_select = (BoundSelectNode &)node;
|
203
|
-
for (
|
204
|
-
EnumerateExpression(
|
203
|
+
for (auto &expr : bound_select.select_list) {
|
204
|
+
EnumerateExpression(expr, callback);
|
205
205
|
}
|
206
206
|
EnumerateExpression(bound_select.where_clause, callback);
|
207
|
-
for (
|
208
|
-
EnumerateExpression(
|
207
|
+
for (auto &expr : bound_select.groups.group_expressions) {
|
208
|
+
EnumerateExpression(expr, callback);
|
209
209
|
}
|
210
210
|
EnumerateExpression(bound_select.having, callback);
|
211
|
-
for (
|
212
|
-
EnumerateExpression(
|
211
|
+
for (auto &expr : bound_select.aggregates) {
|
212
|
+
EnumerateExpression(expr, callback);
|
213
213
|
}
|
214
|
-
for (
|
215
|
-
|
214
|
+
for (auto &entry : bound_select.unnests) {
|
215
|
+
for (auto &expr : entry.second.expressions) {
|
216
|
+
EnumerateExpression(expr, callback);
|
217
|
+
}
|
216
218
|
}
|
217
|
-
for (
|
218
|
-
EnumerateExpression(
|
219
|
+
for (auto &expr : bound_select.windows) {
|
220
|
+
EnumerateExpression(expr, callback);
|
219
221
|
}
|
220
222
|
if (bound_select.from_table) {
|
221
223
|
EnumerateTableRefChildren(*bound_select.from_table, callback);
|
@@ -1169,6 +1169,7 @@ typedef struct PGUpdateStmt {
|
|
1169
1169
|
typedef struct PGPivot {
|
1170
1170
|
PGNodeTag type;
|
1171
1171
|
PGList *pivot_columns; /* The column names to pivot on */
|
1172
|
+
PGList *unpivot_columns;/* The column names to unpivot */
|
1172
1173
|
PGList *pivot_value; /* The set of pivot values */
|
1173
1174
|
char *pivot_enum; /* The enum to fetch the unique values from */
|
1174
1175
|
} PGPivot;
|