duckdb 0.7.2-dev586.0 → 0.7.2-dev654.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 (70) hide show
  1. package/package.json +1 -1
  2. package/src/duckdb/extension/icu/icu-table-range.cpp +7 -7
  3. package/src/duckdb/extension/parquet/parquet_reader.cpp +1 -1
  4. package/src/duckdb/src/catalog/catalog_entry/table_catalog_entry.cpp +3 -3
  5. package/src/duckdb/src/catalog/dependency_list.cpp +12 -0
  6. package/src/duckdb/src/common/string_util.cpp +4 -1
  7. package/src/duckdb/src/common/types/blob.cpp +1 -1
  8. package/src/duckdb/src/common/types/chunk_collection.cpp +2 -2
  9. package/src/duckdb/src/common/types/data_chunk.cpp +1 -1
  10. package/src/duckdb/src/common/types/value.cpp +8 -8
  11. package/src/duckdb/src/common/types.cpp +11 -11
  12. package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +15 -3
  13. package/src/duckdb/src/execution/operator/helper/physical_vacuum.cpp +3 -0
  14. package/src/duckdb/src/execution/operator/join/physical_iejoin.cpp +2 -2
  15. package/src/duckdb/src/execution/operator/join/physical_piecewise_merge_join.cpp +6 -11
  16. package/src/duckdb/src/execution/operator/join/physical_range_join.cpp +1 -1
  17. package/src/duckdb/src/execution/operator/persistent/physical_copy_to_file.cpp +2 -2
  18. package/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp +3 -0
  19. package/src/duckdb/src/function/aggregate/distributive/bitstring_agg.cpp +22 -7
  20. package/src/duckdb/src/function/aggregate/distributive/first.cpp +1 -0
  21. package/src/duckdb/src/function/aggregate/holistic/approximate_quantile.cpp +5 -2
  22. package/src/duckdb/src/function/aggregate/holistic/quantile.cpp +1 -1
  23. package/src/duckdb/src/function/aggregate/nested/list.cpp +8 -8
  24. package/src/duckdb/src/function/cast/struct_cast.cpp +1 -1
  25. package/src/duckdb/src/function/scalar/date/date_part.cpp +1 -1
  26. package/src/duckdb/src/function/scalar/list/list_concat.cpp +5 -4
  27. package/src/duckdb/src/function/scalar/list/list_lambdas.cpp +3 -3
  28. package/src/duckdb/src/function/scalar/list/list_value.cpp +1 -1
  29. package/src/duckdb/src/function/scalar/map/map_entries.cpp +1 -1
  30. package/src/duckdb/src/function/scalar/struct/struct_insert.cpp +1 -1
  31. package/src/duckdb/src/function/scalar/struct/struct_pack.cpp +1 -1
  32. package/src/duckdb/src/function/table/arrow.cpp +2 -2
  33. package/src/duckdb/src/function/table/checkpoint.cpp +5 -1
  34. package/src/duckdb/src/function/table/system/duckdb_constraints.cpp +2 -2
  35. package/src/duckdb/src/function/table/system/test_all_types.cpp +2 -2
  36. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  37. package/src/duckdb/src/include/duckdb/catalog/dependency_list.hpp +3 -0
  38. package/src/duckdb/src/include/duckdb/common/types/value.hpp +3 -3
  39. package/src/duckdb/src/include/duckdb/common/types.hpp +3 -3
  40. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +3 -0
  41. package/src/duckdb/src/include/duckdb/storage/statistics/distinct_statistics.hpp +2 -0
  42. package/src/duckdb/src/include/duckdb/storage/table/update_segment.hpp +0 -1
  43. package/src/duckdb/src/main/config.cpp +4 -0
  44. package/src/duckdb/src/optimizer/join_order/cardinality_estimator.cpp +3 -4
  45. package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +5 -3
  46. package/src/duckdb/src/optimizer/pushdown/pushdown_aggregate.cpp +33 -5
  47. package/src/duckdb/src/optimizer/rule/move_constants.cpp +8 -2
  48. package/src/duckdb/src/optimizer/unnest_rewriter.cpp +2 -2
  49. package/src/duckdb/src/parser/expression/conjunction_expression.cpp +2 -0
  50. package/src/duckdb/src/parser/transform/expression/transform_function.cpp +17 -1
  51. package/src/duckdb/src/parser/transform/helpers/transform_typename.cpp +3 -2
  52. package/src/duckdb/src/parser/transform/statement/transform_select_node.cpp +1 -2
  53. package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +1 -1
  54. package/src/duckdb/src/planner/binder/expression/bind_columnref_expression.cpp +4 -3
  55. package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +25 -13
  56. package/src/duckdb/src/planner/binder/statement/bind_copy.cpp +2 -2
  57. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +2 -1
  58. package/src/duckdb/src/planner/binder/statement/bind_create_table.cpp +9 -1
  59. package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +10 -6
  60. package/src/duckdb/src/planner/binder/statement/bind_update.cpp +3 -1
  61. package/src/duckdb/src/planner/binder/tableref/bind_pivot.cpp +1 -0
  62. package/src/duckdb/src/planner/binder/tableref/plan_cteref.cpp +1 -0
  63. package/src/duckdb/src/planner/expression_binder/having_binder.cpp +3 -0
  64. package/src/duckdb/src/planner/expression_binder.cpp +1 -1
  65. package/src/duckdb/src/storage/statistics/column_statistics.cpp +1 -2
  66. package/src/duckdb/src/storage/statistics/distinct_statistics.cpp +4 -0
  67. package/src/duckdb/src/storage/statistics/list_stats.cpp +6 -2
  68. package/src/duckdb/src/storage/statistics/struct_stats.cpp +3 -1
  69. package/src/duckdb/src/storage/table/row_group.cpp +6 -1
  70. package/src/duckdb/src/storage/table/update_segment.cpp +11 -7
