duckdb 0.7.2-dev14.0 → 0.7.2-dev225.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/binding.gyp +2 -0
- package/package.json +1 -1
- package/src/duckdb/extension/icu/icu-extension.cpp +2 -0
- package/src/duckdb/extension/icu/icu-table-range.cpp +194 -0
- package/src/duckdb/extension/icu/include/icu-table-range.hpp +17 -0
- package/src/duckdb/extension/parquet/column_writer.cpp +0 -1
- package/src/duckdb/extension/parquet/parquet-extension.cpp +11 -2
- package/src/duckdb/src/catalog/catalog_entry/duck_schema_entry.cpp +4 -0
- package/src/duckdb/src/catalog/catalog_entry/scalar_function_catalog_entry.cpp +7 -6
- package/src/duckdb/src/catalog/catalog_entry/table_function_catalog_entry.cpp +20 -1
- package/src/duckdb/src/common/enums/statement_type.cpp +2 -0
- package/src/duckdb/src/common/types/bit.cpp +95 -58
- package/src/duckdb/src/common/types/value.cpp +149 -53
- package/src/duckdb/src/common/types/vector.cpp +13 -10
- package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +1 -1
- package/src/duckdb/src/function/aggregate/algebraic/avg.cpp +0 -6
- package/src/duckdb/src/function/aggregate/distributive/bitagg.cpp +99 -95
- package/src/duckdb/src/function/aggregate/distributive/bitstring_agg.cpp +261 -0
- package/src/duckdb/src/function/aggregate/distributive/sum.cpp +0 -3
- package/src/duckdb/src/function/aggregate/distributive_functions.cpp +1 -0
- package/src/duckdb/src/function/aggregate/sorted_aggregate_function.cpp +16 -5
- package/src/duckdb/src/function/cast/bit_cast.cpp +0 -2
- package/src/duckdb/src/function/cast/blob_cast.cpp +0 -1
- package/src/duckdb/src/function/scalar/bit/bitstring.cpp +99 -0
- package/src/duckdb/src/function/scalar/map/map_entries.cpp +61 -0
- package/src/duckdb/src/function/scalar/map/map_keys_values.cpp +97 -0
- package/src/duckdb/src/function/scalar/nested_functions.cpp +3 -0
- package/src/duckdb/src/function/scalar/operators/add.cpp +0 -9
- package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +2 -14
- package/src/duckdb/src/function/scalar/operators/bitwise.cpp +0 -63
- package/src/duckdb/src/function/scalar/operators/multiply.cpp +0 -6
- package/src/duckdb/src/function/scalar/operators/subtract.cpp +0 -6
- package/src/duckdb/src/function/scalar/string_functions.cpp +1 -0
- package/src/duckdb/src/function/table/read_csv.cpp +9 -0
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/function/table_function.cpp +19 -0
- package/src/duckdb/src/include/duckdb/catalog/catalog_entry/table_function_catalog_entry.hpp +6 -8
- package/src/duckdb/src/include/duckdb/common/constants.hpp +0 -19
- package/src/duckdb/src/include/duckdb/common/enums/statement_type.hpp +2 -1
- package/src/duckdb/src/include/duckdb/common/enums/tableref_type.hpp +2 -1
- package/src/duckdb/src/include/duckdb/common/types/bit.hpp +5 -1
- package/src/duckdb/src/include/duckdb/common/types/value.hpp +2 -8
- package/src/duckdb/src/include/duckdb/common/types.hpp +1 -2
- package/src/duckdb/src/include/duckdb/function/aggregate/distributive_functions.hpp +5 -0
- package/src/duckdb/src/include/duckdb/function/scalar/bit_functions.hpp +4 -0
- package/src/duckdb/src/include/duckdb/function/scalar/nested_functions.hpp +12 -0
- package/src/duckdb/src/include/duckdb/function/table_function.hpp +2 -0
- package/src/duckdb/src/include/duckdb/main/capi/capi_internal.hpp +2 -0
- package/src/duckdb/src/include/duckdb/main/config.hpp +3 -0
- package/src/duckdb/src/include/duckdb/main/database.hpp +1 -0
- package/src/duckdb/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp +2 -2
- package/src/duckdb/src/include/duckdb/parser/common_table_expression_info.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_info.hpp +2 -1
- package/src/duckdb/src/include/duckdb/parser/parsed_data/{alter_function_info.hpp → alter_scalar_function_info.hpp} +13 -13
- package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_table_function_info.hpp +47 -0
- package/src/duckdb/src/include/duckdb/parser/parsed_data/create_table_function_info.hpp +2 -1
- package/src/duckdb/src/include/duckdb/parser/query_node.hpp +2 -1
- package/src/duckdb/src/include/duckdb/parser/statement/multi_statement.hpp +28 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/list.hpp +1 -0
- package/src/duckdb/src/include/duckdb/parser/tableref/pivotref.hpp +76 -0
- package/src/duckdb/src/include/duckdb/parser/tokens.hpp +2 -0
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +28 -0
- package/src/duckdb/src/include/duckdb/planner/binder.hpp +8 -0
- package/src/duckdb/src/include/duckdb/storage/buffer/block_handle.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +76 -44
- package/src/duckdb/src/include/duckdb/storage/statistics/base_statistics.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/statistics/node_statistics.hpp +26 -0
- package/src/duckdb/src/include/duckdb/storage/table/list_column_data.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/table/scan_state.hpp +2 -0
- package/src/duckdb/src/include/duckdb.h +49 -1
- package/src/duckdb/src/include/duckdb.hpp +0 -1
- package/src/duckdb/src/main/capi/pending-c.cpp +16 -3
- package/src/duckdb/src/main/capi/result-c.cpp +27 -1
- package/src/duckdb/src/main/capi/stream-c.cpp +25 -0
- package/src/duckdb/src/main/client_context.cpp +8 -1
- package/src/duckdb/src/main/database.cpp +10 -2
- package/src/duckdb/src/optimizer/join_order/cardinality_estimator.cpp +98 -66
- package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +16 -3
- package/src/duckdb/src/parser/parsed_data/alter_info.cpp +7 -3
- package/src/duckdb/src/parser/parsed_data/alter_scalar_function_info.cpp +56 -0
- package/src/duckdb/src/parser/parsed_data/alter_table_function_info.cpp +51 -0
- package/src/duckdb/src/parser/parsed_data/create_scalar_function_info.cpp +3 -2
- package/src/duckdb/src/parser/parsed_data/create_table_function_info.cpp +6 -0
- package/src/duckdb/src/parser/parsed_expression_iterator.cpp +8 -0
- package/src/duckdb/src/parser/query_node.cpp +1 -1
- package/src/duckdb/src/parser/statement/multi_statement.cpp +18 -0
- package/src/duckdb/src/parser/tableref/pivotref.cpp +296 -0
- package/src/duckdb/src/parser/tableref.cpp +3 -0
- package/src/duckdb/src/parser/transform/helpers/transform_alias.cpp +12 -6
- package/src/duckdb/src/parser/transform/helpers/transform_cte.cpp +24 -0
- package/src/duckdb/src/parser/transform/statement/transform_create_function.cpp +4 -0
- package/src/duckdb/src/parser/transform/statement/transform_create_view.cpp +4 -0
- package/src/duckdb/src/parser/transform/statement/transform_pivot_stmt.cpp +150 -0
- package/src/duckdb/src/parser/transform/statement/transform_select.cpp +8 -0
- package/src/duckdb/src/parser/transform/statement/transform_select_node.cpp +1 -1
- package/src/duckdb/src/parser/transform/tableref/transform_pivot.cpp +105 -0
- package/src/duckdb/src/parser/transform/tableref/transform_tableref.cpp +2 -0
- package/src/duckdb/src/parser/transformer.cpp +15 -3
- package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +11 -3
- package/src/duckdb/src/planner/binder/statement/bind_create.cpp +1 -1
- package/src/duckdb/src/planner/binder/statement/bind_logical_plan.cpp +17 -0
- package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +365 -0
- package/src/duckdb/src/planner/binder.cpp +5 -0
- package/src/duckdb/src/planner/pragma_handler.cpp +10 -2
- package/src/duckdb/src/storage/buffer_manager.cpp +44 -46
- package/src/duckdb/src/storage/compression/bitpacking.cpp +25 -21
- package/src/duckdb/src/storage/compression/fixed_size_uncompressed.cpp +41 -43
- package/src/duckdb/src/storage/compression/rle.cpp +17 -13
- package/src/duckdb/src/storage/statistics/base_statistics.cpp +3 -3
- package/src/duckdb/src/storage/storage_info.cpp +1 -1
- package/src/duckdb/src/storage/table/column_data.cpp +5 -2
- package/src/duckdb/src/storage/table/list_column_data.cpp +32 -47
- package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +3 -0
- package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +34 -1
- package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +1016 -530
- package/src/duckdb/third_party/libpg_query/include/parser/kwlist.hpp +5 -0
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +22697 -21987
- package/src/duckdb/ub_src_function_aggregate_distributive.cpp +2 -0
- package/src/duckdb/ub_src_function_scalar_bit.cpp +2 -0
- package/src/duckdb/ub_src_function_scalar_map.cpp +4 -0
- package/src/duckdb/ub_src_main_capi.cpp +2 -0
- package/src/duckdb/ub_src_parser_parsed_data.cpp +4 -2
- package/src/duckdb/ub_src_parser_statement.cpp +2 -0
- package/src/duckdb/ub_src_parser_tableref.cpp +2 -0
- package/src/duckdb/ub_src_parser_transform_statement.cpp +2 -0
- package/src/duckdb/ub_src_parser_transform_tableref.cpp +2 -0
- package/src/duckdb/ub_src_planner_binder_tableref.cpp +2 -0
- package/src/duckdb/src/include/duckdb/main/loadable_extension.hpp +0 -59
- package/src/duckdb/src/parser/parsed_data/alter_function_info.cpp +0 -55
@@ -0,0 +1,296 @@
|
|
1
|
+
#include "duckdb/parser/tableref/pivotref.hpp"
|
2
|
+
|
3
|
+
#include "duckdb/common/limits.hpp"
|
4
|
+
#include "duckdb/common/field_writer.hpp"
|
5
|
+
|
6
|
+
namespace duckdb {
|
7
|
+
|
8
|
+
//===--------------------------------------------------------------------===//
|
9
|
+
// PivotColumn
|
10
|
+
//===--------------------------------------------------------------------===//
|
11
|
+
string PivotColumn::ToString() const {
|
12
|
+
string result;
|
13
|
+
if (names.size() == 1) {
|
14
|
+
result += KeywordHelper::WriteOptionallyQuoted(names[0]);
|
15
|
+
} else {
|
16
|
+
result += "(";
|
17
|
+
for (idx_t n = 0; n < names.size(); n++) {
|
18
|
+
if (n > 0) {
|
19
|
+
result += ", ";
|
20
|
+
}
|
21
|
+
result += KeywordHelper::WriteOptionallyQuoted(names[n]);
|
22
|
+
}
|
23
|
+
result += ")";
|
24
|
+
}
|
25
|
+
result += " IN ";
|
26
|
+
if (pivot_enum.empty()) {
|
27
|
+
result += "(";
|
28
|
+
for (idx_t e = 0; e < entries.size(); e++) {
|
29
|
+
auto &entry = entries[e];
|
30
|
+
if (e > 0) {
|
31
|
+
result += ", ";
|
32
|
+
}
|
33
|
+
if (entry.star_expr) {
|
34
|
+
D_ASSERT(entry.values.empty());
|
35
|
+
result += entry.star_expr->ToString();
|
36
|
+
} else if (entry.values.size() == 1) {
|
37
|
+
result += entry.values[0].ToSQLString();
|
38
|
+
} else {
|
39
|
+
result += "(";
|
40
|
+
for (idx_t v = 0; v < entry.values.size(); v++) {
|
41
|
+
if (v > 0) {
|
42
|
+
result += ", ";
|
43
|
+
}
|
44
|
+
result += entry.values[v].ToSQLString();
|
45
|
+
}
|
46
|
+
result += ")";
|
47
|
+
}
|
48
|
+
if (!entry.alias.empty()) {
|
49
|
+
result += " AS " + KeywordHelper::WriteOptionallyQuoted(entry.alias);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
result += ")";
|
53
|
+
} else {
|
54
|
+
result += KeywordHelper::WriteOptionallyQuoted(pivot_enum);
|
55
|
+
}
|
56
|
+
return result;
|
57
|
+
}
|
58
|
+
|
59
|
+
bool PivotColumnEntry::Equals(const PivotColumnEntry &other) const {
|
60
|
+
if (alias != other.alias) {
|
61
|
+
return false;
|
62
|
+
}
|
63
|
+
if (values.size() != other.values.size()) {
|
64
|
+
return false;
|
65
|
+
}
|
66
|
+
for (idx_t i = 0; i < values.size(); i++) {
|
67
|
+
if (!Value::NotDistinctFrom(values[i], other.values[i])) {
|
68
|
+
return false;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
return true;
|
72
|
+
}
|
73
|
+
|
74
|
+
bool PivotColumn::Equals(const PivotColumn &other) const {
|
75
|
+
if (other.names != names) {
|
76
|
+
return false;
|
77
|
+
}
|
78
|
+
if (other.pivot_enum != pivot_enum) {
|
79
|
+
return false;
|
80
|
+
}
|
81
|
+
if (other.entries.size() != entries.size()) {
|
82
|
+
return false;
|
83
|
+
}
|
84
|
+
for (idx_t i = 0; i < entries.size(); i++) {
|
85
|
+
if (!entries[i].Equals(other.entries[i])) {
|
86
|
+
return false;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
return true;
|
90
|
+
}
|
91
|
+
|
92
|
+
PivotColumn PivotColumn::Copy() const {
|
93
|
+
PivotColumn result;
|
94
|
+
result.names = names;
|
95
|
+
for (auto &entry : entries) {
|
96
|
+
result.entries.push_back(entry.Copy());
|
97
|
+
}
|
98
|
+
result.pivot_enum = pivot_enum;
|
99
|
+
return result;
|
100
|
+
}
|
101
|
+
|
102
|
+
void PivotColumn::Serialize(Serializer &serializer) const {
|
103
|
+
FieldWriter writer(serializer);
|
104
|
+
writer.WriteList<string>(names);
|
105
|
+
writer.WriteRegularSerializableList(entries);
|
106
|
+
writer.WriteString(pivot_enum);
|
107
|
+
writer.Finalize();
|
108
|
+
}
|
109
|
+
|
110
|
+
PivotColumn PivotColumn::Deserialize(Deserializer &source) {
|
111
|
+
PivotColumn result;
|
112
|
+
FieldReader reader(source);
|
113
|
+
result.names = reader.ReadRequiredList<string>();
|
114
|
+
result.entries = reader.ReadRequiredSerializableList<PivotColumnEntry, PivotColumnEntry>();
|
115
|
+
result.pivot_enum = reader.ReadRequired<string>();
|
116
|
+
reader.Finalize();
|
117
|
+
return result;
|
118
|
+
}
|
119
|
+
|
120
|
+
//===--------------------------------------------------------------------===//
|
121
|
+
// PivotColumnEntry
|
122
|
+
//===--------------------------------------------------------------------===//
|
123
|
+
PivotColumnEntry PivotColumnEntry::Copy() const {
|
124
|
+
PivotColumnEntry result;
|
125
|
+
result.values = values;
|
126
|
+
result.star_expr = star_expr ? star_expr->Copy() : nullptr;
|
127
|
+
result.alias = alias;
|
128
|
+
return result;
|
129
|
+
}
|
130
|
+
|
131
|
+
void PivotColumnEntry::Serialize(Serializer &serializer) const {
|
132
|
+
FieldWriter writer(serializer);
|
133
|
+
writer.WriteRegularSerializableList(values);
|
134
|
+
writer.WriteOptional(star_expr);
|
135
|
+
writer.WriteString(alias);
|
136
|
+
writer.Finalize();
|
137
|
+
}
|
138
|
+
|
139
|
+
PivotColumnEntry PivotColumnEntry::Deserialize(Deserializer &source) {
|
140
|
+
PivotColumnEntry result;
|
141
|
+
FieldReader reader(source);
|
142
|
+
result.values = reader.ReadRequiredSerializableList<Value, Value>();
|
143
|
+
result.star_expr = reader.ReadOptional<ParsedExpression>(nullptr);
|
144
|
+
result.alias = reader.ReadRequired<string>();
|
145
|
+
reader.Finalize();
|
146
|
+
return result;
|
147
|
+
}
|
148
|
+
|
149
|
+
//===--------------------------------------------------------------------===//
|
150
|
+
// PivotRef
|
151
|
+
//===--------------------------------------------------------------------===//
|
152
|
+
string PivotRef::ToString() const {
|
153
|
+
string result;
|
154
|
+
result = source->ToString();
|
155
|
+
if (!aggregates.empty()) {
|
156
|
+
// pivot
|
157
|
+
result += " PIVOT (";
|
158
|
+
for (idx_t aggr_idx = 0; aggr_idx < aggregates.size(); aggr_idx++) {
|
159
|
+
if (aggr_idx > 0) {
|
160
|
+
result += ", ";
|
161
|
+
}
|
162
|
+
result += aggregates[aggr_idx]->ToString();
|
163
|
+
if (!aggregates[aggr_idx]->alias.empty()) {
|
164
|
+
result += " AS " + KeywordHelper::WriteOptionallyQuoted(aggregates[aggr_idx]->alias);
|
165
|
+
}
|
166
|
+
}
|
167
|
+
} else {
|
168
|
+
// unpivot
|
169
|
+
result += " UNPIVOT ";
|
170
|
+
if (include_nulls) {
|
171
|
+
result += "INCLUDE NULLS ";
|
172
|
+
}
|
173
|
+
result += "(";
|
174
|
+
if (unpivot_names.size() == 1) {
|
175
|
+
result += KeywordHelper::WriteOptionallyQuoted(unpivot_names[0]);
|
176
|
+
} else {
|
177
|
+
result += "(";
|
178
|
+
for (idx_t n = 0; n < unpivot_names.size(); n++) {
|
179
|
+
if (n > 0) {
|
180
|
+
result += ", ";
|
181
|
+
}
|
182
|
+
result += KeywordHelper::WriteOptionallyQuoted(unpivot_names[n]);
|
183
|
+
}
|
184
|
+
result += ")";
|
185
|
+
}
|
186
|
+
}
|
187
|
+
result += " FOR";
|
188
|
+
for (auto &pivot : pivots) {
|
189
|
+
result += " ";
|
190
|
+
result += pivot.ToString();
|
191
|
+
}
|
192
|
+
if (!groups.empty()) {
|
193
|
+
result += " GROUP BY ";
|
194
|
+
for (idx_t i = 0; i < groups.size(); i++) {
|
195
|
+
if (i > 0) {
|
196
|
+
result += ", ";
|
197
|
+
}
|
198
|
+
result += groups[i];
|
199
|
+
}
|
200
|
+
}
|
201
|
+
result += ")";
|
202
|
+
if (!alias.empty()) {
|
203
|
+
result += " AS " + KeywordHelper::WriteOptionallyQuoted(alias);
|
204
|
+
if (!column_name_alias.empty()) {
|
205
|
+
result += "(";
|
206
|
+
for (idx_t i = 0; i < column_name_alias.size(); i++) {
|
207
|
+
if (i > 0) {
|
208
|
+
result += ", ";
|
209
|
+
}
|
210
|
+
result += KeywordHelper::WriteOptionallyQuoted(column_name_alias[i]);
|
211
|
+
}
|
212
|
+
result += ")";
|
213
|
+
}
|
214
|
+
}
|
215
|
+
return result;
|
216
|
+
}
|
217
|
+
|
218
|
+
bool PivotRef::Equals(const TableRef *other_p) const {
|
219
|
+
if (!TableRef::Equals(other_p)) {
|
220
|
+
return false;
|
221
|
+
}
|
222
|
+
auto other = (PivotRef *)other_p;
|
223
|
+
if (!source->Equals(other->source.get())) {
|
224
|
+
return false;
|
225
|
+
}
|
226
|
+
if (aggregates.size() != other->aggregates.size()) {
|
227
|
+
return false;
|
228
|
+
}
|
229
|
+
for (idx_t i = 0; i < aggregates.size(); i++) {
|
230
|
+
if (!BaseExpression::Equals(aggregates[i].get(), other->aggregates[i].get())) {
|
231
|
+
return false;
|
232
|
+
}
|
233
|
+
}
|
234
|
+
if (pivots.size() != other->pivots.size()) {
|
235
|
+
return false;
|
236
|
+
}
|
237
|
+
for (idx_t i = 0; i < pivots.size(); i++) {
|
238
|
+
if (!pivots[i].Equals(other->pivots[i])) {
|
239
|
+
return false;
|
240
|
+
}
|
241
|
+
}
|
242
|
+
if (unpivot_names != other->unpivot_names) {
|
243
|
+
return false;
|
244
|
+
}
|
245
|
+
if (alias != other->alias) {
|
246
|
+
return false;
|
247
|
+
}
|
248
|
+
if (groups != other->groups) {
|
249
|
+
return false;
|
250
|
+
}
|
251
|
+
if (include_nulls != other->include_nulls) {
|
252
|
+
return false;
|
253
|
+
}
|
254
|
+
return true;
|
255
|
+
}
|
256
|
+
|
257
|
+
unique_ptr<TableRef> PivotRef::Copy() {
|
258
|
+
auto copy = make_unique<PivotRef>();
|
259
|
+
copy->source = source->Copy();
|
260
|
+
for (auto &aggr : aggregates) {
|
261
|
+
copy->aggregates.push_back(aggr->Copy());
|
262
|
+
}
|
263
|
+
copy->unpivot_names = unpivot_names;
|
264
|
+
for (auto &entry : pivots) {
|
265
|
+
copy->pivots.push_back(entry.Copy());
|
266
|
+
}
|
267
|
+
copy->groups = groups;
|
268
|
+
copy->column_name_alias = column_name_alias;
|
269
|
+
copy->include_nulls = include_nulls;
|
270
|
+
copy->alias = alias;
|
271
|
+
return std::move(copy);
|
272
|
+
}
|
273
|
+
|
274
|
+
void PivotRef::Serialize(FieldWriter &writer) const {
|
275
|
+
writer.WriteSerializable(*source);
|
276
|
+
writer.WriteSerializableList(aggregates);
|
277
|
+
writer.WriteList<string>(unpivot_names);
|
278
|
+
writer.WriteRegularSerializableList(pivots);
|
279
|
+
writer.WriteList<string>(groups);
|
280
|
+
writer.WriteList<string>(column_name_alias);
|
281
|
+
writer.WriteField<bool>(include_nulls);
|
282
|
+
}
|
283
|
+
|
284
|
+
unique_ptr<TableRef> PivotRef::Deserialize(FieldReader &reader) {
|
285
|
+
auto result = make_unique<PivotRef>();
|
286
|
+
result->source = reader.ReadRequiredSerializable<TableRef>();
|
287
|
+
result->aggregates = reader.ReadRequiredSerializableList<ParsedExpression>();
|
288
|
+
result->unpivot_names = reader.ReadRequiredList<string>();
|
289
|
+
result->pivots = reader.ReadRequiredSerializableList<PivotColumn, PivotColumn>();
|
290
|
+
result->groups = reader.ReadRequiredList<string>();
|
291
|
+
result->column_name_alias = reader.ReadRequiredList<string>();
|
292
|
+
result->include_nulls = reader.ReadRequired<bool>();
|
293
|
+
return std::move(result);
|
294
|
+
}
|
295
|
+
|
296
|
+
} // namespace duckdb
|
@@ -78,6 +78,9 @@ unique_ptr<TableRef> TableRef::Deserialize(Deserializer &source) {
|
|
78
78
|
case TableReferenceType::EXPRESSION_LIST:
|
79
79
|
result = ExpressionListRef::Deserialize(reader);
|
80
80
|
break;
|
81
|
+
case TableReferenceType::PIVOT:
|
82
|
+
result = PivotRef::Deserialize(reader);
|
83
|
+
break;
|
81
84
|
case TableReferenceType::CTE:
|
82
85
|
case TableReferenceType::INVALID:
|
83
86
|
throw InternalException("Unsupported type for TableRef::Deserialize");
|
@@ -2,16 +2,22 @@
|
|
2
2
|
|
3
3
|
namespace duckdb {
|
4
4
|
|
5
|
+
vector<string> Transformer::TransformStringList(duckdb_libpgquery::PGList *list) {
|
6
|
+
vector<string> result;
|
7
|
+
if (!list) {
|
8
|
+
return result;
|
9
|
+
}
|
10
|
+
for (auto node = list->head; node != nullptr; node = node->next) {
|
11
|
+
result.emplace_back(reinterpret_cast<duckdb_libpgquery::PGValue *>(node->data.ptr_value)->val.str);
|
12
|
+
}
|
13
|
+
return result;
|
14
|
+
}
|
15
|
+
|
5
16
|
string Transformer::TransformAlias(duckdb_libpgquery::PGAlias *root, vector<string> &column_name_alias) {
|
6
17
|
if (!root) {
|
7
18
|
return "";
|
8
19
|
}
|
9
|
-
|
10
|
-
for (auto node = root->colnames->head; node != nullptr; node = node->next) {
|
11
|
-
column_name_alias.emplace_back(
|
12
|
-
reinterpret_cast<duckdb_libpgquery::PGValue *>(node->data.ptr_value)->val.str);
|
13
|
-
}
|
14
|
-
}
|
20
|
+
column_name_alias = TransformStringList(root->colnames);
|
15
21
|
return root->aliasname;
|
16
22
|
}
|
17
23
|
|
@@ -6,9 +6,33 @@
|
|
6
6
|
|
7
7
|
namespace duckdb {
|
8
8
|
|
9
|
+
unique_ptr<CommonTableExpressionInfo> CommonTableExpressionInfo::Copy() {
|
10
|
+
auto result = make_unique<CommonTableExpressionInfo>();
|
11
|
+
result->aliases = aliases;
|
12
|
+
result->query = unique_ptr_cast<SQLStatement, SelectStatement>(query->Copy());
|
13
|
+
return result;
|
14
|
+
}
|
15
|
+
|
16
|
+
void Transformer::ExtractCTEsRecursive(CommonTableExpressionMap &cte_map) {
|
17
|
+
for (auto &cte_entry : stored_cte_map) {
|
18
|
+
for (auto &entry : cte_entry->map) {
|
19
|
+
auto found_entry = cte_map.map.find(entry.first);
|
20
|
+
if (found_entry != cte_map.map.end()) {
|
21
|
+
// entry already present - use top-most entry
|
22
|
+
continue;
|
23
|
+
}
|
24
|
+
cte_map.map[entry.first] = entry.second->Copy();
|
25
|
+
}
|
26
|
+
}
|
27
|
+
if (parent) {
|
28
|
+
parent->ExtractCTEsRecursive(cte_map);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
9
32
|
void Transformer::TransformCTE(duckdb_libpgquery::PGWithClause *de_with_clause, CommonTableExpressionMap &cte_map) {
|
10
33
|
// TODO: might need to update in case of future lawsuit
|
11
34
|
D_ASSERT(de_with_clause);
|
35
|
+
stored_cte_map.push_back(&cte_map);
|
12
36
|
|
13
37
|
D_ASSERT(de_with_clause->ctes);
|
14
38
|
for (auto cte_ele = de_with_clause->ctes->head; cte_ele != nullptr; cte_ele = cte_ele->next) {
|
@@ -29,6 +29,10 @@ unique_ptr<CreateStatement> Transformer::TransformCreateFunction(duckdb_libpgque
|
|
29
29
|
auto query_node = TransformSelect(stmt->query, true)->node->Copy();
|
30
30
|
macro_func = make_unique<TableMacroFunction>(std::move(query_node));
|
31
31
|
}
|
32
|
+
if (HasPivotEntries()) {
|
33
|
+
throw ParserException("Cannot use PIVOT statement syntax in a macro. Use the SQL standard PIVOT syntax in the "
|
34
|
+
"FROM clause instead.");
|
35
|
+
}
|
32
36
|
|
33
37
|
auto info =
|
34
38
|
make_unique<CreateMacroInfo>((stmt->function ? CatalogType::MACRO_ENTRY : CatalogType::TABLE_MACRO_ENTRY));
|
@@ -26,6 +26,10 @@ unique_ptr<CreateStatement> Transformer::TransformCreateView(duckdb_libpgquery::
|
|
26
26
|
info->on_conflict = TransformOnConflict(stmt->onconflict);
|
27
27
|
|
28
28
|
info->query = TransformSelect(stmt->query, false);
|
29
|
+
if (HasPivotEntries()) {
|
30
|
+
throw ParserException("Cannot use PIVOT statement syntax in a view. Use the SQL standard PIVOT syntax in the "
|
31
|
+
"FROM clause instead.");
|
32
|
+
}
|
29
33
|
|
30
34
|
if (stmt->aliases && stmt->aliases->length > 0) {
|
31
35
|
for (auto c = stmt->aliases->head; c != nullptr; c = lnext(c)) {
|
@@ -0,0 +1,150 @@
|
|
1
|
+
#include "duckdb/parser/transformer.hpp"
|
2
|
+
#include "duckdb/parser/tableref/pivotref.hpp"
|
3
|
+
#include "duckdb/parser/parsed_data/create_type_info.hpp"
|
4
|
+
#include "duckdb/parser/statement/create_statement.hpp"
|
5
|
+
#include "duckdb/parser/statement/select_statement.hpp"
|
6
|
+
#include "duckdb/parser/expression/columnref_expression.hpp"
|
7
|
+
#include "duckdb/parser/expression/star_expression.hpp"
|
8
|
+
#include "duckdb/parser/query_node/select_node.hpp"
|
9
|
+
#include "duckdb/parser/statement/multi_statement.hpp"
|
10
|
+
#include "duckdb/parser/statement/drop_statement.hpp"
|
11
|
+
#include "duckdb/parser/parsed_data/drop_info.hpp"
|
12
|
+
#include "duckdb/parser/expression/cast_expression.hpp"
|
13
|
+
#include "duckdb/parser/result_modifier.hpp"
|
14
|
+
#include "duckdb/parser/tableref/subqueryref.hpp"
|
15
|
+
|
16
|
+
namespace duckdb {
|
17
|
+
|
18
|
+
void Transformer::AddPivotEntry(string enum_name, unique_ptr<SelectNode> base, string column_name) {
|
19
|
+
if (parent) {
|
20
|
+
parent->AddPivotEntry(std::move(enum_name), std::move(base), std::move(column_name));
|
21
|
+
return;
|
22
|
+
}
|
23
|
+
auto result = make_unique<CreatePivotEntry>();
|
24
|
+
result->enum_name = std::move(enum_name);
|
25
|
+
result->base = std::move(base);
|
26
|
+
result->column_name = std::move(column_name);
|
27
|
+
|
28
|
+
pivot_entries.push_back(std::move(result));
|
29
|
+
}
|
30
|
+
|
31
|
+
bool Transformer::HasPivotEntries() {
|
32
|
+
if (parent) {
|
33
|
+
return parent->HasPivotEntries();
|
34
|
+
}
|
35
|
+
return !pivot_entries.empty();
|
36
|
+
}
|
37
|
+
|
38
|
+
idx_t Transformer::PivotEntryCount() {
|
39
|
+
if (parent) {
|
40
|
+
return parent->PivotEntryCount();
|
41
|
+
}
|
42
|
+
return pivot_entries.size();
|
43
|
+
}
|
44
|
+
|
45
|
+
unique_ptr<SQLStatement> Transformer::GenerateCreateEnumStmt(unique_ptr<CreatePivotEntry> entry) {
|
46
|
+
auto result = make_unique<CreateStatement>();
|
47
|
+
auto info = make_unique<CreateTypeInfo>();
|
48
|
+
|
49
|
+
info->temporary = true;
|
50
|
+
info->internal = false;
|
51
|
+
info->catalog = INVALID_CATALOG;
|
52
|
+
info->schema = INVALID_SCHEMA;
|
53
|
+
info->name = std::move(entry->enum_name);
|
54
|
+
info->on_conflict = OnCreateConflict::REPLACE_ON_CONFLICT;
|
55
|
+
|
56
|
+
// generate the query that will result in the enum creation
|
57
|
+
auto select_node = std::move(entry->base);
|
58
|
+
auto columnref = make_unique<ColumnRefExpression>(std::move(entry->column_name));
|
59
|
+
auto cast = make_unique<CastExpression>(LogicalType::VARCHAR, columnref->Copy());
|
60
|
+
select_node->select_list.push_back(std::move(cast));
|
61
|
+
|
62
|
+
// order by the column
|
63
|
+
auto modifier = make_unique<OrderModifier>();
|
64
|
+
modifier->orders.emplace_back(OrderType::ASCENDING, OrderByNullType::ORDER_DEFAULT, std::move(columnref));
|
65
|
+
select_node->modifiers.push_back(std::move(modifier));
|
66
|
+
|
67
|
+
auto select = make_unique<SelectStatement>();
|
68
|
+
select->node = std::move(select_node);
|
69
|
+
info->query = std::move(select);
|
70
|
+
info->type = LogicalType::INVALID;
|
71
|
+
|
72
|
+
result->info = std::move(info);
|
73
|
+
return std::move(result);
|
74
|
+
}
|
75
|
+
|
76
|
+
// unique_ptr<SQLStatement> GenerateDropEnumStmt(string enum_name) {
|
77
|
+
// auto result = make_unique<DropStatement>();
|
78
|
+
// result->info->if_exists = true;
|
79
|
+
// result->info->schema = INVALID_SCHEMA;
|
80
|
+
// result->info->catalog = INVALID_CATALOG;
|
81
|
+
// result->info->name = std::move(enum_name);
|
82
|
+
// result->info->type = CatalogType::TYPE_ENTRY;
|
83
|
+
// return std::move(result);
|
84
|
+
//}
|
85
|
+
|
86
|
+
unique_ptr<SQLStatement> Transformer::CreatePivotStatement(unique_ptr<SQLStatement> statement) {
|
87
|
+
auto result = make_unique<MultiStatement>();
|
88
|
+
for (auto &pivot : pivot_entries) {
|
89
|
+
result->statements.push_back(GenerateCreateEnumStmt(std::move(pivot)));
|
90
|
+
}
|
91
|
+
result->statements.push_back(std::move(statement));
|
92
|
+
// FIXME: drop the types again!?
|
93
|
+
// for(auto &pivot : pivot_entries) {
|
94
|
+
// result->statements.push_back(GenerateDropEnumStmt(std::move(pivot->enum_name)));
|
95
|
+
// }
|
96
|
+
return std::move(result);
|
97
|
+
}
|
98
|
+
|
99
|
+
unique_ptr<QueryNode> Transformer::TransformPivotStatement(duckdb_libpgquery::PGSelectStmt *stmt) {
|
100
|
+
auto pivot = stmt->pivot;
|
101
|
+
auto source = TransformTableRefNode(pivot->source);
|
102
|
+
auto columns = TransformPivotList(pivot->columns);
|
103
|
+
|
104
|
+
auto select_node = make_unique<SelectNode>();
|
105
|
+
// handle the CTEs
|
106
|
+
if (stmt->withClause) {
|
107
|
+
TransformCTE(reinterpret_cast<duckdb_libpgquery::PGWithClause *>(stmt->withClause), select_node->cte_map);
|
108
|
+
}
|
109
|
+
|
110
|
+
// generate CREATE TYPE statements for each of the columns that do not have an IN list
|
111
|
+
auto pivot_idx = PivotEntryCount();
|
112
|
+
for (idx_t c = 0; c < columns.size(); c++) {
|
113
|
+
auto &col = columns[c];
|
114
|
+
if (!col.pivot_enum.empty() || !col.entries.empty()) {
|
115
|
+
continue;
|
116
|
+
}
|
117
|
+
if (col.names.size() != 1) {
|
118
|
+
throw InternalException("PIVOT statement with multiple names in pivot entry!?");
|
119
|
+
}
|
120
|
+
auto enum_name = "__pivot_enum_" + std::to_string(pivot_idx) + "_" + std::to_string(c);
|
121
|
+
|
122
|
+
auto new_select = make_unique<SelectNode>();
|
123
|
+
ExtractCTEsRecursive(new_select->cte_map);
|
124
|
+
new_select->from_table = source->Copy();
|
125
|
+
AddPivotEntry(enum_name, std::move(new_select), col.names[0]);
|
126
|
+
col.pivot_enum = enum_name;
|
127
|
+
}
|
128
|
+
|
129
|
+
// generate the actual query, including the pivot
|
130
|
+
select_node->select_list.push_back(make_unique<StarExpression>());
|
131
|
+
|
132
|
+
auto pivot_ref = make_unique<PivotRef>();
|
133
|
+
pivot_ref->source = std::move(source);
|
134
|
+
if (pivot->aggrs) {
|
135
|
+
TransformExpressionList(*pivot->aggrs, pivot_ref->aggregates);
|
136
|
+
} else {
|
137
|
+
if (!pivot->unpivots) {
|
138
|
+
throw InternalException("No unpivots and no aggrs");
|
139
|
+
}
|
140
|
+
pivot_ref->unpivot_names = TransformStringList(pivot->unpivots);
|
141
|
+
}
|
142
|
+
if (pivot->groups) {
|
143
|
+
pivot_ref->groups = TransformStringList(pivot->groups);
|
144
|
+
}
|
145
|
+
pivot_ref->pivots = std::move(columns);
|
146
|
+
select_node->from_table = std::move(pivot_ref);
|
147
|
+
return std::move(select_node);
|
148
|
+
}
|
149
|
+
|
150
|
+
} // namespace duckdb
|
@@ -4,6 +4,14 @@
|
|
4
4
|
|
5
5
|
namespace duckdb {
|
6
6
|
|
7
|
+
unique_ptr<QueryNode> Transformer::TransformSelectNode(duckdb_libpgquery::PGSelectStmt *stmt) {
|
8
|
+
if (stmt->pivot) {
|
9
|
+
return TransformPivotStatement(stmt);
|
10
|
+
} else {
|
11
|
+
return TransformSelectInternal(stmt);
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
7
15
|
unique_ptr<SelectStatement> Transformer::TransformSelect(duckdb_libpgquery::PGNode *node, bool is_select) {
|
8
16
|
auto stmt = reinterpret_cast<duckdb_libpgquery::PGSelectStmt *>(node);
|
9
17
|
auto result = make_unique<SelectStatement>();
|
@@ -8,7 +8,7 @@
|
|
8
8
|
|
9
9
|
namespace duckdb {
|
10
10
|
|
11
|
-
unique_ptr<QueryNode> Transformer::
|
11
|
+
unique_ptr<QueryNode> Transformer::TransformSelectInternal(duckdb_libpgquery::PGSelectStmt *stmt) {
|
12
12
|
D_ASSERT(stmt->type == duckdb_libpgquery::T_PGSelectStmt);
|
13
13
|
auto stack_checker = StackCheck();
|
14
14
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#include "duckdb/common/exception.hpp"
|
2
|
+
#include "duckdb/parser/tableref/pivotref.hpp"
|
3
|
+
#include "duckdb/parser/transformer.hpp"
|
4
|
+
#include "duckdb/parser/expression/columnref_expression.hpp"
|
5
|
+
#include "duckdb/parser/expression/constant_expression.hpp"
|
6
|
+
#include "duckdb/parser/expression/function_expression.hpp"
|
7
|
+
|
8
|
+
namespace duckdb {
|
9
|
+
|
10
|
+
static void TransformPivotInList(unique_ptr<ParsedExpression> &expr, PivotColumnEntry &entry, bool root_entry = true) {
|
11
|
+
if (expr->type == ExpressionType::COLUMN_REF) {
|
12
|
+
auto &colref = (ColumnRefExpression &)*expr;
|
13
|
+
if (colref.IsQualified()) {
|
14
|
+
throw ParserException("PIVOT IN list cannot contain qualified column references");
|
15
|
+
}
|
16
|
+
entry.values.emplace_back(colref.GetColumnName());
|
17
|
+
} else if (expr->type == ExpressionType::VALUE_CONSTANT) {
|
18
|
+
auto &constant_expr = (ConstantExpression &)*expr;
|
19
|
+
entry.values.push_back(std::move(constant_expr.value));
|
20
|
+
} else if (root_entry && expr->type == ExpressionType::FUNCTION) {
|
21
|
+
auto &function = (FunctionExpression &)*expr;
|
22
|
+
if (function.function_name != "row") {
|
23
|
+
throw ParserException("PIVOT IN list must contain columns or lists of columns");
|
24
|
+
}
|
25
|
+
for (auto &child : function.children) {
|
26
|
+
TransformPivotInList(child, entry, false);
|
27
|
+
}
|
28
|
+
} else if (root_entry && expr->type == ExpressionType::STAR) {
|
29
|
+
entry.star_expr = std::move(expr);
|
30
|
+
} else {
|
31
|
+
throw ParserException("PIVOT IN list must contain columns or lists of columns");
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
PivotColumn Transformer::TransformPivotColumn(duckdb_libpgquery::PGPivot *pivot) {
|
36
|
+
PivotColumn col;
|
37
|
+
col.names = TransformStringList(pivot->pivot_columns);
|
38
|
+
if (pivot->pivot_value) {
|
39
|
+
for (auto node = pivot->pivot_value->head; node != nullptr; node = node->next) {
|
40
|
+
auto n = (duckdb_libpgquery::PGNode *)node->data.ptr_value;
|
41
|
+
auto expr = TransformExpression(n);
|
42
|
+
PivotColumnEntry entry;
|
43
|
+
entry.alias = expr->alias;
|
44
|
+
TransformPivotInList(expr, entry);
|
45
|
+
col.entries.push_back(std::move(entry));
|
46
|
+
}
|
47
|
+
}
|
48
|
+
if (pivot->pivot_enum) {
|
49
|
+
col.pivot_enum = pivot->pivot_enum;
|
50
|
+
}
|
51
|
+
return col;
|
52
|
+
}
|
53
|
+
|
54
|
+
vector<PivotColumn> Transformer::TransformPivotList(duckdb_libpgquery::PGList *list) {
|
55
|
+
vector<PivotColumn> result;
|
56
|
+
for (auto node = list->head; node != nullptr; node = node->next) {
|
57
|
+
auto pivot = (duckdb_libpgquery::PGPivot *)node->data.ptr_value;
|
58
|
+
result.push_back(TransformPivotColumn(pivot));
|
59
|
+
}
|
60
|
+
return result;
|
61
|
+
}
|
62
|
+
|
63
|
+
unique_ptr<TableRef> Transformer::TransformPivot(duckdb_libpgquery::PGPivotExpr *root) {
|
64
|
+
auto result = make_unique<PivotRef>();
|
65
|
+
result->source = TransformTableRefNode(root->source);
|
66
|
+
if (root->aggrs) {
|
67
|
+
TransformExpressionList(*root->aggrs, result->aggregates);
|
68
|
+
}
|
69
|
+
if (root->unpivots) {
|
70
|
+
result->unpivot_names = TransformStringList(root->unpivots);
|
71
|
+
}
|
72
|
+
result->pivots = TransformPivotList(root->pivots);
|
73
|
+
if (root->groups) {
|
74
|
+
result->groups = TransformStringList(root->groups);
|
75
|
+
}
|
76
|
+
for (auto &pivot : result->pivots) {
|
77
|
+
idx_t expected_size;
|
78
|
+
bool is_pivot = result->unpivot_names.empty();
|
79
|
+
if (!result->unpivot_names.empty()) {
|
80
|
+
// unpivot
|
81
|
+
if (pivot.names.size() != 1) {
|
82
|
+
throw ParserException("UNPIVOT requires a single column name for the PIVOT IN clause");
|
83
|
+
}
|
84
|
+
expected_size = pivot.entries[0].values.size();
|
85
|
+
} else {
|
86
|
+
// pivot
|
87
|
+
expected_size = pivot.names.size();
|
88
|
+
}
|
89
|
+
for (auto &entry : pivot.entries) {
|
90
|
+
if (entry.star_expr && is_pivot) {
|
91
|
+
throw ParserException("PIVOT IN list must contain columns or lists of columns - star expressions are "
|
92
|
+
"only supported for UNPIVOT");
|
93
|
+
}
|
94
|
+
if (entry.values.size() != expected_size) {
|
95
|
+
throw ParserException("PIVOT IN list - inconsistent amount of rows - expected %d but got %d",
|
96
|
+
expected_size, entry.values.size());
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
result->include_nulls = root->include_nulls;
|
101
|
+
result->alias = TransformAlias(root->alias, result->column_name_alias);
|
102
|
+
return std::move(result);
|
103
|
+
}
|
104
|
+
|
105
|
+
} // namespace duckdb
|
@@ -16,6 +16,8 @@ unique_ptr<TableRef> Transformer::TransformTableRefNode(duckdb_libpgquery::PGNod
|
|
16
16
|
return TransformRangeSubselect(reinterpret_cast<duckdb_libpgquery::PGRangeSubselect *>(n));
|
17
17
|
case duckdb_libpgquery::T_PGRangeFunction:
|
18
18
|
return TransformRangeFunction(reinterpret_cast<duckdb_libpgquery::PGRangeFunction *>(n));
|
19
|
+
case duckdb_libpgquery::T_PGPivotExpr:
|
20
|
+
return TransformPivot(reinterpret_cast<duckdb_libpgquery::PGPivotExpr *>(n));
|
19
21
|
default:
|
20
22
|
throw NotImplementedException("From Type %d not supported", n->type);
|
21
23
|
}
|