duckdb 0.7.2-dev402.0 → 0.7.2-dev586.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.
Files changed (105) hide show
  1. package/binding.gyp +9 -9
  2. package/package.json +1 -1
  3. package/src/duckdb/extension/parquet/include/parquet_timestamp.hpp +0 -1
  4. package/src/duckdb/extension/parquet/parquet-extension.cpp +1 -0
  5. package/src/duckdb/extension/parquet/parquet_timestamp.cpp +8 -6
  6. package/src/duckdb/src/catalog/catalog.cpp +13 -0
  7. package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +2 -21
  8. package/src/duckdb/src/catalog/catalog_entry/type_catalog_entry.cpp +8 -2
  9. package/src/duckdb/src/catalog/catalog_set.cpp +1 -0
  10. package/src/duckdb/src/common/arrow/arrow_appender.cpp +48 -4
  11. package/src/duckdb/src/common/arrow/arrow_converter.cpp +1 -1
  12. package/src/duckdb/src/common/field_writer.cpp +1 -0
  13. package/src/duckdb/src/common/serializer/buffered_deserializer.cpp +4 -0
  14. package/src/duckdb/src/common/serializer/buffered_file_reader.cpp +15 -2
  15. package/src/duckdb/src/common/types.cpp +136 -53
  16. package/src/duckdb/src/execution/operator/schema/physical_create_type.cpp +20 -40
  17. package/src/duckdb/src/execution/physical_plan/plan_aggregate.cpp +9 -1
  18. package/src/duckdb/src/execution/physical_plan/plan_distinct.cpp +5 -8
  19. package/src/duckdb/src/function/aggregate/distributive/bool.cpp +2 -0
  20. package/src/duckdb/src/function/aggregate/distributive/count.cpp +1 -0
  21. package/src/duckdb/src/function/aggregate/distributive/minmax.cpp +2 -0
  22. package/src/duckdb/src/function/aggregate/distributive/sum.cpp +8 -0
  23. package/src/duckdb/src/function/aggregate/holistic/quantile.cpp +15 -0
  24. package/src/duckdb/src/function/aggregate/sorted_aggregate_function.cpp +42 -11
  25. package/src/duckdb/src/function/function_binder.cpp +1 -8
  26. package/src/duckdb/src/function/scalar/date/current.cpp +0 -2
  27. package/src/duckdb/src/function/table/arrow.cpp +3 -0
  28. package/src/duckdb/src/function/table/arrow_conversion.cpp +18 -0
  29. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  30. package/src/duckdb/src/function/table_function.cpp +11 -11
  31. package/src/duckdb/src/include/duckdb/catalog/catalog.hpp +3 -0
  32. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/duck_table_entry.hpp +1 -1
  33. package/src/duckdb/src/include/duckdb/common/field_writer.hpp +12 -4
  34. package/src/duckdb/src/include/duckdb/common/{http_stats.hpp → http_state.hpp} +18 -4
  35. package/src/duckdb/src/include/duckdb/common/serializer/buffered_deserializer.hpp +4 -2
  36. package/src/duckdb/src/include/duckdb/common/serializer/buffered_file_reader.hpp +8 -2
  37. package/src/duckdb/src/include/duckdb/common/serializer.hpp +13 -0
  38. package/src/duckdb/src/include/duckdb/common/types.hpp +27 -1
  39. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_file_handle.hpp +1 -0
  40. package/src/duckdb/src/include/duckdb/execution/physical_plan_generator.hpp +0 -3
  41. package/src/duckdb/src/include/duckdb/function/aggregate_function.hpp +6 -3
  42. package/src/duckdb/src/include/duckdb/function/function_binder.hpp +3 -6
  43. package/src/duckdb/src/include/duckdb/function/table/arrow.hpp +12 -1
  44. package/src/duckdb/src/include/duckdb/function/table_function.hpp +8 -0
  45. package/src/duckdb/src/include/duckdb/main/client_data.hpp +3 -3
  46. package/src/duckdb/src/include/duckdb/main/connection_manager.hpp +2 -0
  47. package/src/duckdb/src/include/duckdb/main/extension_entries.hpp +1 -0
  48. package/src/duckdb/src/include/duckdb/optimizer/rule/list.hpp +1 -0
  49. package/src/duckdb/src/include/duckdb/optimizer/rule/ordered_aggregate_optimizer.hpp +24 -0
  50. package/src/duckdb/src/include/duckdb/parser/expression/function_expression.hpp +2 -2
  51. package/src/duckdb/src/include/duckdb/parser/expression/star_expression.hpp +2 -2
  52. package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_info.hpp +3 -0
  53. package/src/duckdb/src/include/duckdb/parser/parsed_data/alter_table_info.hpp +6 -0
  54. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +2 -0
  55. package/src/duckdb/src/include/duckdb/planner/binder.hpp +4 -3
  56. package/src/duckdb/src/include/duckdb/planner/bound_result_modifier.hpp +3 -0
  57. package/src/duckdb/src/include/duckdb/planner/expression/bound_aggregate_expression.hpp +3 -0
  58. package/src/duckdb/src/include/duckdb/planner/expression_binder/order_binder.hpp +4 -1
  59. package/src/duckdb/src/include/duckdb/planner/operator/logical_distinct.hpp +3 -0
  60. package/src/duckdb/src/include/duckdb/storage/checkpoint_manager.hpp +1 -1
  61. package/src/duckdb/src/include/duckdb/storage/meta_block_reader.hpp +7 -0
  62. package/src/duckdb/src/include/duckdb/storage/write_ahead_log.hpp +1 -1
  63. package/src/duckdb/src/main/client_context.cpp +30 -32
  64. package/src/duckdb/src/main/client_data.cpp +7 -6
  65. package/src/duckdb/src/main/database.cpp +9 -0
  66. package/src/duckdb/src/main/query_profiler.cpp +17 -15
  67. package/src/duckdb/src/optimizer/optimizer.cpp +1 -0
  68. package/src/duckdb/src/optimizer/rule/ordered_aggregate_optimizer.cpp +30 -0
  69. package/src/duckdb/src/optimizer/rule/regex_optimizations.cpp +9 -2
  70. package/src/duckdb/src/parser/expression/star_expression.cpp +6 -6
  71. package/src/duckdb/src/parser/parsed_expression_iterator.cpp +7 -1
  72. package/src/duckdb/src/parser/transform/expression/transform_columnref.cpp +17 -2
  73. package/src/duckdb/src/parser/transform/expression/transform_function.cpp +45 -40
  74. package/src/duckdb/src/parser/transform/helpers/transform_groupby.cpp +7 -0
  75. package/src/duckdb/src/parser/transform/helpers/transform_orderby.cpp +0 -7
  76. package/src/duckdb/src/parser/transform/statement/transform_rename.cpp +3 -4
  77. package/src/duckdb/src/planner/bind_context.cpp +2 -25
  78. package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +6 -4
  79. package/src/duckdb/src/planner/binder/expression/bind_lambda.cpp +3 -2
  80. package/src/duckdb/src/planner/binder/expression/bind_star_expression.cpp +176 -0
  81. package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +57 -82
  82. package/src/duckdb/src/planner/binder/query_node/plan_query_node.cpp +11 -0
  83. package/src/duckdb/src/planner/binder/statement/bind_delete.cpp +1 -1
  84. package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +2 -2
  85. package/src/duckdb/src/planner/binder/statement/bind_update.cpp +1 -1
  86. package/src/duckdb/src/planner/binder/tableref/bind_table_function.cpp +11 -1
  87. package/src/duckdb/src/planner/binder.cpp +12 -23
  88. package/src/duckdb/src/planner/bound_result_modifier.cpp +26 -0
  89. package/src/duckdb/src/planner/expression/bound_aggregate_expression.cpp +9 -2
  90. package/src/duckdb/src/planner/expression_iterator.cpp +5 -0
  91. package/src/duckdb/src/planner/logical_operator.cpp +4 -2
  92. package/src/duckdb/src/planner/logical_operator_visitor.cpp +5 -0
  93. package/src/duckdb/src/planner/operator/logical_distinct.cpp +3 -0
  94. package/src/duckdb/src/planner/planner.cpp +2 -1
  95. package/src/duckdb/src/storage/checkpoint_manager.cpp +8 -3
  96. package/src/duckdb/src/storage/meta_block_reader.cpp +22 -0
  97. package/src/duckdb/src/storage/storage_info.cpp +1 -1
  98. package/src/duckdb/src/storage/wal_replay.cpp +8 -5
  99. package/src/duckdb/src/storage/write_ahead_log.cpp +2 -2
  100. package/src/duckdb/src/transaction/commit_state.cpp +11 -7
  101. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +1 -1
  102. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +8145 -8317
  103. package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +4 -4
  104. package/src/duckdb/ub_src_optimizer_rule.cpp +2 -0
  105. package/src/duckdb/ub_src_planner_binder_expression.cpp +2 -0