@@ -74,7 +74,7 @@ static unique_ptr<FunctionData> StructInsertBind(ClientContext &context, ScalarF
74
74
  }
75
75
 
76
76
  // this is more for completeness reasons
77
- bound_function.return_type = LogicalType::STRUCT(std::move(new_struct_children));
77
+ bound_function.return_type = LogicalType::STRUCT(new_struct_children);
78
78
  return make_unique<VariableReturnBindData>(bound_function.return_type);
79
79
  }
80
80
 
@@ -54,7 +54,7 @@ static unique_ptr<FunctionData> StructPackBind(ClientContext &context, ScalarFun
54
54
  }
55
55
 
56
56
  // this is more for completeness reasons
57
- bound_function.return_type = LogicalType::STRUCT(std::move(struct_children));
57
+ bound_function.return_type = LogicalType::STRUCT(struct_children);
58
58
  return make_unique<VariableReturnBindData>(bound_function.return_type);
59
59
  }
60
60
 
@@ -117,14 +117,14 @@ LogicalType ArrowTableFunction::GetArrowLogicalType(
117
117
  idx_t fixed_size = std::stoi(parameters);
118
118
  arrow_convert_data[col_idx]->variable_sz_type.emplace_back(ArrowVariableSizeType::FIXED_SIZE, fixed_size);
119
119
  auto child_type = GetArrowLogicalType(*schema.children[0], arrow_convert_data, col_idx);
120
- return LogicalType::LIST(std::move(child_type));
120
+ return LogicalType::LIST(child_type);
121
121
  } else if (format == "+s") {
122
122
  child_list_t<LogicalType> child_types;
123
123
  for (idx_t type_idx = 0; type_idx < (idx_t)schema.n_children; type_idx++) {
124
124
  auto child_type = GetArrowLogicalType(*schema.children[type_idx], arrow_convert_data, col_idx);
125
125
  child_types.push_back({schema.children[type_idx]->name, child_type});
126
126
  }
127
- return LogicalType::STRUCT(std::move(child_types));
127
+ return LogicalType::STRUCT(child_types);
128
128
 
129
129
  } else if (format == "+m") {
130
130
  arrow_convert_data[col_idx]->variable_sz_type.emplace_back(ArrowVariableSizeType::NORMAL, 0);
@@ -32,7 +32,11 @@ static unique_ptr<FunctionData> CheckpointBind(ClientContext &context, TableFunc
32
32
  AttachedDatabase *db;
33
33
  auto &db_manager = DatabaseManager::Get(context);
34
34
  if (!input.inputs.empty()) {
35
- db = db_manager.GetDatabase(context, StringValue::Get(input.inputs[0]));
35
+ auto &db_name = StringValue::Get(input.inputs[0]);
36
+ db = db_manager.GetDatabase(context, db_name);
37
+ if (!db) {
38
+ throw BinderException("Database \"%s\" not found", db_name);
39
+ }
36
40
  } else {
37
41
  db = db_manager.GetDatabase(context, DatabaseManager::GetDefaultDatabase(context));
38
42
  }
@@ -204,8 +204,8 @@ void DuckDBConstraintsFunction(ClientContext &context, TableFunctionInput &data_
204
204
  const auto &bound_foreign_key = (const BoundForeignKeyConstraint &)bound_constraint;
205
205
  const auto &info = bound_foreign_key.info;
206
206
  // find the other table
207
- auto table_entry =
208
- Catalog::GetEntry<TableCatalogEntry>(context, INVALID_CATALOG, info.schema, info.table, true);
207
+ auto table_entry = Catalog::GetEntry<TableCatalogEntry>(context, table.catalog->GetName(),
208
+ info.schema, info.table, true);
209
209
  if (!table_entry) {
210
210
  throw InternalException("dukdb_constraints: entry %s.%s referenced in foreign key not found",
211
211
  info.schema, info.table);
@@ -138,7 +138,7 @@ vector<TestType> TestAllTypesFun::GetTestTypes() {
138
138
  child_list_t<LogicalType> struct_type_list;
139
139
  struct_type_list.push_back(make_pair("a", LogicalType::INTEGER));
140
140
  struct_type_list.push_back(make_pair("b", LogicalType::VARCHAR));
141
- auto struct_type = LogicalType::STRUCT(std::move(struct_type_list));
141
+ auto struct_type = LogicalType::STRUCT(struct_type_list);
142
142
 
143
143
  child_list_t<Value> min_struct_list;
144
144
  min_struct_list.push_back(make_pair("a", Value(LogicalType::INTEGER)));
@@ -156,7 +156,7 @@ vector<TestType> TestAllTypesFun::GetTestTypes() {
156
156
  child_list_t<LogicalType> struct_list_type_list;
157
157
  struct_list_type_list.push_back(make_pair("a", int_list_type));
158
158
  struct_list_type_list.push_back(make_pair("b", varchar_list_type));
159
- auto struct_list_type = LogicalType::STRUCT(std::move(struct_list_type_list));
159
+ auto struct_list_type = LogicalType::STRUCT(struct_list_type_list);
160
160
 
161
161
  child_list_t<Value> min_struct_vl_list;
162
162
  min_struct_vl_list.push_back(make_pair("a", Value(int_list_type)));
@@ -1,8 +1,8 @@
1
1
  #ifndef DUCKDB_VERSION
2
- #define DUCKDB_VERSION "0.7.2-dev586"
2
+ #define DUCKDB_VERSION "0.7.2-dev654"
3
3
  #endif
4
4
  #ifndef DUCKDB_SOURCE_ID
5
- #define DUCKDB_SOURCE_ID "23ee8b036a"
5
+ #define DUCKDB_SOURCE_ID "6525767cf1"
6
6
  #endif
7
7
  #include "duckdb/function/table/system_functions.hpp"
8
8
  #include "duckdb/main/database.hpp"
@@ -12,6 +12,7 @@
12
12
  #include "duckdb/common/unordered_set.hpp"
13
13
 
14
14
  namespace duckdb {
15
+ class Catalog;
15
16
  class CatalogEntry;
16
17
 
17
18
  //! The DependencyList
@@ -21,6 +22,8 @@ class DependencyList {
21
22
  public:
22
23
  DUCKDB_API void AddDependency(CatalogEntry *entry);
23
24
 
25
+ DUCKDB_API void VerifyDependencies(Catalog *catalog, const string &name);
26
+
24
27
  private:
25
28
  unordered_set<CatalogEntry *> set;
26
29
  };
@@ -151,11 +151,11 @@ public:
151
151
  //! Cannot be called with an empty list, use either EMPTYLIST or LIST with a type instead
152
152
  DUCKDB_API static Value LIST(vector<Value> values);
153
153
  //! Create a list value with the given entries
154
- DUCKDB_API static Value LIST(LogicalType child_type, vector<Value> values);
154
+ DUCKDB_API static Value LIST(const LogicalType &child_type, vector<Value> values);
155
155
  //! Create an empty list with the specified child-type
156
- DUCKDB_API static Value EMPTYLIST(LogicalType child_type);
156
+ DUCKDB_API static Value EMPTYLIST(const LogicalType &child_type);
157
157
  //! Create a map value with the given entries
158
- DUCKDB_API static Value MAP(LogicalType child_type, vector<Value> values);
158
+ DUCKDB_API static Value MAP(const LogicalType &child_type, vector<Value> values);
159
159
  //! Create a union value from a selected value and a tag from a set of alternatives.
160
160
  DUCKDB_API static Value UNION(child_list_t<LogicalType> members, uint8_t tag, Value value);
161
161
 
@@ -427,10 +427,10 @@ public:
427
427
  // explicitly allowing these functions to be capitalized to be in-line with the remaining functions
428
428
  DUCKDB_API static LogicalType DECIMAL(int width, int scale); // NOLINT
429
429
  DUCKDB_API static LogicalType VARCHAR_COLLATION(string collation); // NOLINT
430
- DUCKDB_API static LogicalType LIST( LogicalType child); // NOLINT
431
- DUCKDB_API static LogicalType STRUCT( child_list_t<LogicalType> children); // NOLINT
430
+ DUCKDB_API static LogicalType LIST(const LogicalType &child); // NOLINT
431
+ DUCKDB_API static LogicalType STRUCT(const child_list_t<LogicalType> &children); // NOLINT
432
432
  DUCKDB_API static LogicalType AGGREGATE_STATE(aggregate_state_t state_type); // NOLINT
433
- DUCKDB_API static LogicalType MAP(LogicalType child); // NOLINT
433
+ DUCKDB_API static LogicalType MAP(const LogicalType &child); // NOLINT
434
434
  DUCKDB_API static LogicalType MAP( child_list_t<LogicalType> children); // NOLINT
435
435
  DUCKDB_API static LogicalType MAP(LogicalType key, LogicalType value); // NOLINT
436
436
  DUCKDB_API static LogicalType UNION( child_list_t<LogicalType> members); // NOLINT
@@ -71,8 +71,11 @@ private:
71
71
  vector<unique_ptr<CreatePivotEntry>> pivot_entries;
72
72
  //! Sets of stored CTEs, if any
73
73
  vector<CommonTableExpressionMap *> stored_cte_map;
74
+ //! Whether or not we are currently binding a window definition
75
+ bool in_window_definition = false;
74
76
 
75
77
  void Clear();
78
+ bool InWindowDefinition();
76
79
 
77
80
  void SetParamCount(idx_t new_count) {
78
81
  if (parent) {
@@ -46,6 +46,8 @@ public:
46
46
  string ToString() const;
47
47
  idx_t GetCount() const;
48
48
 
49
+ static bool TypeIsSupported(const LogicalType &type);
50
+
49
51
  private:
50
52
  //! For distinct statistics we sample the input to speed up insertions
51
53
  static constexpr const double SAMPLE_RATE = 0.1;
@@ -34,7 +34,6 @@ public:
34
34
  bool HasUncommittedUpdates(idx_t vector_index);
35
35
  bool HasUpdates(idx_t vector_index) const;
36
36
  bool HasUpdates(idx_t start_row_idx, idx_t end_row_idx);
37
- void ClearUpdates();
38
37
 
39
38
  void FetchUpdates(TransactionData transaction, idx_t vector_index, Vector &result);
40
39
  void FetchCommitted(idx_t vector_index, Vector &result);
@@ -270,6 +270,7 @@ idx_t CGroupBandwidthQuota(idx_t physical_cores, FileSystem &fs) {
270
270
  }
271
271
 
272
272
  idx_t GetSystemMaxThreadsInternal(FileSystem &fs) {
273
+ #ifndef DUCKDB_NO_THREADS
273
274
  idx_t physical_cores = std::thread::hardware_concurrency();
274
275
  #ifdef __linux__
275
276
  auto cores_available_per_period = CGroupBandwidthQuota(physical_cores, fs);
@@ -277,6 +278,9 @@ idx_t GetSystemMaxThreadsInternal(FileSystem &fs) {
277
278
  #else
278
279
  return physical_cores;
279
280
  #endif
281
+ #else
282
+ return 1;
283
+ #endif
280
284
  }
281
285
 
282
286
  void DBConfig::SetDefaultMaxThreads() {
@@ -39,8 +39,7 @@ void CardinalityEstimator::AddRelationTdom(FilterInfo *filter_info) {
39
39
  }
40
40
  }
41
41
  auto key = ColumnBinding(filter_info->left_binding.table_index, filter_info->left_binding.column_index);
42
- column_binding_set_t tmp({key});
43
- relations_to_tdoms.emplace_back(RelationsToTDom(tmp));
42
+ relations_to_tdoms.emplace_back(column_binding_set_t({key}));
44
43
  }
45
44
 
46
45
  bool CardinalityEstimator::SingleColumnFilter(FilterInfo *filter_info) {
@@ -93,7 +92,7 @@ void CardinalityEstimator::AddToEquivalenceSets(FilterInfo *filter_info, vector<
93
92
  column_binding_set_t tmp;
94
93
  tmp.insert(filter_info->left_binding);
95
94
  tmp.insert(filter_info->right_binding);
96
- relations_to_tdoms.emplace_back(RelationsToTDom(tmp));
95
+ relations_to_tdoms.emplace_back(tmp);
97
96
  relations_to_tdoms.back().filters.push_back(filter_info);
98
97
  }
99
98
  }
@@ -259,7 +258,7 @@ double CardinalityEstimator::EstimateCardinalityWithSet(JoinRelationSet *new_set
259
258
  // connection to any subgraph in subgraphs. Add a new subgraph, and maybe later there will be
260
259
  // a connection.
261
260
  if (!found_match) {
262
- subgraphs.emplace_back(Subgraph2Denominator());
261
+ subgraphs.emplace_back();
263
262
  auto subgraph = &subgraphs.back();
264
263
  subgraph->relations.insert(filter->left_binding.table_index);
265
264
  subgraph->relations.insert(filter->right_binding.table_index);
@@ -156,7 +156,7 @@ bool JoinOrderOptimizer::ExtractJoinRelations(LogicalOperator &input_op, vector<
156
156
  vector<column_binding_map_t<ColumnBinding>> child_binding_maps;
157
157
  idx_t child_bindings_it = 0;
158
158
  for (auto &child : op->children) {
159
- child_binding_maps.emplace_back(column_binding_map_t<ColumnBinding>());
159
+ child_binding_maps.emplace_back();
160
160
  JoinOrderOptimizer optimizer(context);
161
161
  child = optimizer.Optimize(std::move(child));
162
162
  // save the relation bindings from the optimized child. These later all get added to the
@@ -230,7 +230,7 @@ bool JoinOrderOptimizer::ExtractJoinRelations(LogicalOperator &input_op, vector<
230
230
  auto relation_id = relations.size();
231
231
  // push one child column binding map back.
232
232
  vector<column_binding_map_t<ColumnBinding>> child_binding_maps;
233
- child_binding_maps.emplace_back(column_binding_map_t<ColumnBinding>());
233
+ child_binding_maps.emplace_back();
234
234
  optimizer.cardinality_estimator.CopyRelationMap(child_binding_maps.at(0));
235
235
  // This logical projection may sit on top of a logical comparison join that has been pushed down
236
236
  // we want to copy the binding info of both tables
@@ -882,9 +882,11 @@ unique_ptr<LogicalOperator> JoinOrderOptimizer::RewritePlan(unique_ptr<LogicalOp
882
882
 
883
883
  // first we will extract all relations from the main plan
884
884
  vector<unique_ptr<LogicalOperator>> extracted_relations;
885
+ extracted_relations.reserve(relations.size());
885
886
  for (auto &relation : relations) {
886
887
  extracted_relations.push_back(ExtractJoinRelation(*relation));
887
888
  }
889
+
888
890
  // now we generate the actual joins
889
891
  auto join_tree = GenerateJoins(extracted_relations, node);
890
892
  // perform the final pushdown of remaining filters
@@ -1012,7 +1014,7 @@ unique_ptr<LogicalOperator> JoinOrderOptimizer::Optimize(unique_ptr<LogicalOpera
1012
1014
  for (idx_t i = 0; i < relations.size(); i++) {
1013
1015
  auto &rel = *relations[i];
1014
1016
  auto node = set_manager.GetJoinRelation(i);
1015
- nodes_ops.emplace_back(NodeOp(make_unique<JoinNode>(node, 0), rel.op));
1017
+ nodes_ops.emplace_back(make_unique<JoinNode>(node, 0), rel.op);
1016
1018
  }
1017
1019
 
1018
1020
  cardinality_estimator.InitCardinalityEstimatorProps(&nodes_ops, &filter_infos);
@@ -9,6 +9,14 @@ namespace duckdb {
9
9
 
10
10
  using Filter = FilterPushdown::Filter;
11
11
 
12
+ static void ExtractFilterBindings(Expression &expr, vector<ColumnBinding> &bindings) {
13
+ if (expr.type == ExpressionType::BOUND_COLUMN_REF) {
14
+ auto &colref = (BoundColumnRefExpression &)expr;
15
+ bindings.push_back(colref.binding);
16
+ }
17
+ ExpressionIterator::EnumerateChildren(expr, [&](Expression &child) { ExtractFilterBindings(child, bindings); });
18
+ }
19
+
12
20
  static unique_ptr<Expression> ReplaceGroupBindings(LogicalAggregate &proj, unique_ptr<Expression> expr) {
13
21
  if (expr->type == ExpressionType::BOUND_COLUMN_REF) {
14
22
  auto &colref = (BoundColumnRefExpression &)*expr;
@@ -40,14 +48,34 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownAggregate(unique_ptr<Logical
40
48
  // filter on GROUPINGS function: cannot pushdown
41
49
  continue;
42
50
  }
43
- // if there are any empty grouping sets, we cannot push down filters
44
- bool has_empty_grouping_sets = false;
51
+ // no aggregate! we are filtering on a group
52
+ // we can only push this down if the filter is in all grouping sets
53
+ vector<ColumnBinding> bindings;
54
+ ExtractFilterBindings(*f.filter, bindings);
55
+
56
+ bool can_pushdown_filter = true;
57
+ if (aggr.grouping_sets.empty()) {
58
+ // empty grouping set - we cannot pushdown the filter
59
+ can_pushdown_filter = false;
60
+ }
45
61
  for (auto &grp : aggr.grouping_sets) {
46
- if (grp.empty()) {
47
- has_empty_grouping_sets = true;
62
+ // check for each of the grouping sets if they contain all groups
63
+ if (bindings.empty()) {
64
+ // we can never push down empty grouping sets
65
+ can_pushdown_filter = false;
66
+ break;
67
+ }
68
+ for (auto &binding : bindings) {
69
+ if (grp.find(binding.column_index) == grp.end()) {
70
+ can_pushdown_filter = false;
71
+ break;
72
+ }
73
+ }
74
+ if (!can_pushdown_filter) {
75
+ break;
48
76
  }
49
77
  }
50
- if (has_empty_grouping_sets) {
78
+ if (!can_pushdown_filter) {
51
79
  continue;
52
80
  }
53
81
  // no aggregate! we can push this down
@@ -73,7 +73,10 @@ unique_ptr<Expression> MoveConstantsRule::Apply(LogicalOperator &op, vector<Expr
73
73
  }
74
74
  auto result_value = Value::HUGEINT(outer_value);
75
75
  if (!result_value.DefaultTryCastAs(constant_type)) {
76
- // if the cast is not possible then the comparison is not possible
76
+ // if the cast is not possible then an equality comparison is not possible
77
+ if (comparison->type != ExpressionType::COMPARE_EQUAL) {
78
+ return nullptr;
79
+ }
77
80
  return ExpressionRewriter::ConstantOrNull(std::move(arithmetic->children[arithmetic_child_index]),
78
81
  Value::BOOLEAN(false));
79
82
  }
@@ -86,7 +89,10 @@ unique_ptr<Expression> MoveConstantsRule::Apply(LogicalOperator &op, vector<Expr
86
89
  }
87
90
  auto result_value = Value::HUGEINT(inner_value);
88
91
  if (!result_value.DefaultTryCastAs(constant_type)) {
89
- // if the cast is not possible then the comparison is not possible
92
+ // if the cast is not possible then an equality comparison is not possible
93
+ if (comparison->type != ExpressionType::COMPARE_EQUAL) {
94
+ return nullptr;
95
+ }
90
96
  return ExpressionRewriter::ConstantOrNull(std::move(arithmetic->children[arithmetic_child_index]),
91
97
  Value::BOOLEAN(false));
92
98
  }
@@ -261,7 +261,7 @@ void UnnestRewriter::UpdateBoundUnnestBindings(UnnestRewriterPlanUpdater &update
261
261
  for (idx_t child_col_idx = 0; child_col_idx < unnest_child_cols.size(); child_col_idx++) {
262
262
  if (delim_columns[delim_col_idx].table_index == unnest_child_cols[child_col_idx].table_index) {
263
263
  ColumnBinding old_binding(overwritten_tbl_idx, DConstants::INVALID_INDEX);
264
- updater.replace_bindings.emplace_back(ReplaceBinding(old_binding, delim_columns[delim_col_idx]));
264
+ updater.replace_bindings.emplace_back(old_binding, delim_columns[delim_col_idx]);
265
265
  break;
266
266
  }
267
267
  }
@@ -301,7 +301,7 @@ void UnnestRewriter::GetLHSExpressions(LogicalOperator &op) {
301
301
  }
302
302
 
303
303
  for (idx_t i = 0; i < op.types.size(); i++) {
304
- lhs_bindings.emplace_back(LHSBinding(col_bindings[i], op.types[i]));
304
+ lhs_bindings.emplace_back(col_bindings[i], op.types[i]);
305
305
  if (set_alias) {
306
306
  auto &proj = (LogicalProjection &)op;
307
307
  lhs_bindings.back().alias = proj.expressions[i]->alias;
@@ -45,9 +45,11 @@ bool ConjunctionExpression::Equal(const ConjunctionExpression *a, const Conjunct
45
45
 
46
46
  unique_ptr<ParsedExpression> ConjunctionExpression::Copy() const {
47
47
  vector<unique_ptr<ParsedExpression>> copy_children;
48
+ copy_children.reserve(children.size());
48
49
  for (auto &expr : children) {
49
50
  copy_children.push_back(expr->Copy());
50
51
  }
52
+
51
53
  auto copy = make_unique<ConjunctionExpression>(type, std::move(copy_children));
52
54
  copy->CopyProperties(*this);
53
55
  return std::move(copy);
@@ -24,7 +24,7 @@ static ExpressionType WindowToExpressionType(string &fun_name) {
24
24
  return ExpressionType::WINDOW_FIRST_VALUE;
25
25
  } else if (fun_name == "last_value" || fun_name == "last") {
26
26
  return ExpressionType::WINDOW_LAST_VALUE;
27
- } else if (fun_name == "nth_value" || fun_name == "last") {
27
+ } else if (fun_name == "nth_value") {
28
28
  return ExpressionType::WINDOW_NTH_VALUE;
29
29
  } else if (fun_name == "cume_dist") {
30
30
  return ExpressionType::WINDOW_CUME_DIST;
@@ -105,6 +105,16 @@ bool Transformer::ExpressionIsEmptyStar(ParsedExpression &expr) {
105
105
  return false;
106
106
  }
107
107
 
108
+ bool Transformer::InWindowDefinition() {
109
+ if (in_window_definition) {
110
+ return true;
111
+ }
112
+ if (parent) {
113
+ return parent->InWindowDefinition();
114
+ }
115
+ return false;
116
+ }
117
+
108
118
  unique_ptr<ParsedExpression> Transformer::TransformFuncCall(duckdb_libpgquery::PGFuncCall *root) {
109
119
  auto name = root->funcname;
110
120
  string catalog, schema, function_name;
@@ -139,6 +149,10 @@ unique_ptr<ParsedExpression> Transformer::TransformFuncCall(duckdb_libpgquery::P
139
149
 
140
150
  auto lowercase_name = StringUtil::Lower(function_name);
141
151
  if (root->over) {
152
+ if (InWindowDefinition()) {
153
+ throw ParserException("window functions are not allowed in window definitions");
154
+ }
155
+
142
156
  const auto win_fun_type = WindowToExpressionType(lowercase_name);
143
157
  if (win_fun_type == ExpressionType::INVALID) {
144
158
  throw InternalException("Unknown/unsupported window function");
@@ -218,8 +232,10 @@ unique_ptr<ParsedExpression> Transformer::TransformFuncCall(duckdb_libpgquery::P
218
232
  window_ref = it->second;
219
233
  D_ASSERT(window_ref);
220
234
  }
235
+ in_window_definition = true;
221
236
  TransformWindowDef(window_ref, expr.get());
222
237
  TransformWindowFrame(window_spec, expr.get());
238
+ in_window_definition = false;
223
239
  expr->query_location = root->location;
224
240
  return std::move(expr);
225
241
  }
@@ -52,7 +52,8 @@ LogicalType Transformer::TransformTypeName(duckdb_libpgquery::PGTypeName *type_n
52
52
  children.push_back(make_pair(entry_name, entry_type));
53
53
  }
54
54
  D_ASSERT(!children.empty());
55
- result_type = LogicalType::STRUCT(std::move(children));
55
+ result_type = LogicalType::STRUCT(children);
56
+
56
57
  } else if (base_type == LogicalTypeId::MAP) {
57
58
 
58
59
  if (!type_name->typmods || type_name->typmods->length != 2) {
@@ -207,7 +208,7 @@ LogicalType Transformer::TransformTypeName(duckdb_libpgquery::PGTypeName *type_n
207
208
  // array bounds: turn the type into a list
208
209
  idx_t extra_stack = 0;
209
210
  for (auto cell = type_name->arrayBounds->head; cell != nullptr; cell = cell->next) {
210
- result_type = LogicalType::LIST(std::move(result_type));
211
+ result_type = LogicalType::LIST(result_type);
211
212
  StackCheck(extra_stack++);
212
213
  }
213
214
  }
@@ -26,8 +26,7 @@ unique_ptr<QueryNode> Transformer::TransformSelectInternal(duckdb_libpgquery::PG
26
26
  auto window_def = reinterpret_cast<duckdb_libpgquery::PGWindowDef *>(window_ele->data.ptr_value);
27
27
  D_ASSERT(window_def);
28
28
  D_ASSERT(window_def->name);
29
- auto window_name = StringUtil::Lower(string(window_def->name));
30
-
29
+ string window_name(window_def->name);
31
30
  auto it = window_clauses.find(window_name);
32
31
  if (it != window_clauses.end()) {
33
32
  throw ParserException("window \"%s\" is already defined", window_name);
@@ -219,7 +219,7 @@ BindResult SelectBinder::BindAggregate(FunctionExpression &aggr, AggregateFuncti
219
219
  const auto null_order = (order.null_order == OrderByNullType::ORDER_DEFAULT)
220
220
  ? config.options.default_null_order
221
221
  : order.null_order;
222
- order_bys->orders.emplace_back(BoundOrderByNode(sense, null_order, std::move(order_expr.expr)));
222
+ order_bys->orders.emplace_back(sense, null_order, std::move(order_expr.expr));
223
223
  }
224
224
  }
225
225
 
@@ -175,11 +175,12 @@ unique_ptr<ParsedExpression> ExpressionBinder::CreateStructPack(ColumnRefExpress
175
175
  }
176
176
  }
177
177
  // We found the table, now create the struct_pack expression
178
- vector<unique_ptr<ParsedExpression>> child_exprs;
178
+ vector<unique_ptr<ParsedExpression>> child_expressions;
179
+ child_expressions.reserve(binding->names.size());
179
180
  for (const auto &column_name : binding->names) {
180
- child_exprs.push_back(make_unique<ColumnRefExpression>(column_name, table_name));
181
+ child_expressions.push_back(make_unique<ColumnRefExpression>(column_name, table_name));
181
182
  }
182
- return make_unique<FunctionExpression>("struct_pack", std::move(child_exprs));
183
+ return make_unique<FunctionExpression>("struct_pack", std::move(child_expressions));
183
184
  }
184
185
 
185
186
  unique_ptr<ParsedExpression> ExpressionBinder::QualifyColumnName(ColumnRefExpression &colref, string &error_message) {
@@ -426,12 +426,16 @@ unique_ptr<BoundQueryNode> Binder::BindSelectNode(SelectNode &statement, unique_
426
426
  // after that, we bind to the SELECT list
427
427
  SelectBinder select_binder(*this, context, *result, info, alias_map);
428
428
  vector<LogicalType> internal_sql_types;
429
+ vector<idx_t> group_by_all_indexes;
429
430
  for (idx_t i = 0; i < statement.select_list.size(); i++) {
430
431
  bool is_window = statement.select_list[i]->IsWindow();
431
432
  idx_t unnest_count = result->unnests.size();
432
433
  LogicalType result_type;
433
434
  auto expr = select_binder.Bind(statement.select_list[i], &result_type);
434
- if (statement.aggregate_handling == AggregateHandling::FORCE_AGGREGATES && select_binder.HasBoundColumns()) {
435
+ bool is_original_column = i < result->column_count;
436
+ bool can_group_by_all =
437
+ statement.aggregate_handling == AggregateHandling::FORCE_AGGREGATES && is_original_column;
438
+ if (can_group_by_all && select_binder.HasBoundColumns()) {
435
439
  if (select_binder.BoundAggregates()) {
436
440
  throw BinderException("Cannot mix aggregates with non-aggregated columns!");
437
441
  }
@@ -443,20 +447,25 @@ unique_ptr<BoundQueryNode> Binder::BindSelectNode(SelectNode &statement, unique_
443
447
  }
444
448
  // we are forcing aggregates, and the node has columns bound
445
449
  // this entry becomes a group
446
- auto group_ref = make_unique<BoundColumnRefExpression>(
447
- expr->return_type, ColumnBinding(result->group_index, result->groups.group_expressions.size()));
448
- result->groups.group_expressions.push_back(std::move(expr));
449
- expr = std::move(group_ref);
450
+ group_by_all_indexes.push_back(i);
450
451
  }
451
452
  result->select_list.push_back(std::move(expr));
452
453
  if (i < result->column_count) {
453
454
  result->types.push_back(result_type);
454
455
  }
455
456
  internal_sql_types.push_back(result_type);
456
- if (statement.aggregate_handling == AggregateHandling::FORCE_AGGREGATES) {
457
+ if (can_group_by_all) {
457
458
  select_binder.ResetBindings();
458
459
  }
459
460
  }
461
+ // push the GROUP BY ALL expressions into the group set
462
+ for (auto &group_by_all_index : group_by_all_indexes) {
463
+ auto &expr = result->select_list[group_by_all_index];
464
+ auto group_ref = make_unique<BoundColumnRefExpression>(
465
+ expr->return_type, ColumnBinding(result->group_index, result->groups.group_expressions.size()));
466
+ result->groups.group_expressions.push_back(std::move(expr));
467
+ expr = std::move(group_ref);
468
+ }
460
469
  result->need_prune = result->select_list.size() > result->column_count;
461
470
 
462
471
  // in the normal select binder, we bind columns as if there is no aggregation
@@ -467,16 +476,19 @@ unique_ptr<BoundQueryNode> Binder::BindSelectNode(SelectNode &statement, unique_
467
476
  !result->groups.grouping_sets.empty()) {
468
477
  if (statement.aggregate_handling == AggregateHandling::NO_AGGREGATES_ALLOWED) {
469
478
  throw BinderException("Aggregates cannot be present in a Project relation!");
470
- } else if (statement.aggregate_handling == AggregateHandling::STANDARD_HANDLING) {
471
- if (select_binder.HasBoundColumns()) {
472
- auto &bound_columns = select_binder.GetBoundColumns();
473
- string error;
474
- error = "column \"%s\" must appear in the GROUP BY clause or must be part of an aggregate function.";
479
+ } else if (select_binder.HasBoundColumns()) {
480
+ auto &bound_columns = select_binder.GetBoundColumns();
481
+ string error;
482
+ error = "column \"%s\" must appear in the GROUP BY clause or must be part of an aggregate function.";
483
+ if (statement.aggregate_handling == AggregateHandling::FORCE_AGGREGATES) {
484
+ error += "\nGROUP BY ALL will only group entries in the SELECT list. Add it to the SELECT list or "
485
+ "GROUP BY this entry explicitly.";
486
+ } else {
475
487
  error += "\nEither add it to the GROUP BY list, or use \"ANY_VALUE(%s)\" if the exact value of \"%s\" "
476
488
  "is not important.";
477
- throw BinderException(FormatError(bound_columns[0].query_location, error, bound_columns[0].name,
478
- bound_columns[0].name, bound_columns[0].name));
479
489
  }
490
+ throw BinderException(FormatError(bound_columns[0].query_location, error, bound_columns[0].name,
491
+ bound_columns[0].name, bound_columns[0].name));
480
492
  }
481
493
  }
482
494
 
@@ -185,7 +185,7 @@ BoundStatement Binder::BindCopyFrom(CopyStatement &stmt) {
185
185
  vector<string> expected_names;
186
186
  if (!bound_insert.column_index_map.empty()) {
187
187
  expected_names.resize(bound_insert.expected_types.size());
188
- for (auto &col : table->GetColumns().Logical()) {
188
+ for (auto &col : table->GetColumns().Physical()) {
189
189
  auto i = col.Physical();
190
190
  if (bound_insert.column_index_map[i] != DConstants::INVALID_INDEX) {
191
191
  expected_names[bound_insert.column_index_map[i]] = col.Name();
@@ -193,7 +193,7 @@ BoundStatement Binder::BindCopyFrom(CopyStatement &stmt) {
193
193
  }
194
194
  } else {
195
195
  expected_names.reserve(bound_insert.expected_types.size());
196
- for (auto &col : table->GetColumns().Logical()) {
196
+ for (auto &col : table->GetColumns().Physical()) {
197
197
  expected_names.push_back(col.Name());
198
198
  }
199
199
  }
@@ -441,8 +441,9 @@ unique_ptr<LogicalOperator> DuckCatalog::BindCreateIndex(Binder &binder, CreateS
441
441
 
442
442
  auto &get = (LogicalGet &)*plan;
443
443
  // bind the index expressions
444
- vector<unique_ptr<Expression>> expressions;
445
444
  IndexBinder index_binder(binder, binder.context);
445
+ vector<unique_ptr<Expression>> expressions;
446
+ expressions.reserve(base.expressions.size());
446
447
  for (auto &expr : base.expressions) {
447
448
  expressions.push_back(index_binder.Bind(expr));
448
449
  }
@@ -119,9 +119,15 @@ static void BindConstraints(Binder &binder, BoundCreateTableInfo &info) {
119
119
  fk.info.type == ForeignKeyType::FK_TYPE_SELF_REFERENCE_TABLE);
120
120
  physical_index_set_t fk_key_set, pk_key_set;
121
121
  for (idx_t i = 0; i < fk.info.pk_keys.size(); i++) {
122
+ if (pk_key_set.find(fk.info.pk_keys[i]) != pk_key_set.end()) {
123
+ throw BinderException("Duplicate primary key referenced in FOREIGN KEY constraint");
124
+ }
122
125
  pk_key_set.insert(fk.info.pk_keys[i]);
123
126
  }
124
127
  for (idx_t i = 0; i < fk.info.fk_keys.size(); i++) {
128
+ if (fk_key_set.find(fk.info.fk_keys[i]) != fk_key_set.end()) {
129
+ throw BinderException("Duplicate key specified in FOREIGN KEY constraint");
130
+ }
125
131
  fk_key_set.insert(fk.info.fk_keys[i]);
126
132
  }
127
133
  info.bound_constraints.push_back(
@@ -292,6 +298,7 @@ unique_ptr<BoundCreateTableInfo> Binder::BindCreateTableInfo(unique_ptr<CreateIn
292
298
  result->dependencies.AddDependency(type_dependency);
293
299
  }
294
300
  }
301
+ result->dependencies.VerifyDependencies(schema->catalog, result->Base().table);
295
302
  properties.allow_stream_result = false;
296
303
  return result;
297
304
  }
@@ -303,9 +310,10 @@ unique_ptr<BoundCreateTableInfo> Binder::BindCreateTableInfo(unique_ptr<CreateIn
303
310
  }
304
311
 
305
312
  vector<unique_ptr<Expression>> Binder::BindCreateIndexExpressions(TableCatalogEntry *table, CreateIndexInfo *info) {
306
- vector<unique_ptr<Expression>> expressions;
307
313
 
308
314
  auto index_binder = IndexBinder(*this, this->context, table, info);
315
+ vector<unique_ptr<Expression>> expressions;
316
+ expressions.reserve(info->expressions.size());
309
317
  for (auto &expr : info->expressions) {
310
318
  expressions.push_back(index_binder.Bind(expr));
311
319
  }