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
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
|
}
|
@@ -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-dev899"
|
3
3
|
#endif
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
5
|
+
#define DUCKDB_SOURCE_ID "88b1bfa74d"
|
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);
|
@@ -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;
|
@@ -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);
|