duckdb 0.7.2-dev886.0 → 0.7.2-dev904.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/lib/duckdb.d.ts +1 -1
- package/lib/duckdb.js +1 -1
- 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
package/lib/duckdb.d.ts
CHANGED
@@ -100,7 +100,7 @@ export class Connection {
|
|
100
100
|
unregister_udf(name: string, callback: Callback<any>): void;
|
101
101
|
|
102
102
|
stream(sql: any, ...args: any[]): QueryResult;
|
103
|
-
arrowIPCStream(sql: any, ...args: any[]): IpcResultStreamIterator
|
103
|
+
arrowIPCStream(sql: any, ...args: any[]): Promise<IpcResultStreamIterator>;
|
104
104
|
|
105
105
|
register_buffer(name: string, array: ArrowIterable, force: boolean, callback?: Callback<void>): void;
|
106
106
|
unregister_buffer(name: string, callback?: Callback<void>): void;
|
package/lib/duckdb.js
CHANGED
@@ -189,7 +189,7 @@ Connection.prototype.arrowIPCAll = function (sql) {
|
|
189
189
|
* @arg sql
|
190
190
|
* @param {...*} params
|
191
191
|
* @param callback
|
192
|
-
* @return IpcResultStreamIterator
|
192
|
+
* @return Promise<IpcResultStreamIterator>
|
193
193
|
*/
|
194
194
|
Connection.prototype.arrowIPCStream = async function (sql) {
|
195
195
|
const query = "SELECT * FROM to_arrow_ipc((" + sql + "));";
|
package/package.json
CHANGED
@@ -96,7 +96,7 @@ static unique_ptr<FunctionData> StructExtractBind(ClientContext &context, Scalar
|
|
96
96
|
}
|
97
97
|
|
98
98
|
bound_function.return_type = return_type;
|
99
|
-
return make_unique<StructExtractBindData>(key, key_index, return_type);
|
99
|
+
return make_unique<StructExtractBindData>(std::move(key), key_index, std::move(return_type));
|
100
100
|
}
|
101
101
|
|
102
102
|
static unique_ptr<BaseStatistics> PropagateStructExtractStats(ClientContext &context, FunctionStatisticsInput &input) {
|
@@ -1,8 +1,8 @@
|
|
1
1
|
#ifndef DUCKDB_VERSION
|
2
|
-
#define DUCKDB_VERSION "0.7.2-
|
2
|
+
#define DUCKDB_VERSION "0.7.2-dev904"
|
3
3
|
#endif
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
5
|
+
#define DUCKDB_SOURCE_ID "56a94e3a49"
|
6
6
|
#endif
|
7
7
|
#include "duckdb/function/table/system_functions.hpp"
|
8
8
|
#include "duckdb/main/database.hpp"
|
@@ -30,8 +30,10 @@ struct PivotColumnEntry {
|
|
30
30
|
};
|
31
31
|
|
32
32
|
struct PivotColumn {
|
33
|
-
//! The
|
34
|
-
vector<
|
33
|
+
//! The set of expressions to pivot on
|
34
|
+
vector<unique_ptr<ParsedExpression>> pivot_expressions;
|
35
|
+
//! The set of unpivot names
|
36
|
+
vector<string> unpivot_names;
|
35
37
|
//! The set of values to pivot on
|
36
38
|
vector<PivotColumnEntry> entries;
|
37
39
|
//! The enum to read pivot values from (if any)
|
@@ -42,7 +42,7 @@ class Transformer {
|
|
42
42
|
struct CreatePivotEntry {
|
43
43
|
string enum_name;
|
44
44
|
unique_ptr<SelectNode> base;
|
45
|
-
|
45
|
+
unique_ptr<ParsedExpression> column;
|
46
46
|
};
|
47
47
|
|
48
48
|
public:
|
@@ -108,7 +108,7 @@ private:
|
|
108
108
|
return parent ? parent->HasNamedParameters() : !named_param_map.empty();
|
109
109
|
}
|
110
110
|
|
111
|
-
void AddPivotEntry(string enum_name, unique_ptr<SelectNode> source,
|
111
|
+
void AddPivotEntry(string enum_name, unique_ptr<SelectNode> source, unique_ptr<ParsedExpression> column);
|
112
112
|
unique_ptr<SQLStatement> GenerateCreateEnumStmt(unique_ptr<CreatePivotEntry> entry);
|
113
113
|
bool HasPivotEntries();
|
114
114
|
idx_t PivotEntryCount();
|
@@ -73,7 +73,6 @@ struct CorrelatedColumnInfo {
|
|
73
73
|
*/
|
74
74
|
class Binder : public std::enable_shared_from_this<Binder> {
|
75
75
|
friend class ExpressionBinder;
|
76
|
-
friend class SelectBinder;
|
77
76
|
friend class RecursiveSubqueryPlanner;
|
78
77
|
|
79
78
|
public:
|
@@ -185,6 +184,9 @@ public:
|
|
185
184
|
BindingMode GetBindingMode();
|
186
185
|
void AddTableName(string table_name);
|
187
186
|
const unordered_set<string> &GetTableNames();
|
187
|
+
SQLStatement *GetRootStatement() {
|
188
|
+
return root_statement;
|
189
|
+
}
|
188
190
|
|
189
191
|
void SetCanContainNulls(bool can_contain_nulls);
|
190
192
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
//===----------------------------------------------------------------------===//
|
2
|
+
// DuckDB
|
3
|
+
//
|
4
|
+
// duckdb/planner/expression_binder/base_select_binder.hpp
|
5
|
+
//
|
6
|
+
//
|
7
|
+
//===----------------------------------------------------------------------===//
|
8
|
+
|
9
|
+
#pragma once
|
10
|
+
|
11
|
+
#include "duckdb/common/case_insensitive_map.hpp"
|
12
|
+
#include "duckdb/parser/expression_map.hpp"
|
13
|
+
#include "duckdb/planner/expression_binder.hpp"
|
14
|
+
|
15
|
+
namespace duckdb {
|
16
|
+
class BoundColumnRefExpression;
|
17
|
+
class WindowExpression;
|
18
|
+
|
19
|
+
class BoundSelectNode;
|
20
|
+
|
21
|
+
struct BoundGroupInformation {
|
22
|
+
expression_map_t<idx_t> map;
|
23
|
+
case_insensitive_map_t<idx_t> alias_map;
|
24
|
+
};
|
25
|
+
|
26
|
+
//! The BaseSelectBinder is the base binder of the SELECT, HAVING and QUALIFY binders. It can bind aggregates and window
|
27
|
+
//! functions.
|
28
|
+
class BaseSelectBinder : public ExpressionBinder {
|
29
|
+
public:
|
30
|
+
BaseSelectBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info,
|
31
|
+
case_insensitive_map_t<idx_t> alias_map);
|
32
|
+
BaseSelectBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info);
|
33
|
+
|
34
|
+
bool BoundAggregates() {
|
35
|
+
return bound_aggregate;
|
36
|
+
}
|
37
|
+
void ResetBindings() {
|
38
|
+
this->bound_aggregate = false;
|
39
|
+
this->bound_columns.clear();
|
40
|
+
}
|
41
|
+
|
42
|
+
protected:
|
43
|
+
BindResult BindExpression(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth,
|
44
|
+
bool root_expression = false) override;
|
45
|
+
|
46
|
+
BindResult BindAggregate(FunctionExpression &expr, AggregateFunctionCatalogEntry *function, idx_t depth) override;
|
47
|
+
|
48
|
+
bool inside_window;
|
49
|
+
bool bound_aggregate = false;
|
50
|
+
|
51
|
+
BoundSelectNode &node;
|
52
|
+
BoundGroupInformation &info;
|
53
|
+
case_insensitive_map_t<idx_t> alias_map;
|
54
|
+
|
55
|
+
protected:
|
56
|
+
BindResult BindColumnRef(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth);
|
57
|
+
BindResult BindGroupingFunction(OperatorExpression &op, idx_t depth) override;
|
58
|
+
BindResult BindWindow(WindowExpression &expr, idx_t depth);
|
59
|
+
|
60
|
+
idx_t TryBindGroup(ParsedExpression &expr, idx_t depth);
|
61
|
+
BindResult BindGroup(ParsedExpression &expr, idx_t depth, idx_t group_index);
|
62
|
+
};
|
63
|
+
|
64
|
+
} // namespace duckdb
|
@@ -8,14 +8,14 @@
|
|
8
8
|
|
9
9
|
#pragma once
|
10
10
|
|
11
|
-
#include "duckdb/planner/expression_binder/
|
11
|
+
#include "duckdb/planner/expression_binder/base_select_binder.hpp"
|
12
12
|
#include "duckdb/planner/expression_binder/column_alias_binder.hpp"
|
13
13
|
#include "duckdb/common/enums/aggregate_handling.hpp"
|
14
14
|
|
15
15
|
namespace duckdb {
|
16
16
|
|
17
17
|
//! The HAVING binder is responsible for binding an expression within the HAVING clause of a SQL statement
|
18
|
-
class HavingBinder : public
|
18
|
+
class HavingBinder : public BaseSelectBinder {
|
19
19
|
public:
|
20
20
|
HavingBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info,
|
21
21
|
case_insensitive_map_t<idx_t> &alias_map, AggregateHandling aggregate_handling);
|
@@ -8,13 +8,13 @@
|
|
8
8
|
|
9
9
|
#pragma once
|
10
10
|
|
11
|
-
#include "duckdb/planner/expression_binder/
|
11
|
+
#include "duckdb/planner/expression_binder/base_select_binder.hpp"
|
12
12
|
#include "duckdb/planner/expression_binder/column_alias_binder.hpp"
|
13
13
|
|
14
14
|
namespace duckdb {
|
15
15
|
|
16
16
|
//! The QUALIFY binder is responsible for binding an expression within the QUALIFY clause of a SQL statement
|
17
|
-
class QualifyBinder : public
|
17
|
+
class QualifyBinder : public BaseSelectBinder {
|
18
18
|
public:
|
19
19
|
QualifyBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info,
|
20
20
|
case_insensitive_map_t<idx_t> &alias_map);
|
@@ -8,58 +8,29 @@
|
|
8
8
|
|
9
9
|
#pragma once
|
10
10
|
|
11
|
-
#include "duckdb/
|
12
|
-
#include "duckdb/parser/expression_map.hpp"
|
13
|
-
#include "duckdb/planner/expression_binder.hpp"
|
11
|
+
#include "duckdb/planner/expression_binder/base_select_binder.hpp"
|
14
12
|
|
15
13
|
namespace duckdb {
|
16
|
-
class BoundColumnRefExpression;
|
17
|
-
class WindowExpression;
|
18
|
-
|
19
|
-
class BoundSelectNode;
|
20
|
-
|
21
|
-
struct BoundGroupInformation {
|
22
|
-
expression_map_t<idx_t> map;
|
23
|
-
case_insensitive_map_t<idx_t> alias_map;
|
24
|
-
};
|
25
14
|
|
26
15
|
//! The SELECT binder is responsible for binding an expression within the SELECT clause of a SQL statement
|
27
|
-
class SelectBinder : public
|
16
|
+
class SelectBinder : public BaseSelectBinder {
|
28
17
|
public:
|
29
18
|
SelectBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info,
|
30
19
|
case_insensitive_map_t<idx_t> alias_map);
|
31
20
|
SelectBinder(Binder &binder, ClientContext &context, BoundSelectNode &node, BoundGroupInformation &info);
|
32
21
|
|
33
|
-
bool
|
34
|
-
return
|
22
|
+
bool HasExpandedExpressions() {
|
23
|
+
return !expanded_expressions.empty();
|
35
24
|
}
|
36
|
-
|
37
|
-
|
38
|
-
this->bound_columns.clear();
|
25
|
+
vector<unique_ptr<Expression>> &ExpandedExpressions() {
|
26
|
+
return expanded_expressions;
|
39
27
|
}
|
40
28
|
|
41
29
|
protected:
|
42
|
-
BindResult
|
43
|
-
bool root_expression = false) override;
|
44
|
-
|
45
|
-
BindResult BindAggregate(FunctionExpression &expr, AggregateFunctionCatalogEntry *function, idx_t depth) override;
|
46
|
-
|
47
|
-
BindResult BindUnnest(FunctionExpression &function, idx_t depth) override;
|
48
|
-
|
49
|
-
bool inside_window;
|
50
|
-
bool bound_aggregate = false;
|
51
|
-
|
52
|
-
BoundSelectNode &node;
|
53
|
-
BoundGroupInformation &info;
|
54
|
-
case_insensitive_map_t<idx_t> alias_map;
|
55
|
-
|
56
|
-
protected:
|
57
|
-
BindResult BindColumnRef(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth);
|
58
|
-
BindResult BindGroupingFunction(OperatorExpression &op, idx_t depth) override;
|
59
|
-
BindResult BindWindow(WindowExpression &expr, idx_t depth);
|
30
|
+
BindResult BindUnnest(FunctionExpression &function, idx_t depth, bool root_expression) override;
|
60
31
|
|
61
|
-
idx_t
|
62
|
-
|
32
|
+
idx_t unnest_level = 0;
|
33
|
+
vector<unique_ptr<Expression>> expanded_expressions;
|
63
34
|
};
|
64
35
|
|
65
36
|
} // namespace duckdb
|
@@ -135,7 +135,7 @@ protected:
|
|
135
135
|
virtual BindResult BindFunction(FunctionExpression &expr, ScalarFunctionCatalogEntry *function, idx_t depth);
|
136
136
|
virtual BindResult BindLambdaFunction(FunctionExpression &expr, ScalarFunctionCatalogEntry *function, idx_t depth);
|
137
137
|
virtual BindResult BindAggregate(FunctionExpression &expr, AggregateFunctionCatalogEntry *function, idx_t depth);
|
138
|
-
virtual BindResult BindUnnest(FunctionExpression &expr, idx_t depth);
|
138
|
+
virtual BindResult BindUnnest(FunctionExpression &expr, idx_t depth, bool root_expression);
|
139
139
|
virtual BindResult BindMacro(FunctionExpression &expr, ScalarMacroCatalogEntry *macro, idx_t depth,
|
140
140
|
unique_ptr<ParsedExpression> *expr_ptr);
|
141
141
|
|
@@ -25,6 +25,13 @@ public:
|
|
25
25
|
vector<GroupingSet> grouping_sets;
|
26
26
|
};
|
27
27
|
|
28
|
+
struct BoundUnnestNode {
|
29
|
+
//! The index of the UNNEST node
|
30
|
+
idx_t index;
|
31
|
+
//! The set of expressions
|
32
|
+
vector<unique_ptr<Expression>> expressions;
|
33
|
+
};
|
34
|
+
|
28
35
|
//! Bound equivalent of SelectNode
|
29
36
|
class BoundSelectNode : public BoundQueryNode {
|
30
37
|
public:
|
@@ -78,9 +85,8 @@ public:
|
|
78
85
|
//! Window functions to compute (only used if HasWindow is true)
|
79
86
|
vector<unique_ptr<Expression>> windows;
|
80
87
|
|
81
|
-
idx_t unnest_index;
|
82
88
|
//! Unnest expression
|
83
|
-
|
89
|
+
unordered_map<idx_t, BoundUnnestNode> unnests;
|
84
90
|
|
85
91
|
//! Index of pruned node
|
86
92
|
idx_t prune_index;
|
@@ -12,15 +12,29 @@ namespace duckdb {
|
|
12
12
|
//===--------------------------------------------------------------------===//
|
13
13
|
string PivotColumn::ToString() const {
|
14
14
|
string result;
|
15
|
-
if (
|
16
|
-
|
17
|
-
|
15
|
+
if (!unpivot_names.empty()) {
|
16
|
+
D_ASSERT(pivot_expressions.empty());
|
17
|
+
// unpivot
|
18
|
+
if (unpivot_names.size() == 1) {
|
19
|
+
result += KeywordHelper::WriteOptionallyQuoted(unpivot_names[0]);
|
20
|
+
} else {
|
21
|
+
result += "(";
|
22
|
+
for (idx_t n = 0; n < unpivot_names.size(); n++) {
|
23
|
+
if (n > 0) {
|
24
|
+
result += ", ";
|
25
|
+
}
|
26
|
+
result += KeywordHelper::WriteOptionallyQuoted(unpivot_names[n]);
|
27
|
+
}
|
28
|
+
result += ")";
|
29
|
+
}
|
30
|
+
} else if (!pivot_expressions.empty()) {
|
31
|
+
// pivot
|
18
32
|
result += "(";
|
19
|
-
for (idx_t n = 0; n <
|
33
|
+
for (idx_t n = 0; n < pivot_expressions.size(); n++) {
|
20
34
|
if (n > 0) {
|
21
35
|
result += ", ";
|
22
36
|
}
|
23
|
-
result +=
|
37
|
+
result += pivot_expressions[n]->ToString();
|
24
38
|
}
|
25
39
|
result += ")";
|
26
40
|
}
|
@@ -74,7 +88,10 @@ bool PivotColumnEntry::Equals(const PivotColumnEntry &other) const {
|
|
74
88
|
}
|
75
89
|
|
76
90
|
bool PivotColumn::Equals(const PivotColumn &other) const {
|
77
|
-
if (other.
|
91
|
+
if (!ExpressionUtil::ListEquals(pivot_expressions, other.pivot_expressions)) {
|
92
|
+
return false;
|
93
|
+
}
|
94
|
+
if (other.unpivot_names != unpivot_names) {
|
78
95
|
return false;
|
79
96
|
}
|
80
97
|
if (other.pivot_enum != pivot_enum) {
|
@@ -93,7 +110,10 @@ bool PivotColumn::Equals(const PivotColumn &other) const {
|
|
93
110
|
|
94
111
|
PivotColumn PivotColumn::Copy() const {
|
95
112
|
PivotColumn result;
|
96
|
-
|
113
|
+
for (auto &expr : pivot_expressions) {
|
114
|
+
result.pivot_expressions.push_back(expr->Copy());
|
115
|
+
}
|
116
|
+
result.unpivot_names = unpivot_names;
|
97
117
|
for (auto &entry : entries) {
|
98
118
|
result.entries.push_back(entry.Copy());
|
99
119
|
}
|
@@ -103,14 +123,16 @@ PivotColumn PivotColumn::Copy() const {
|
|
103
123
|
|
104
124
|
void PivotColumn::Serialize(Serializer &serializer) const {
|
105
125
|
FieldWriter writer(serializer);
|
106
|
-
writer.
|
126
|
+
writer.WriteSerializableList(pivot_expressions);
|
127
|
+
writer.WriteList<string>(unpivot_names);
|
107
128
|
writer.WriteRegularSerializableList(entries);
|
108
129
|
writer.WriteString(pivot_enum);
|
109
130
|
writer.Finalize();
|
110
131
|
}
|
111
132
|
|
112
133
|
void PivotColumn::FormatSerialize(FormatSerializer &serializer) const {
|
113
|
-
serializer.WriteProperty("
|
134
|
+
serializer.WriteProperty("pivot_expressions", pivot_expressions);
|
135
|
+
serializer.WriteProperty("unpivot_names", unpivot_names);
|
114
136
|
serializer.WriteProperty("entries", entries);
|
115
137
|
serializer.WriteProperty("pivot_enum", pivot_enum);
|
116
138
|
}
|
@@ -118,7 +140,8 @@ void PivotColumn::FormatSerialize(FormatSerializer &serializer) const {
|
|
118
140
|
PivotColumn PivotColumn::Deserialize(Deserializer &source) {
|
119
141
|
PivotColumn result;
|
120
142
|
FieldReader reader(source);
|
121
|
-
result.
|
143
|
+
result.pivot_expressions = reader.ReadRequiredSerializableList<ParsedExpression>();
|
144
|
+
result.unpivot_names = reader.ReadRequiredList<string>();
|
122
145
|
result.entries = reader.ReadRequiredSerializableList<PivotColumnEntry, PivotColumnEntry>();
|
123
146
|
result.pivot_enum = reader.ReadRequired<string>();
|
124
147
|
reader.Finalize();
|
@@ -127,7 +150,8 @@ PivotColumn PivotColumn::Deserialize(Deserializer &source) {
|
|
127
150
|
|
128
151
|
PivotColumn PivotColumn::FormatDeserialize(FormatDeserializer &source) {
|
129
152
|
PivotColumn result;
|
130
|
-
source.ReadProperty("
|
153
|
+
source.ReadProperty("pivot_expressions", result.pivot_expressions);
|
154
|
+
source.ReadProperty("unpivot_names", result.unpivot_names);
|
131
155
|
source.ReadProperty("entries", result.entries);
|
132
156
|
source.ReadProperty("pivot_enum", result.pivot_enum);
|
133
157
|
return result;
|
@@ -10,21 +10,22 @@
|
|
10
10
|
#include "duckdb/parser/statement/drop_statement.hpp"
|
11
11
|
#include "duckdb/parser/parsed_data/drop_info.hpp"
|
12
12
|
#include "duckdb/parser/expression/cast_expression.hpp"
|
13
|
+
#include "duckdb/parser/expression/operator_expression.hpp"
|
13
14
|
#include "duckdb/parser/expression/function_expression.hpp"
|
14
15
|
#include "duckdb/parser/result_modifier.hpp"
|
15
16
|
#include "duckdb/parser/tableref/subqueryref.hpp"
|
16
17
|
|
17
18
|
namespace duckdb {
|
18
19
|
|
19
|
-
void Transformer::AddPivotEntry(string enum_name, unique_ptr<SelectNode> base,
|
20
|
+
void Transformer::AddPivotEntry(string enum_name, unique_ptr<SelectNode> base, unique_ptr<ParsedExpression> column) {
|
20
21
|
if (parent) {
|
21
|
-
parent->AddPivotEntry(std::move(enum_name), std::move(base), std::move(
|
22
|
+
parent->AddPivotEntry(std::move(enum_name), std::move(base), std::move(column));
|
22
23
|
return;
|
23
24
|
}
|
24
25
|
auto result = make_unique<CreatePivotEntry>();
|
25
26
|
result->enum_name = std::move(enum_name);
|
26
27
|
result->base = std::move(base);
|
27
|
-
result->
|
28
|
+
result->column = std::move(column);
|
28
29
|
|
29
30
|
pivot_entries.push_back(std::move(result));
|
30
31
|
}
|
@@ -56,10 +57,13 @@ unique_ptr<SQLStatement> Transformer::GenerateCreateEnumStmt(unique_ptr<CreatePi
|
|
56
57
|
|
57
58
|
// generate the query that will result in the enum creation
|
58
59
|
auto select_node = std::move(entry->base);
|
59
|
-
auto columnref =
|
60
|
+
auto columnref = entry->column->Copy();
|
60
61
|
auto cast = make_unique<CastExpression>(LogicalType::VARCHAR, columnref->Copy());
|
61
62
|
select_node->select_list.push_back(std::move(cast));
|
62
63
|
|
64
|
+
auto is_not_null = make_unique<OperatorExpression>(ExpressionType::OPERATOR_IS_NOT_NULL, std::move(entry->column));
|
65
|
+
select_node->where_clause = std::move(is_not_null);
|
66
|
+
|
63
67
|
// order by the column
|
64
68
|
auto modifier = make_unique<OrderModifier>();
|
65
69
|
modifier->orders.emplace_back(OrderType::ASCENDING, OrderByNullType::ORDER_DEFAULT, std::move(columnref));
|
@@ -135,7 +139,7 @@ unique_ptr<QueryNode> Transformer::TransformPivotStatement(duckdb_libpgquery::PG
|
|
135
139
|
if (!col.pivot_enum.empty() || !col.entries.empty()) {
|
136
140
|
continue;
|
137
141
|
}
|
138
|
-
if (col.
|
142
|
+
if (col.pivot_expressions.size() != 1) {
|
139
143
|
throw InternalException("PIVOT statement with multiple names in pivot entry!?");
|
140
144
|
}
|
141
145
|
auto enum_name = "__pivot_enum_" + std::to_string(pivot_idx) + "_" + std::to_string(c);
|
@@ -143,7 +147,7 @@ unique_ptr<QueryNode> Transformer::TransformPivotStatement(duckdb_libpgquery::PG
|
|
143
147
|
auto new_select = make_unique<SelectNode>();
|
144
148
|
ExtractCTEsRecursive(new_select->cte_map);
|
145
149
|
new_select->from_table = source->Copy();
|
146
|
-
AddPivotEntry(enum_name, std::move(new_select), col.
|
150
|
+
AddPivotEntry(enum_name, std::move(new_select), col.pivot_expressions[0]->Copy());
|
147
151
|
col.pivot_enum = enum_name;
|
148
152
|
}
|
149
153
|
|
@@ -34,7 +34,21 @@ static void TransformPivotInList(unique_ptr<ParsedExpression> &expr, PivotColumn
|
|
34
34
|
|
35
35
|
PivotColumn Transformer::TransformPivotColumn(duckdb_libpgquery::PGPivot *pivot) {
|
36
36
|
PivotColumn col;
|
37
|
-
|
37
|
+
if (pivot->pivot_columns) {
|
38
|
+
TransformExpressionList(*pivot->pivot_columns, col.pivot_expressions);
|
39
|
+
for (auto &expr : col.pivot_expressions) {
|
40
|
+
if (expr->IsScalar()) {
|
41
|
+
throw ParserException("Cannot pivot on constant value \"%s\"", expr->ToString());
|
42
|
+
}
|
43
|
+
if (expr->HasSubquery()) {
|
44
|
+
throw ParserException("Cannot pivot on subquery \"%s\"", expr->ToString());
|
45
|
+
}
|
46
|
+
}
|
47
|
+
} else if (pivot->unpivot_columns) {
|
48
|
+
col.unpivot_names = TransformStringList(pivot->unpivot_columns);
|
49
|
+
} else {
|
50
|
+
throw InternalException("Either pivot_columns or unpivot_columns must be defined");
|
51
|
+
}
|
38
52
|
if (pivot->pivot_value) {
|
39
53
|
for (auto node = pivot->pivot_value->head; node != nullptr; node = node->next) {
|
40
54
|
auto n = (duckdb_libpgquery::PGNode *)node->data.ptr_value;
|
@@ -78,13 +92,15 @@ unique_ptr<TableRef> Transformer::TransformPivot(duckdb_libpgquery::PGPivotExpr
|
|
78
92
|
bool is_pivot = result->unpivot_names.empty();
|
79
93
|
if (!result->unpivot_names.empty()) {
|
80
94
|
// unpivot
|
81
|
-
if (pivot.
|
95
|
+
if (pivot.unpivot_names.size() != 1) {
|
82
96
|
throw ParserException("UNPIVOT requires a single column name for the PIVOT IN clause");
|
83
97
|
}
|
98
|
+
D_ASSERT(pivot.pivot_expressions.empty());
|
84
99
|
expected_size = pivot.entries[0].values.size();
|
85
100
|
} else {
|
86
101
|
// pivot
|
87
|
-
expected_size = pivot.
|
102
|
+
expected_size = pivot.pivot_expressions.size();
|
103
|
+
D_ASSERT(pivot.unpivot_names.empty());
|
88
104
|
}
|
89
105
|
for (auto &entry : pivot.entries) {
|
90
106
|
if (entry.star_expr && is_pivot) {
|
@@ -7,7 +7,7 @@
|
|
7
7
|
#include "duckdb/planner/expression/bound_columnref_expression.hpp"
|
8
8
|
#include "duckdb/planner/expression/bound_constant_expression.hpp"
|
9
9
|
#include "duckdb/planner/expression_binder/aggregate_binder.hpp"
|
10
|
-
#include "duckdb/planner/expression_binder/
|
10
|
+
#include "duckdb/planner/expression_binder/base_select_binder.hpp"
|
11
11
|
#include "duckdb/planner/query_node/bound_select_node.hpp"
|
12
12
|
#include "duckdb/execution/expression_executor.hpp"
|
13
13
|
#include "duckdb/function/scalar/generic_functions.hpp"
|
@@ -81,7 +81,7 @@ static void NegatePercentileFractions(ClientContext &context, unique_ptr<ParsedE
|
|
81
81
|
}
|
82
82
|
}
|
83
83
|
|
84
|
-
BindResult
|
84
|
+
BindResult BaseSelectBinder::BindAggregate(FunctionExpression &aggr, AggregateFunctionCatalogEntry *func, idx_t depth) {
|
85
85
|
// first bind the child of the aggregate expression (if any)
|
86
86
|
this->bound_aggregate = true;
|
87
87
|
unique_ptr<Expression> bound_filter;
|
@@ -18,13 +18,6 @@ BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t
|
|
18
18
|
unique_ptr<ParsedExpression> *expr_ptr) {
|
19
19
|
// lookup the function in the catalog
|
20
20
|
QueryErrorContext error_context(binder.root_statement, function.query_location);
|
21
|
-
|
22
|
-
if (function.function_name == "unnest" || function.function_name == "unlist") {
|
23
|
-
// special case, not in catalog
|
24
|
-
// TODO make sure someone does not create such a function OR
|
25
|
-
// have unnest live in catalog, too
|
26
|
-
return BindUnnest(function, depth);
|
27
|
-
}
|
28
21
|
auto func = Catalog::GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, function.catalog, function.schema,
|
29
22
|
function.function_name, true, error_context);
|
30
23
|
if (!func) {
|
@@ -246,7 +239,7 @@ BindResult ExpressionBinder::BindAggregate(FunctionExpression &expr, AggregateFu
|
|
246
239
|
return BindResult(binder.FormatError(expr, UnsupportedAggregateMessage()));
|
247
240
|
}
|
248
241
|
|
249
|
-
BindResult ExpressionBinder::BindUnnest(FunctionExpression &expr, idx_t depth) {
|
242
|
+
BindResult ExpressionBinder::BindUnnest(FunctionExpression &expr, idx_t depth, bool root_expression) {
|
250
243
|
return BindResult(binder.FormatError(expr, UnsupportedUnnestMessage()));
|
251
244
|
}
|
252
245
|
|