duckdb 0.7.2-dev865.0 → 0.7.2-dev886.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/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/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/transform/statement/transform_pivot_stmt.cpp +31 -6
- package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +1 -1
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +13437 -13349
package/package.json
CHANGED
@@ -131,6 +131,9 @@ static DefaultMacro internal_macros[] = {
|
|
131
131
|
// nested list aggregates
|
132
132
|
{DEFAULT_SCHEMA, "list_histogram", {"l", nullptr}, "list_aggr(l, 'histogram')"},
|
133
133
|
|
134
|
+
// date functions
|
135
|
+
{DEFAULT_SCHEMA, "date_add", {"date", "interval", nullptr}, "date + interval"},
|
136
|
+
|
134
137
|
{nullptr, nullptr, {nullptr}, nullptr}
|
135
138
|
};
|
136
139
|
|
@@ -46,32 +46,59 @@ bool DuckCatalog::IsDuckCatalog() {
|
|
46
46
|
//===--------------------------------------------------------------------===//
|
47
47
|
// Schema
|
48
48
|
//===--------------------------------------------------------------------===//
|
49
|
-
CatalogEntry *DuckCatalog::
|
50
|
-
D_ASSERT(!info->schema.empty());
|
49
|
+
CatalogEntry *DuckCatalog::CreateSchemaInternal(CatalogTransaction transaction, CreateSchemaInfo *info) {
|
51
50
|
DependencyList dependencies;
|
52
51
|
auto entry = make_unique<DuckSchemaEntry>(this, info->schema, info->internal);
|
53
52
|
auto result = entry.get();
|
54
53
|
if (!schemas->CreateEntry(transaction, info->schema, std::move(entry), dependencies)) {
|
55
|
-
|
54
|
+
return nullptr;
|
55
|
+
}
|
56
|
+
return (CatalogEntry *)result;
|
57
|
+
}
|
58
|
+
|
59
|
+
CatalogEntry *DuckCatalog::CreateSchema(CatalogTransaction transaction, CreateSchemaInfo *info) {
|
60
|
+
D_ASSERT(!info->schema.empty());
|
61
|
+
auto result = CreateSchemaInternal(transaction, info);
|
62
|
+
if (!result) {
|
63
|
+
switch (info->on_conflict) {
|
64
|
+
case OnCreateConflict::ERROR_ON_CONFLICT:
|
56
65
|
throw CatalogException("Schema with name %s already exists!", info->schema);
|
57
|
-
|
58
|
-
|
66
|
+
case OnCreateConflict::REPLACE_ON_CONFLICT: {
|
67
|
+
DropInfo drop_info;
|
68
|
+
drop_info.type = CatalogType::SCHEMA_ENTRY;
|
69
|
+
drop_info.catalog = info->catalog;
|
70
|
+
drop_info.name = info->schema;
|
71
|
+
DropSchema(transaction, &drop_info);
|
72
|
+
result = CreateSchemaInternal(transaction, info);
|
73
|
+
if (!result) {
|
74
|
+
throw InternalException("Failed to create schema entry in CREATE_OR_REPLACE");
|
75
|
+
}
|
76
|
+
break;
|
77
|
+
}
|
78
|
+
case OnCreateConflict::IGNORE_ON_CONFLICT:
|
79
|
+
break;
|
80
|
+
default:
|
81
|
+
throw InternalException("Unsupported OnCreateConflict for CreateSchema");
|
59
82
|
}
|
60
83
|
return nullptr;
|
61
84
|
}
|
62
85
|
return result;
|
63
86
|
}
|
64
87
|
|
65
|
-
void DuckCatalog::DropSchema(
|
88
|
+
void DuckCatalog::DropSchema(CatalogTransaction transaction, DropInfo *info) {
|
66
89
|
D_ASSERT(!info->name.empty());
|
67
90
|
ModifyCatalog();
|
68
|
-
if (!schemas->DropEntry(
|
91
|
+
if (!schemas->DropEntry(transaction, info->name, info->cascade)) {
|
69
92
|
if (!info->if_exists) {
|
70
93
|
throw CatalogException("Schema with name \"%s\" does not exist!", info->name);
|
71
94
|
}
|
72
95
|
}
|
73
96
|
}
|
74
97
|
|
98
|
+
void DuckCatalog::DropSchema(ClientContext &context, DropInfo *info) {
|
99
|
+
DropSchema(GetCatalogTransaction(context), info);
|
100
|
+
}
|
101
|
+
|
75
102
|
void DuckCatalog::ScanSchemas(ClientContext &context, std::function<void(CatalogEntry *)> callback) {
|
76
103
|
schemas->Scan(GetCatalogTransaction(context), [&](CatalogEntry *entry) { callback(entry); });
|
77
104
|
}
|
@@ -197,6 +197,60 @@ list<ColumnDataCollection> BoxRenderer::FetchRenderCollections(ClientContext &co
|
|
197
197
|
return collections;
|
198
198
|
}
|
199
199
|
|
200
|
+
list<ColumnDataCollection> BoxRenderer::PivotCollections(ClientContext &context, list<ColumnDataCollection> input,
|
201
|
+
vector<string> &column_names,
|
202
|
+
vector<LogicalType> &result_types, idx_t row_count) {
|
203
|
+
auto &top = input.front();
|
204
|
+
auto &bottom = input.back();
|
205
|
+
|
206
|
+
vector<LogicalType> varchar_types;
|
207
|
+
vector<string> new_names;
|
208
|
+
new_names.emplace_back("Column");
|
209
|
+
new_names.emplace_back("Type");
|
210
|
+
varchar_types.emplace_back(LogicalType::VARCHAR);
|
211
|
+
varchar_types.emplace_back(LogicalType::VARCHAR);
|
212
|
+
for (idx_t r = 0; r < top.Count(); r++) {
|
213
|
+
new_names.emplace_back("Row " + to_string(r + 1));
|
214
|
+
varchar_types.emplace_back(LogicalType::VARCHAR);
|
215
|
+
}
|
216
|
+
for (idx_t r = 0; r < bottom.Count(); r++) {
|
217
|
+
auto row_index = row_count - bottom.Count() + r + 1;
|
218
|
+
new_names.emplace_back("Row " + to_string(row_index));
|
219
|
+
varchar_types.emplace_back(LogicalType::VARCHAR);
|
220
|
+
}
|
221
|
+
//
|
222
|
+
DataChunk row_chunk;
|
223
|
+
row_chunk.Initialize(Allocator::DefaultAllocator(), varchar_types);
|
224
|
+
std::list<ColumnDataCollection> result;
|
225
|
+
result.emplace_back(context, varchar_types);
|
226
|
+
result.emplace_back(context, varchar_types);
|
227
|
+
auto &res_coll = result.front();
|
228
|
+
ColumnDataAppendState append_state;
|
229
|
+
res_coll.InitializeAppend(append_state);
|
230
|
+
for (idx_t c = 0; c < top.ColumnCount(); c++) {
|
231
|
+
vector<column_t> column_ids {c};
|
232
|
+
auto row_index = row_chunk.size();
|
233
|
+
idx_t current_index = 0;
|
234
|
+
row_chunk.SetValue(current_index++, row_index, column_names[c]);
|
235
|
+
row_chunk.SetValue(current_index++, row_index, RenderType(result_types[c]));
|
236
|
+
for (auto &collection : input) {
|
237
|
+
for (auto &chunk : collection.Chunks(column_ids)) {
|
238
|
+
for (idx_t r = 0; r < chunk.size(); r++) {
|
239
|
+
row_chunk.SetValue(current_index++, row_index, chunk.GetValue(0, r));
|
240
|
+
}
|
241
|
+
}
|
242
|
+
}
|
243
|
+
row_chunk.SetCardinality(row_chunk.size() + 1);
|
244
|
+
if (row_chunk.size() == STANDARD_VECTOR_SIZE || c + 1 == top.ColumnCount()) {
|
245
|
+
res_coll.Append(append_state, row_chunk);
|
246
|
+
row_chunk.Reset();
|
247
|
+
}
|
248
|
+
}
|
249
|
+
column_names = std::move(new_names);
|
250
|
+
result_types = std::move(varchar_types);
|
251
|
+
return result;
|
252
|
+
}
|
253
|
+
|
200
254
|
string ConvertRenderValue(const string &input) {
|
201
255
|
return StringUtil::Replace(StringUtil::Replace(input, "\n", "\\n"), string("\0", 1), "\\0");
|
202
256
|
}
|
@@ -213,11 +267,10 @@ string BoxRenderer::GetRenderValue(ColumnDataRowCollection &rows, idx_t c, idx_t
|
|
213
267
|
}
|
214
268
|
}
|
215
269
|
|
216
|
-
vector<idx_t> BoxRenderer::ComputeRenderWidths(const vector<string> &names, const
|
270
|
+
vector<idx_t> BoxRenderer::ComputeRenderWidths(const vector<string> &names, const vector<LogicalType> &result_types,
|
217
271
|
list<ColumnDataCollection> &collections, idx_t min_width,
|
218
272
|
idx_t max_width, vector<idx_t> &column_map, idx_t &total_length) {
|
219
|
-
auto column_count =
|
220
|
-
auto &result_types = result.Types();
|
273
|
+
auto column_count = result_types.size();
|
221
274
|
|
222
275
|
vector<idx_t> widths;
|
223
276
|
widths.reserve(column_count);
|
@@ -357,13 +410,15 @@ void BoxRenderer::RenderHeader(const vector<string> &names, const vector<Logical
|
|
357
410
|
ss << std::endl;
|
358
411
|
|
359
412
|
// render the types
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
413
|
+
if (config.render_mode == RenderMode::ROWS) {
|
414
|
+
for (idx_t c = 0; c < column_count; c++) {
|
415
|
+
auto column_idx = column_map[c];
|
416
|
+
auto type = column_idx == SPLIT_COLUMN ? "" : RenderType(result_types[column_idx]);
|
417
|
+
RenderValue(ss, type, widths[c]);
|
418
|
+
}
|
419
|
+
ss << config.VERTICAL;
|
420
|
+
ss << std::endl;
|
364
421
|
}
|
365
|
-
ss << config.VERTICAL;
|
366
|
-
ss << std::endl;
|
367
422
|
|
368
423
|
// render the line under the header
|
369
424
|
ss << config.LMIDDLE;
|
@@ -390,12 +445,14 @@ void BoxRenderer::RenderValues(const list<ColumnDataCollection> &collections, co
|
|
390
445
|
auto column_count = column_map.size();
|
391
446
|
|
392
447
|
vector<ValueRenderAlignment> alignments;
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
448
|
+
if (config.render_mode == RenderMode::ROWS) {
|
449
|
+
for (idx_t c = 0; c < column_count; c++) {
|
450
|
+
auto column_idx = column_map[c];
|
451
|
+
if (column_idx == SPLIT_COLUMN) {
|
452
|
+
alignments.push_back(ValueRenderAlignment::MIDDLE);
|
453
|
+
} else {
|
454
|
+
alignments.push_back(TypeAlignment(result_types[column_idx]));
|
455
|
+
}
|
399
456
|
}
|
400
457
|
}
|
401
458
|
|
@@ -409,13 +466,28 @@ void BoxRenderer::RenderValues(const list<ColumnDataCollection> &collections, co
|
|
409
466
|
} else {
|
410
467
|
str = GetRenderValue(rows, column_idx, r);
|
411
468
|
}
|
412
|
-
|
469
|
+
ValueRenderAlignment alignment;
|
470
|
+
if (config.render_mode == RenderMode::ROWS) {
|
471
|
+
alignment = alignments[c];
|
472
|
+
} else {
|
473
|
+
if (c < 2) {
|
474
|
+
alignment = ValueRenderAlignment::LEFT;
|
475
|
+
} else if (c == SPLIT_COLUMN) {
|
476
|
+
alignment = ValueRenderAlignment::MIDDLE;
|
477
|
+
} else {
|
478
|
+
alignment = ValueRenderAlignment::RIGHT;
|
479
|
+
}
|
480
|
+
}
|
481
|
+
RenderValue(ss, str, widths[c], alignment);
|
413
482
|
}
|
414
483
|
ss << config.VERTICAL;
|
415
484
|
ss << std::endl;
|
416
485
|
}
|
417
486
|
|
418
487
|
if (bottom_rows > 0) {
|
488
|
+
if (config.render_mode == RenderMode::COLUMNS) {
|
489
|
+
throw InternalException("Columns render mode does not support bottom rows");
|
490
|
+
}
|
419
491
|
// render the bottom rows
|
420
492
|
// first render the divider
|
421
493
|
auto brows = bottom_collection.GetRows();
|
@@ -607,15 +679,19 @@ void BoxRenderer::Render(ClientContext &context, const vector<string> &names, co
|
|
607
679
|
|
608
680
|
// fetch the top and bottom render collections from the result
|
609
681
|
auto collections = FetchRenderCollections(context, result, top_rows, bottom_rows);
|
610
|
-
|
611
|
-
auto
|
682
|
+
auto column_names = names;
|
683
|
+
auto result_types = result.Types();
|
684
|
+
if (config.render_mode == RenderMode::COLUMNS) {
|
685
|
+
collections = PivotCollections(context, std::move(collections), column_names, result_types, row_count);
|
686
|
+
}
|
612
687
|
|
613
688
|
// for each column, figure out the width
|
614
689
|
// start off by figuring out the name of the header by looking at the column name and column type
|
615
690
|
idx_t min_width = has_hidden_rows || row_count == 0 ? minimum_row_length : 0;
|
616
691
|
vector<idx_t> column_map;
|
617
692
|
idx_t total_length;
|
618
|
-
auto widths =
|
693
|
+
auto widths =
|
694
|
+
ComputeRenderWidths(column_names, result_types, collections, min_width, max_width, column_map, total_length);
|
619
695
|
|
620
696
|
// render boundaries for the individual columns
|
621
697
|
vector<idx_t> boundaries;
|
@@ -631,7 +707,7 @@ void BoxRenderer::Render(ClientContext &context, const vector<string> &names, co
|
|
631
707
|
|
632
708
|
// now begin rendering
|
633
709
|
// first render the header
|
634
|
-
RenderHeader(
|
710
|
+
RenderHeader(column_names, result_types, column_map, widths, boundaries, total_length, row_count > 0, ss);
|
635
711
|
|
636
712
|
// render the values, if there are any
|
637
713
|
RenderValues(collections, column_map, widths, result_types, ss);
|
@@ -649,10 +725,20 @@ void BoxRenderer::Render(ClientContext &context, const vector<string> &names, co
|
|
649
725
|
}
|
650
726
|
}
|
651
727
|
idx_t column_count = column_map.size();
|
652
|
-
if (
|
653
|
-
|
654
|
-
|
728
|
+
if (config.render_mode == RenderMode::COLUMNS) {
|
729
|
+
if (has_hidden_columns) {
|
730
|
+
has_hidden_rows = true;
|
731
|
+
shown_str = " (" + to_string(column_count - 3) + " shown)";
|
732
|
+
} else {
|
733
|
+
shown_str = string();
|
734
|
+
}
|
735
|
+
} else {
|
736
|
+
if (has_hidden_columns) {
|
737
|
+
column_count--;
|
738
|
+
column_count_str += " (" + to_string(column_count) + " shown)";
|
739
|
+
}
|
655
740
|
}
|
741
|
+
|
656
742
|
RenderRowCount(std::move(row_count_str), std::move(shown_str), column_count_str, boundaries, has_hidden_rows,
|
657
743
|
has_hidden_columns, total_length, row_count, column_count, minimum_row_length, ss);
|
658
744
|
}
|
@@ -1,8 +1,8 @@
|
|
1
1
|
#ifndef DUCKDB_VERSION
|
2
|
-
#define DUCKDB_VERSION "0.7.2-
|
2
|
+
#define DUCKDB_VERSION "0.7.2-dev886"
|
3
3
|
#endif
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
5
|
+
#define DUCKDB_SOURCE_ID "7d73c6e6a8"
|
6
6
|
#endif
|
7
7
|
#include "duckdb/function/table/system_functions.hpp"
|
8
8
|
#include "duckdb/main/database.hpp"
|
@@ -59,8 +59,9 @@ public:
|
|
59
59
|
DUCKDB_API string GetDBPath() override;
|
60
60
|
|
61
61
|
private:
|
62
|
+
DUCKDB_API void DropSchema(CatalogTransaction transaction, DropInfo *info);
|
62
63
|
DUCKDB_API void DropSchema(ClientContext &context, DropInfo *info) override;
|
63
|
-
|
64
|
+
CatalogEntry *CreateSchemaInternal(CatalogTransaction transaction, CreateSchemaInfo *info);
|
64
65
|
void Verify() override;
|
65
66
|
|
66
67
|
private:
|
@@ -18,6 +18,7 @@ class ColumnDataCollection;
|
|
18
18
|
class ColumnDataRowCollection;
|
19
19
|
|
20
20
|
enum class ValueRenderAlignment { LEFT, MIDDLE, RIGHT };
|
21
|
+
enum class RenderMode { ROWS, COLUMNS };
|
21
22
|
|
22
23
|
struct BoxRendererConfig {
|
23
24
|
// a max_width of 0 means we default to the terminal width
|
@@ -30,7 +31,10 @@ struct BoxRendererConfig {
|
|
30
31
|
// the max col width determines the maximum size of a single column
|
31
32
|
// note that the max col width is only used if the result does not fit on the screen
|
32
33
|
idx_t max_col_width = 20;
|
34
|
+
//! how to render NULL values
|
33
35
|
string null_value = "NULL";
|
36
|
+
//! Whether or not to render row-wise or column-wise
|
37
|
+
RenderMode render_mode = RenderMode::ROWS;
|
34
38
|
|
35
39
|
#ifndef DUCKDB_ASCII_TREE_RENDERER
|
36
40
|
const char *LTCORNER = "\342\224\214"; // "┌";
|
@@ -94,10 +98,12 @@ private:
|
|
94
98
|
string RenderType(const LogicalType &type);
|
95
99
|
ValueRenderAlignment TypeAlignment(const LogicalType &type);
|
96
100
|
string GetRenderValue(ColumnDataRowCollection &rows, idx_t c, idx_t r);
|
97
|
-
|
98
101
|
list<ColumnDataCollection> FetchRenderCollections(ClientContext &context, const ColumnDataCollection &result,
|
99
102
|
idx_t top_rows, idx_t bottom_rows);
|
100
|
-
|
103
|
+
list<ColumnDataCollection> PivotCollections(ClientContext &context, list<ColumnDataCollection> input,
|
104
|
+
vector<string> &column_names, vector<LogicalType> &result_types,
|
105
|
+
idx_t row_count);
|
106
|
+
vector<idx_t> ComputeRenderWidths(const vector<string> &names, const vector<LogicalType> &result_types,
|
101
107
|
list<ColumnDataCollection> &collections, idx_t min_width, idx_t max_width,
|
102
108
|
vector<idx_t> &column_map, idx_t &total_length);
|
103
109
|
void RenderHeader(const vector<string> &names, const vector<LogicalType> &result_types,
|
@@ -67,6 +67,8 @@ private:
|
|
67
67
|
unique_ptr<LogicalOperator> PushdownSingleJoin(unique_ptr<LogicalOperator> op, unordered_set<idx_t> &left_bindings,
|
68
68
|
unordered_set<idx_t> &right_bindings);
|
69
69
|
|
70
|
+
//! Push any remaining filters into a LogicalFilter at this level
|
71
|
+
unique_ptr<LogicalOperator> PushFinalFilters(unique_ptr<LogicalOperator> op);
|
70
72
|
// Finish pushing down at this operator, creating a LogicalFilter to store any of the stored filters and recursively
|
71
73
|
// pushing down into its children (if any)
|
72
74
|
unique_ptr<LogicalOperator> FinishPushdown(unique_ptr<LogicalOperator> op);
|
@@ -105,13 +105,7 @@ void FilterPushdown::GenerateFilters() {
|
|
105
105
|
});
|
106
106
|
}
|
107
107
|
|
108
|
-
unique_ptr<LogicalOperator> FilterPushdown::
|
109
|
-
// unhandled type, first perform filter pushdown in its children
|
110
|
-
for (auto &child : op->children) {
|
111
|
-
FilterPushdown pushdown(optimizer);
|
112
|
-
child = pushdown.Rewrite(std::move(child));
|
113
|
-
}
|
114
|
-
// now push any existing filters
|
108
|
+
unique_ptr<LogicalOperator> FilterPushdown::PushFinalFilters(unique_ptr<LogicalOperator> op) {
|
115
109
|
if (filters.empty()) {
|
116
110
|
// no filters to push
|
117
111
|
return op;
|
@@ -124,6 +118,16 @@ unique_ptr<LogicalOperator> FilterPushdown::FinishPushdown(unique_ptr<LogicalOpe
|
|
124
118
|
return std::move(filter);
|
125
119
|
}
|
126
120
|
|
121
|
+
unique_ptr<LogicalOperator> FilterPushdown::FinishPushdown(unique_ptr<LogicalOperator> op) {
|
122
|
+
// unhandled type, first perform filter pushdown in its children
|
123
|
+
for (auto &child : op->children) {
|
124
|
+
FilterPushdown pushdown(optimizer);
|
125
|
+
child = pushdown.Rewrite(std::move(child));
|
126
|
+
}
|
127
|
+
// now push any existing filters
|
128
|
+
return PushFinalFilters(std::move(op));
|
129
|
+
}
|
130
|
+
|
127
131
|
void FilterPushdown::Filter::ExtractBindings() {
|
128
132
|
bindings.clear();
|
129
133
|
LogicalJoin::GetExpressionBindings(*filter, bindings);
|
@@ -122,16 +122,7 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownLeftJoin(unique_ptr<LogicalO
|
|
122
122
|
right_pushdown.GenerateFilters();
|
123
123
|
op->children[0] = left_pushdown.Rewrite(std::move(op->children[0]));
|
124
124
|
op->children[1] = right_pushdown.Rewrite(std::move(op->children[1]));
|
125
|
-
|
126
|
-
// no filters to push
|
127
|
-
return op;
|
128
|
-
}
|
129
|
-
auto filter = make_unique<LogicalFilter>();
|
130
|
-
for (auto &f : filters) {
|
131
|
-
filter->expressions.push_back(std::move(f->filter));
|
132
|
-
}
|
133
|
-
filter->children.push_back(std::move(op));
|
134
|
-
return std::move(filter);
|
125
|
+
return PushFinalFilters(std::move(op));
|
135
126
|
}
|
136
127
|
|
137
128
|
} // namespace duckdb
|
@@ -77,7 +77,7 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownMarkJoin(unique_ptr<LogicalO
|
|
77
77
|
}
|
78
78
|
op->children[0] = left_pushdown.Rewrite(std::move(op->children[0]));
|
79
79
|
op->children[1] = right_pushdown.Rewrite(std::move(op->children[1]));
|
80
|
-
return
|
80
|
+
return PushFinalFilters(std::move(op));
|
81
81
|
}
|
82
82
|
|
83
83
|
} // namespace duckdb
|
@@ -23,7 +23,7 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownSingleJoin(unique_ptr<Logica
|
|
23
23
|
}
|
24
24
|
op->children[0] = left_pushdown.Rewrite(std::move(op->children[0]));
|
25
25
|
op->children[1] = right_pushdown.Rewrite(std::move(op->children[1]));
|
26
|
-
return
|
26
|
+
return PushFinalFilters(std::move(op));
|
27
27
|
}
|
28
28
|
|
29
29
|
} // namespace duckdb
|
@@ -10,6 +10,7 @@
|
|
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/function_expression.hpp"
|
13
14
|
#include "duckdb/parser/result_modifier.hpp"
|
14
15
|
#include "duckdb/parser/tableref/subqueryref.hpp"
|
15
16
|
|
@@ -99,15 +100,35 @@ unique_ptr<SQLStatement> Transformer::CreatePivotStatement(unique_ptr<SQLStateme
|
|
99
100
|
unique_ptr<QueryNode> Transformer::TransformPivotStatement(duckdb_libpgquery::PGSelectStmt *stmt) {
|
100
101
|
auto pivot = stmt->pivot;
|
101
102
|
auto source = TransformTableRefNode(pivot->source);
|
102
|
-
auto columns = TransformPivotList(pivot->columns);
|
103
103
|
|
104
104
|
auto select_node = make_unique<SelectNode>();
|
105
105
|
// handle the CTEs
|
106
106
|
if (stmt->withClause) {
|
107
107
|
TransformCTE(reinterpret_cast<duckdb_libpgquery::PGWithClause *>(stmt->withClause), select_node->cte_map);
|
108
108
|
}
|
109
|
+
if (!pivot->columns) {
|
110
|
+
// no pivot columns - not actually a pivot
|
111
|
+
select_node->from_table = std::move(source);
|
112
|
+
if (pivot->groups) {
|
113
|
+
auto groups = TransformStringList(pivot->groups);
|
114
|
+
GroupingSet set;
|
115
|
+
for (idx_t gr = 0; gr < groups.size(); gr++) {
|
116
|
+
auto &group = groups[gr];
|
117
|
+
auto colref = make_unique<ColumnRefExpression>(group);
|
118
|
+
select_node->select_list.push_back(colref->Copy());
|
119
|
+
select_node->groups.group_expressions.push_back(std::move(colref));
|
120
|
+
set.insert(gr);
|
121
|
+
}
|
122
|
+
select_node->groups.grouping_sets.push_back(std::move(set));
|
123
|
+
}
|
124
|
+
if (pivot->aggrs) {
|
125
|
+
TransformExpressionList(*pivot->aggrs, select_node->select_list);
|
126
|
+
}
|
127
|
+
return std::move(select_node);
|
128
|
+
}
|
109
129
|
|
110
130
|
// generate CREATE TYPE statements for each of the columns that do not have an IN list
|
131
|
+
auto columns = TransformPivotList(pivot->columns);
|
111
132
|
auto pivot_idx = PivotEntryCount();
|
112
133
|
for (idx_t c = 0; c < columns.size(); c++) {
|
113
134
|
auto &col = columns[c];
|
@@ -131,13 +152,17 @@ unique_ptr<QueryNode> Transformer::TransformPivotStatement(duckdb_libpgquery::PG
|
|
131
152
|
|
132
153
|
auto pivot_ref = make_unique<PivotRef>();
|
133
154
|
pivot_ref->source = std::move(source);
|
134
|
-
if (pivot->
|
135
|
-
|
155
|
+
if (pivot->unpivots) {
|
156
|
+
pivot_ref->unpivot_names = TransformStringList(pivot->unpivots);
|
136
157
|
} else {
|
137
|
-
if (
|
138
|
-
|
158
|
+
if (pivot->aggrs) {
|
159
|
+
TransformExpressionList(*pivot->aggrs, pivot_ref->aggregates);
|
160
|
+
} else {
|
161
|
+
// pivot but no aggregates specified - push a count star
|
162
|
+
vector<unique_ptr<ParsedExpression>> children;
|
163
|
+
auto function = make_unique<FunctionExpression>("count_star", std::move(children));
|
164
|
+
pivot_ref->aggregates.push_back(std::move(function));
|
139
165
|
}
|
140
|
-
pivot_ref->unpivot_names = TransformStringList(pivot->unpivots);
|
141
166
|
}
|
142
167
|
if (pivot->groups) {
|
143
168
|
pivot_ref->groups = TransformStringList(pivot->groups);
|
@@ -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 {
|