@@ -96,6 +96,13 @@ void ParsedExpressionIterator::EnumerateChildren(
96
96
  }
97
97
  break;
98
98
  }
99
+ case ExpressionClass::STAR: {
100
+ auto &star_expr = (StarExpression &)expr;
101
+ if (star_expr.expr) {
102
+ callback(star_expr.expr);
103
+ }
104
+ break;
105
+ }
99
106
  case ExpressionClass::SUBQUERY: {
100
107
  auto &subquery_expr = (SubqueryExpression &)expr;
101
108
  if (subquery_expr.child) {
@@ -135,7 +142,6 @@ void ParsedExpressionIterator::EnumerateChildren(
135
142
  case ExpressionClass::COLUMN_REF:
136
143
  case ExpressionClass::CONSTANT:
137
144
  case ExpressionClass::DEFAULT:
138
- case ExpressionClass::STAR:
139
145
  case ExpressionClass::PARAMETER:
140
146
  case ExpressionClass::POSITIONAL_REFERENCE:
141
147
  // these node types have no children
@@ -1,5 +1,6 @@
1
1
  #include "duckdb/common/exception.hpp"
2
2
  #include "duckdb/parser/expression/columnref_expression.hpp"
3
+ #include "duckdb/parser/expression/function_expression.hpp"
3
4
  #include "duckdb/parser/expression/star_expression.hpp"
4
5
  #include "duckdb/parser/transformer.hpp"
5
6
 
@@ -36,13 +37,27 @@ unique_ptr<ParsedExpression> Transformer::TransformStarExpression(duckdb_libpgqu
36
37
  result->replace_list.insert(make_pair(std::move(exclude_entry), std::move(replace_expression)));
37
38
  }
38
39
  }
39
- if (star->regex) {
40
+ if (star->expr) {
41
+ D_ASSERT(star->columns);
40
42
  D_ASSERT(result->relation_name.empty());
41
43
  D_ASSERT(result->exclude_list.empty());
42
44
  D_ASSERT(result->replace_list.empty());
43
- result->regex = star->regex;
45
+ result->expr = TransformExpression(star->expr);
46
+ if (result->expr->type == ExpressionType::STAR) {
47
+ auto child_star = (StarExpression *)result->expr.get();
48
+ result->exclude_list = std::move(child_star->exclude_list);
49
+ result->replace_list = std::move(child_star->replace_list);
50
+ result->expr.reset();
51
+ } else if (result->expr->type == ExpressionType::LAMBDA) {
52
+ vector<unique_ptr<ParsedExpression>> children;
53
+ children.push_back(make_unique<StarExpression>());
54
+ children.push_back(std::move(result->expr));
55
+ auto list_filter = make_unique<FunctionExpression>("list_filter", std::move(children));
56
+ result->expr = std::move(list_filter);
57
+ }
44
58
  }
45
59
  result->columns = star->columns;
60
+ result->query_location = star->location;
46
61
  return std::move(result);
47
62
  }
48
63
 
@@ -94,6 +94,17 @@ void Transformer::TransformWindowFrame(duckdb_libpgquery::PGWindowDef *window_sp
94
94
  }
95
95
  }
96
96
 
97
+ bool Transformer::ExpressionIsEmptyStar(ParsedExpression &expr) {
98
+ if (expr.expression_class != ExpressionClass::STAR) {
99
+ return false;
100
+ }
101
+ auto &star = (StarExpression &)expr;
102
+ if (!star.columns && star.exclude_list.empty() && star.replace_list.empty()) {
103
+ return true;
104
+ }
105
+ return false;
106
+ }
107
+
97
108
  unique_ptr<ParsedExpression> Transformer::TransformFuncCall(duckdb_libpgquery::PGFuncCall *root) {
98
109
  auto name = root->funcname;
99
110
  string catalog, schema, function_name;
@@ -116,8 +127,17 @@ unique_ptr<ParsedExpression> Transformer::TransformFuncCall(duckdb_libpgquery::P
116
127
  throw InternalException("TransformFuncCall - Expected 1, 2 or 3 qualifications");
117
128
  }
118
129
 
119
- auto lowercase_name = StringUtil::Lower(function_name);
130
+ // transform children
131
+ vector<unique_ptr<ParsedExpression>> children;
132
+ if (root->args) {
133
+ TransformExpressionList(*root->args, children);
134
+ }
135
+ if (children.size() == 1 && ExpressionIsEmptyStar(*children[0]) && !root->agg_distinct && !root->agg_order) {
136
+ // COUNT(*) gets translated into COUNT()
137
+ children.clear();
138
+ }
120
139
 
140
+ auto lowercase_name = StringUtil::Lower(function_name);
121
141
  if (root->over) {
122
142
  const auto win_fun_type = WindowToExpressionType(lowercase_name);
123
143
  if (win_fun_type == ExpressionType::INVALID) {
@@ -151,39 +171,32 @@ unique_ptr<ParsedExpression> Transformer::TransformFuncCall(duckdb_libpgquery::P
151
171
  expr->filter_expr = std::move(filter_expr);
152
172
  }
153
173
 
154
- if (root->args) {
155
- vector<unique_ptr<ParsedExpression>> function_list;
156
- TransformExpressionList(*root->args, function_list);
157
-
158
- if (win_fun_type == ExpressionType::WINDOW_AGGREGATE) {
159
- for (auto &child : function_list) {
160
- expr->children.push_back(std::move(child));
174
+ if (win_fun_type == ExpressionType::WINDOW_AGGREGATE) {
175
+ expr->children = std::move(children);
176
+ } else {
177
+ if (!children.empty()) {
178
+ expr->children.push_back(std::move(children[0]));
179
+ }
180
+ if (win_fun_type == ExpressionType::WINDOW_LEAD || win_fun_type == ExpressionType::WINDOW_LAG) {
181
+ if (children.size() > 1) {
182
+ expr->offset_expr = std::move(children[1]);
161
183
  }
162
- } else {
163
- if (!function_list.empty()) {
164
- expr->children.push_back(std::move(function_list[0]));
184
+ if (children.size() > 2) {
185
+ expr->default_expr = std::move(children[2]);
186
+ }
187
+ if (children.size() > 3) {
188
+ throw ParserException("Incorrect number of parameters for function %s", lowercase_name);
189
+ }
190
+ } else if (win_fun_type == ExpressionType::WINDOW_NTH_VALUE) {
191
+ if (children.size() > 1) {
192
+ expr->children.push_back(std::move(children[1]));
165
193
  }
166
- if (win_fun_type == ExpressionType::WINDOW_LEAD || win_fun_type == ExpressionType::WINDOW_LAG) {
167
- if (function_list.size() > 1) {
168
- expr->offset_expr = std::move(function_list[1]);
169
- }
170
- if (function_list.size() > 2) {
171
- expr->default_expr = std::move(function_list[2]);
172
- }
173
- if (function_list.size() > 3) {
174
- throw ParserException("Incorrect number of parameters for function %s", lowercase_name);
175
- }
176
- } else if (win_fun_type == ExpressionType::WINDOW_NTH_VALUE) {
177
- if (function_list.size() > 1) {
178
- expr->children.push_back(std::move(function_list[1]));
179
- }
180
- if (function_list.size() > 2) {
181
- throw ParserException("Incorrect number of parameters for function %s", lowercase_name);
182
- }
183
- } else {
184
- if (function_list.size() > 1) {
185
- throw ParserException("Incorrect number of parameters for function %s", lowercase_name);
186
- }
194
+ if (children.size() > 2) {
195
+ throw ParserException("Incorrect number of parameters for function %s", lowercase_name);
196
+ }
197
+ } else {
198
+ if (children.size() > 1) {
199
+ throw ParserException("Incorrect number of parameters for function %s", lowercase_name);
187
200
  }
188
201
  }
189
202
  }
@@ -215,14 +228,6 @@ unique_ptr<ParsedExpression> Transformer::TransformFuncCall(duckdb_libpgquery::P
215
228
  throw ParserException("IGNORE NULLS is not supported for non-window functions");
216
229
  }
217
230
 
218
- // TransformExpressionList??
219
- vector<unique_ptr<ParsedExpression>> children;
220
- if (root->args != nullptr) {
221
- for (auto node = root->args->head; node != nullptr; node = node->next) {
222
- auto child_expr = TransformExpression((duckdb_libpgquery::PGNode *)node->data.ptr_value);
223
- children.push_back(std::move(child_expr));
224
- }
225
- }
226
231
  unique_ptr<ParsedExpression> filter_expr;
227
232
  if (root->agg_filter) {
228
233
  filter_expr = TransformExpression(root->agg_filter);
@@ -176,6 +176,13 @@ bool Transformer::TransformGroupBy(duckdb_libpgquery::PGList *group, SelectNode
176
176
  result.grouping_sets = std::move(new_sets);
177
177
  }
178
178
  }
179
+ if (result.group_expressions.size() == 1 && result.grouping_sets.size() == 1 &&
180
+ ExpressionIsEmptyStar(*result.group_expressions[0])) {
181
+ // GROUP BY *
182
+ result.group_expressions.clear();
183
+ result.grouping_sets.clear();
184
+ select_node.aggregate_handling = AggregateHandling::FORCE_AGGREGATES;
185
+ }
179
186
  return true;
180
187
  }
181
188
 
@@ -36,13 +36,6 @@ bool Transformer::TransformOrderBy(duckdb_libpgquery::PGList *order, vector<Orde
36
36
  throw NotImplementedException("Unimplemented order by type");
37
37
  }
38
38
  auto order_expression = TransformExpression(target);
39
- if (order_expression->GetExpressionClass() == ExpressionClass::STAR) {
40
- auto &star_expr = (StarExpression &)*order_expression;
41
- D_ASSERT(star_expr.relation_name.empty());
42
- if (star_expr.columns) {
43
- throw ParserException("COLUMNS expr is not supported in ORDER BY");
44
- }
45
- }
46
39
  result.emplace_back(type, null_order, std::move(order_expression));
47
40
  } else {
48
41
  throw NotImplementedException("ORDER BY list member type %d\n", temp->type);
@@ -6,7 +6,9 @@ namespace duckdb {
6
6
  unique_ptr<AlterStatement> Transformer::TransformRename(duckdb_libpgquery::PGNode *node) {
7
7
  auto stmt = reinterpret_cast<duckdb_libpgquery::PGRenameStmt *>(node);
8
8
  D_ASSERT(stmt);
9
- D_ASSERT(stmt->relation);
9
+ if (!stmt->relation) {
10
+ throw NotImplementedException("Altering schemas is not yet supported");
11
+ }
10
12
 
11
13
  unique_ptr<AlterInfo> info;
12
14
 
@@ -17,8 +19,6 @@ unique_ptr<AlterStatement> Transformer::TransformRename(duckdb_libpgquery::PGNod
17
19
  if (stmt->relation->relname) {
18
20
  data.name = stmt->relation->relname;
19
21
  }
20
- if (stmt->relation->schemaname) {
21
- }
22
22
  // first we check the type of ALTER
23
23
  switch (stmt->renameType) {
24
24
  case duckdb_libpgquery::PG_OBJECT_COLUMN: {
@@ -36,7 +36,6 @@ unique_ptr<AlterStatement> Transformer::TransformRename(duckdb_libpgquery::PGNod
36
36
  info = make_unique<RenameTableInfo>(std::move(data), new_name);
37
37
  break;
38
38
  }
39
-
40
39
  case duckdb_libpgquery::PG_OBJECT_VIEW: {
41
40
  // change view name
42
41
  string new_name = stmt->newname;
@@ -13,7 +13,7 @@
13
13
  #include "duckdb/planner/bound_query_node.hpp"
14
14
  #include "duckdb/planner/expression/bound_columnref_expression.hpp"
15
15
  #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp"
16
- #include "re2/re2.h"
16
+ #include "duckdb/planner/expression_binder/constant_binder.hpp"
17
17
 
18
18
  #include <algorithm>
19
19
 
@@ -319,31 +319,15 @@ bool BindContext::CheckExclusionList(StarExpression &expr, Binding *binding, con
319
319
  return false;
320
320
  }
321
321
 
322
- bool CheckRegex(const string &column_name, duckdb_re2::RE2 *regex) {
323
- if (!regex) {
324
- return true;
325
- }
326
- return RE2::PartialMatch(column_name, *regex);
327
- }
328
-
329
322
  void BindContext::GenerateAllColumnExpressions(StarExpression &expr,
330
323
  vector<unique_ptr<ParsedExpression>> &new_select_list) {
331
324
  if (bindings_list.empty()) {
332
- throw BinderException("SELECT * expression without FROM clause!");
325
+ throw BinderException("* expression without FROM clause!");
333
326
  }
334
327
  case_insensitive_set_t excluded_columns;
335
328
  if (expr.relation_name.empty()) {
336
329
  // SELECT * case
337
330
  // bind all expressions of each table in-order
338
- unique_ptr<duckdb_re2::RE2> regex;
339
- bool found_match = true;
340
- if (!expr.regex.empty()) {
341
- regex = make_unique<duckdb_re2::RE2>(expr.regex);
342
- if (!regex->error().empty()) {
343
- throw BinderException("Failed to compile regex \"%s\": %s", expr.regex, regex->error());
344
- }
345
- found_match = false;
346
- }
347
331
  unordered_set<UsingColumnSet *> handled_using_columns;
348
332
  for (auto &entry : bindings_list) {
349
333
  auto binding = entry.second;
@@ -351,10 +335,6 @@ void BindContext::GenerateAllColumnExpressions(StarExpression &expr,
351
335
  if (CheckExclusionList(expr, binding, column_name, new_select_list, excluded_columns)) {
352
336
  continue;
353
337
  }
354
- if (!CheckRegex(column_name, regex.get())) {
355
- continue;
356
- }
357
- found_match = true;
358
338
  // check if this column is a USING column
359
339
  auto using_binding = GetUsingBinding(column_name, binding->alias);
360
340
  if (using_binding) {
@@ -384,9 +364,6 @@ void BindContext::GenerateAllColumnExpressions(StarExpression &expr,
384
364
  new_select_list.push_back(make_unique<ColumnRefExpression>(column_name, binding->alias));
385
365
  }
386
366
  }
387
- if (!found_match) {
388
- throw BinderException("No matching columns found that match regex \"%s\"", expr.regex);
389
- }
390
367
  } else {
391
368
  // SELECT tbl.* case
392
369
  // SELECT struct.* case
@@ -208,8 +208,9 @@ BindResult SelectBinder::BindAggregate(FunctionExpression &aggr, AggregateFuncti
208
208
  auto bound_function = func->functions.GetFunctionByOffset(best_function);
209
209
 
210
210
  // Bind any sort columns, unless the aggregate is order-insensitive
211
- auto order_bys = make_unique<BoundOrderModifier>();
211
+ unique_ptr<BoundOrderModifier> order_bys;
212
212
  if (!aggr.order_bys->orders.empty()) {
213
+ order_bys = make_unique<BoundOrderModifier>();
213
214
  auto &config = DBConfig::GetConfig(context);
214
215
  for (auto &order : aggr.order_bys->orders) {
215
216
  auto &order_expr = (BoundExpression &)*order.expression;
@@ -222,12 +223,13 @@ BindResult SelectBinder::BindAggregate(FunctionExpression &aggr, AggregateFuncti
222
223
  }
223
224
  }
224
225
 
225
- auto aggregate = function_binder.BindAggregateFunction(
226
- bound_function, std::move(children), std::move(bound_filter),
227
- aggr.distinct ? AggregateType::DISTINCT : AggregateType::NON_DISTINCT, std::move(order_bys));
226
+ auto aggregate =
227
+ function_binder.BindAggregateFunction(bound_function, std::move(children), std::move(bound_filter),
228
+ aggr.distinct ? AggregateType::DISTINCT : AggregateType::NON_DISTINCT);
228
229
  if (aggr.export_state) {
229
230
  aggregate = ExportAggregateFunction::Bind(std::move(aggregate));
230
231
  }
232
+ aggregate->order_bys = std::move(order_bys);
231
233
 
232
234
  // check for all the aggregates if this aggregate already exists
233
235
  idx_t aggr_index;
@@ -48,7 +48,6 @@ BindResult ExpressionBinder::BindExpression(LambdaExpression &expr, idx_t depth,
48
48
 
49
49
  // positional parameters as column references
50
50
  for (idx_t i = 0; i < expr.params.size(); i++) {
51
-
52
51
  if (expr.params[i]->GetExpressionClass() != ExpressionClass::COLUMN_REF) {
53
52
  throw BinderException("Parameter must be a column name.");
54
53
  }
@@ -80,7 +79,9 @@ BindResult ExpressionBinder::BindExpression(LambdaExpression &expr, idx_t depth,
80
79
  // bind the parameter expressions
81
80
  for (idx_t i = 0; i < expr.params.size(); i++) {
82
81
  auto result = BindExpression(&expr.params[i], depth, false);
83
- D_ASSERT(!result.HasError());
82
+ if (result.HasError()) {
83
+ throw InternalException("Error during lambda binding: %s", result.error);
84
+ }
84
85
  }
85
86
 
86
87
  auto result = BindExpression(&expr.expr, depth, false);
@@ -0,0 +1,176 @@
1
+ #include "duckdb/planner/binder.hpp"
2
+ #include "duckdb/parser/expression/star_expression.hpp"
3
+ #include "duckdb/parser/expression/constant_expression.hpp"
4
+ #include "duckdb/planner/expression_binder/table_function_binder.hpp"
5
+ #include "duckdb/parser/parsed_expression_iterator.hpp"
6
+ #include "duckdb/execution/expression_executor.hpp"
7
+ #include "re2/re2.h"
8
+
9
+ namespace duckdb {
10
+
11
+ bool Binder::FindStarExpression(unique_ptr<ParsedExpression> &expr, StarExpression **star, bool is_root,
12
+ bool in_columns) {
13
+ bool has_star = false;
14
+ if (expr->GetExpressionClass() == ExpressionClass::STAR) {
15
+ auto current_star = (StarExpression *)expr.get();
16
+ if (!current_star->columns) {
17
+ if (is_root) {
18
+ *star = current_star;
19
+ return true;
20
+ }
21
+ if (!in_columns) {
22
+ throw BinderException(
23
+ "STAR expression is only allowed as the root element of an expression. Use COLUMNS(*) instead.");
24
+ }
25
+ // star expression inside a COLUMNS - convert to a constant list
26
+ if (!current_star->replace_list.empty()) {
27
+ throw BinderException(
28
+ "STAR expression with REPLACE list is only allowed as the root element of COLUMNS");
29
+ }
30
+ vector<unique_ptr<ParsedExpression>> star_list;
31
+ bind_context.GenerateAllColumnExpressions(*current_star, star_list);
32
+
33
+ vector<Value> values;
34
+ values.reserve(star_list.size());
35
+ for (auto &expr : star_list) {
36
+ values.emplace_back(expr->ToString());
37
+ }
38
+ D_ASSERT(!values.empty());
39
+
40
+ expr = make_unique<ConstantExpression>(Value::LIST(LogicalType::VARCHAR, values));
41
+ return true;
42
+ }
43
+ if (in_columns) {
44
+ throw BinderException("COLUMNS expression is not allowed inside another COLUMNS expression");
45
+ }
46
+ in_columns = true;
47
+ if (*star) {
48
+ // we can have multiple
49
+ if (!StarExpression::Equal(*star, current_star)) {
50
+ throw BinderException(
51
+ FormatError(*expr, "Multiple different STAR/COLUMNS in the same expression are not supported"));
52
+ }
53
+ return true;
54
+ }
55
+ *star = current_star;
56
+ has_star = true;
57
+ }
58
+ ParsedExpressionIterator::EnumerateChildren(*expr, [&](unique_ptr<ParsedExpression> &child_expr) {
59
+ if (FindStarExpression(child_expr, star, false, in_columns)) {
60
+ has_star = true;
61
+ }
62
+ });
63
+ return has_star;
64
+ }
65
+
66
+ void Binder::ReplaceStarExpression(unique_ptr<ParsedExpression> &expr, unique_ptr<ParsedExpression> &replacement) {
67
+ D_ASSERT(expr);
68
+ if (expr->GetExpressionClass() == ExpressionClass::STAR) {
69
+ D_ASSERT(replacement);
70
+ expr = replacement->Copy();
71
+ return;
72
+ }
73
+ ParsedExpressionIterator::EnumerateChildren(
74
+ *expr, [&](unique_ptr<ParsedExpression> &child_expr) { ReplaceStarExpression(child_expr, replacement); });
75
+ }
76
+
77
+ void Binder::ExpandStarExpression(unique_ptr<ParsedExpression> expr,
78
+ vector<unique_ptr<ParsedExpression>> &new_select_list) {
79
+ StarExpression *star = nullptr;
80
+ if (!FindStarExpression(expr, &star, true, false)) {
81
+ // no star expression: add it as-is
82
+ D_ASSERT(!star);
83
+ new_select_list.push_back(std::move(expr));
84
+ return;
85
+ }
86
+ D_ASSERT(star);
87
+ vector<unique_ptr<ParsedExpression>> star_list;
88
+ // we have star expressions! expand the list of star expressions
89
+ bind_context.GenerateAllColumnExpressions(*star, star_list);
90
+
91
+ if (star->expr) {
92
+ // COLUMNS with an expression
93
+ // two options:
94
+ // VARCHAR parameter <- this is a regular expression
95
+ // LIST of VARCHAR parameters <- this is a set of columns
96
+ TableFunctionBinder binder(*this, context);
97
+ auto child = star->expr->Copy();
98
+ auto result = binder.Bind(child);
99
+ if (!result->IsFoldable()) {
100
+ // cannot resolve parameters here
101
+ if (star->expr->HasParameter()) {
102
+ throw ParameterNotResolvedException();
103
+ } else {
104
+ throw BinderException("Unsupported expression in COLUMNS");
105
+ }
106
+ }
107
+ auto val = ExpressionExecutor::EvaluateScalar(context, *result);
108
+ if (val.type().id() == LogicalTypeId::VARCHAR) {
109
+ // regex
110
+ if (val.IsNull()) {
111
+ throw BinderException("COLUMNS does not support NULL as regex argument");
112
+ }
113
+ auto &regex_str = StringValue::Get(val);
114
+ duckdb_re2::RE2 regex(regex_str);
115
+ if (!regex.error().empty()) {
116
+ auto err = StringUtil::Format("Failed to compile regex \"%s\": %s", regex_str, regex.error());
117
+ throw BinderException(FormatError(*star, err));
118
+ }
119
+ vector<unique_ptr<ParsedExpression>> new_list;
120
+ for (idx_t i = 0; i < star_list.size(); i++) {
121
+ auto &colref = (ColumnRefExpression &)*star_list[i];
122
+ if (!RE2::PartialMatch(colref.GetColumnName(), regex)) {
123
+ continue;
124
+ }
125
+ new_list.push_back(std::move(star_list[i]));
126
+ }
127
+ if (new_list.empty()) {
128
+ auto err = StringUtil::Format("No matching columns found that match regex \"%s\"", regex_str);
129
+ throw BinderException(FormatError(*star, err));
130
+ }
131
+ star_list = std::move(new_list);
132
+ } else if (val.type().id() == LogicalTypeId::LIST &&
133
+ ListType::GetChildType(val.type()).id() == LogicalTypeId::VARCHAR) {
134
+ // list of varchar columns
135
+ if (val.IsNull() || ListValue::GetChildren(val).empty()) {
136
+ auto err =
137
+ StringUtil::Format("Star expression \"%s\" resulted in an empty set of columns", star->ToString());
138
+ throw BinderException(FormatError(*star, err));
139
+ }
140
+ auto &children = ListValue::GetChildren(val);
141
+ vector<unique_ptr<ParsedExpression>> new_list;
142
+ for (auto &child : children) {
143
+ auto qname = QualifiedName::Parse(StringValue::Get(child));
144
+ vector<string> names;
145
+ if (!qname.catalog.empty()) {
146
+ names.push_back(qname.catalog);
147
+ }
148
+ if (!qname.schema.empty()) {
149
+ names.push_back(qname.schema);
150
+ }
151
+ names.push_back(qname.name);
152
+ new_list.push_back(make_unique<ColumnRefExpression>(std::move(names)));
153
+ }
154
+ star_list = std::move(new_list);
155
+ } else {
156
+ throw BinderException(FormatError(
157
+ *star, "COLUMNS expects either a VARCHAR argument (regex) or a LIST of VARCHAR (list of columns)"));
158
+ }
159
+ }
160
+
161
+ // now perform the replacement
162
+ for (idx_t i = 0; i < star_list.size(); i++) {
163
+ auto new_expr = expr->Copy();
164
+ ReplaceStarExpression(new_expr, star_list[i]);
165
+ new_select_list.push_back(std::move(new_expr));
166
+ }
167
+ }
168
+
169
+ void Binder::ExpandStarExpressions(vector<unique_ptr<ParsedExpression>> &select_list,
170
+ vector<unique_ptr<ParsedExpression>> &new_select_list) {
171
+ for (auto &select_element : select_list) {
172
+ ExpandStarExpression(std::move(select_element), new_select_list);
173
+ }
174
+ }
175
+
176
+ } // namespace duckdb