duckdb 0.7.2-dev614.0 → 0.7.2-dev717.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 (58) hide show
  1. package/package.json +1 -1
  2. package/src/duckdb/extension/json/include/json_functions.hpp +1 -0
  3. package/src/duckdb/extension/json/json_functions.cpp +11 -4
  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/column_data_collection_segment.cpp +11 -6
  8. package/src/duckdb/src/common/vector_operations/vector_cast.cpp +2 -1
  9. package/src/duckdb/src/execution/aggregate_hashtable.cpp +10 -5
  10. package/src/duckdb/src/execution/expression_executor/execute_cast.cpp +2 -1
  11. package/src/duckdb/src/execution/index/art/art.cpp +5 -5
  12. package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +3 -0
  13. package/src/duckdb/src/execution/operator/helper/physical_vacuum.cpp +3 -0
  14. package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +3 -0
  15. package/src/duckdb/src/execution/partitionable_hashtable.cpp +14 -2
  16. package/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp +3 -0
  17. package/src/duckdb/src/function/aggregate/distributive/bitstring_agg.cpp +22 -7
  18. package/src/duckdb/src/function/aggregate/distributive/first.cpp +1 -0
  19. package/src/duckdb/src/function/aggregate/holistic/approximate_quantile.cpp +5 -2
  20. package/src/duckdb/src/function/cast/cast_function_set.cpp +1 -1
  21. package/src/duckdb/src/function/cast/enum_casts.cpp +25 -3
  22. package/src/duckdb/src/function/cast/list_casts.cpp +17 -4
  23. package/src/duckdb/src/function/cast/map_cast.cpp +5 -2
  24. package/src/duckdb/src/function/cast/string_cast.cpp +36 -10
  25. package/src/duckdb/src/function/cast/struct_cast.cpp +23 -3
  26. package/src/duckdb/src/function/cast/union_casts.cpp +33 -7
  27. package/src/duckdb/src/function/table/checkpoint.cpp +5 -1
  28. package/src/duckdb/src/function/table/system/duckdb_constraints.cpp +2 -2
  29. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  30. package/src/duckdb/src/include/duckdb/catalog/dependency_list.hpp +3 -0
  31. package/src/duckdb/src/include/duckdb/common/optional_ptr.hpp +45 -0
  32. package/src/duckdb/src/include/duckdb/execution/aggregate_hashtable.hpp +1 -0
  33. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +2 -2
  34. package/src/duckdb/src/include/duckdb/execution/partitionable_hashtable.hpp +3 -0
  35. package/src/duckdb/src/include/duckdb/function/cast/bound_cast_data.hpp +84 -0
  36. package/src/duckdb/src/include/duckdb/function/cast/cast_function_set.hpp +2 -2
  37. package/src/duckdb/src/include/duckdb/function/cast/default_casts.hpp +28 -64
  38. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +3 -0
  39. package/src/duckdb/src/include/duckdb/storage/data_table.hpp +2 -2
  40. package/src/duckdb/src/include/duckdb/storage/index.hpp +4 -3
  41. package/src/duckdb/src/include/duckdb/storage/statistics/distinct_statistics.hpp +2 -0
  42. package/src/duckdb/src/include/duckdb/transaction/local_storage.hpp +2 -2
  43. package/src/duckdb/src/optimizer/pushdown/pushdown_aggregate.cpp +33 -5
  44. package/src/duckdb/src/optimizer/rule/move_constants.cpp +8 -2
  45. package/src/duckdb/src/parser/transform/expression/transform_function.cpp +17 -1
  46. package/src/duckdb/src/parser/transform/statement/transform_select_node.cpp +1 -2
  47. package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +25 -13
  48. package/src/duckdb/src/planner/binder/statement/bind_copy.cpp +5 -3
  49. package/src/duckdb/src/planner/binder/statement/bind_create_table.cpp +7 -0
  50. package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +10 -6
  51. package/src/duckdb/src/planner/binder/statement/bind_update.cpp +3 -1
  52. package/src/duckdb/src/planner/expression_binder/having_binder.cpp +3 -0
  53. package/src/duckdb/src/storage/data_table.cpp +15 -13
  54. package/src/duckdb/src/storage/index.cpp +12 -1
  55. package/src/duckdb/src/storage/local_storage.cpp +20 -23
  56. package/src/duckdb/src/storage/statistics/column_statistics.cpp +1 -2
  57. package/src/duckdb/src/storage/statistics/distinct_statistics.cpp +4 -0
  58. package/src/duckdb/src/storage/table/row_group.cpp +6 -1
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
4
  "types": "./lib/duckdb.d.ts",
5
- "version": "0.7.2-dev614.0",
5
+ "version": "0.7.2-dev717.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
@@ -54,6 +54,7 @@ public:
54
54
 
55
55
  struct JSONFunctionLocalState : public FunctionLocalState {
56
56
  public:
57
+ explicit JSONFunctionLocalState(Allocator &allocator);
57
58
  explicit JSONFunctionLocalState(ClientContext &context);
58
59
  static unique_ptr<FunctionLocalState> Init(ExpressionState &state, const BoundFunctionExpression &expr,
59
60
  FunctionData *bind_data);
@@ -103,7 +103,10 @@ unique_ptr<FunctionData> JSONReadManyFunctionData::Bind(ClientContext &context,
103
103
  return make_unique<JSONReadManyFunctionData>(std::move(paths), std::move(lens));
104
104
  }
105
105
 
106
- JSONFunctionLocalState::JSONFunctionLocalState(ClientContext &context) : json_allocator(BufferAllocator::Get(context)) {
106
+ JSONFunctionLocalState::JSONFunctionLocalState(Allocator &allocator) : json_allocator(allocator) {
107
+ }
108
+ JSONFunctionLocalState::JSONFunctionLocalState(ClientContext &context)
109
+ : JSONFunctionLocalState(BufferAllocator::Get(context)) {
107
110
  }
108
111
 
109
112
  unique_ptr<FunctionLocalState> JSONFunctionLocalState::Init(ExpressionState &state, const BoundFunctionExpression &expr,
@@ -184,8 +187,12 @@ unique_ptr<TableRef> JSONFunctions::ReadJSONReplacement(ClientContext &context,
184
187
  return std::move(table_function);
185
188
  }
186
189
 
187
- static unique_ptr<FunctionLocalState> InitJSONCastLocalState(ClientContext &context) {
188
- return make_unique<JSONFunctionLocalState>(context);
190
+ static unique_ptr<FunctionLocalState> InitJSONCastLocalState(CastLocalStateParameters &parameters) {
191
+ if (parameters.context) {
192
+ return make_unique<JSONFunctionLocalState>(*parameters.context);
193
+ } else {
194
+ return make_unique<JSONFunctionLocalState>(Allocator::DefaultAllocator());
195
+ }
189
196
  }
190
197
 
191
198
  static bool CastVarcharToJSON(Vector &source, Vector &result, idx_t count, CastParameters &parameters) {
@@ -208,9 +215,9 @@ static bool CastVarcharToJSON(Vector &source, Vector &result, idx_t count, CastP
208
215
  mask.SetInvalid(idx);
209
216
  success = false;
210
217
  }
211
-
212
218
  return input;
213
219
  });
220
+ result.Reinterpret(source);
214
221
  return success;
215
222
  }
216
223
 
@@ -193,14 +193,14 @@ const vector<unique_ptr<Constraint>> &TableCatalogEntry::GetConstraints() {
193
193
  }
194
194
 
195
195
  DataTable &TableCatalogEntry::GetStorage() {
196
- throw InternalException("Calling GetStorage on a TableCatalogEntry that is not a DTableCatalogEntry");
196
+ throw InternalException("Calling GetStorage on a TableCatalogEntry that is not a DuckTableEntry");
197
197
  }
198
198
 
199
199
  DataTable *TableCatalogEntry::GetStoragePtr() {
200
- throw InternalException("Calling GetStoragePtr on a TableCatalogEntry that is not a DTableCatalogEntry");
200
+ throw InternalException("Calling GetStoragePtr on a TableCatalogEntry that is not a DuckTableEntry");
201
201
  }
202
202
 
203
203
  const vector<unique_ptr<BoundConstraint>> &TableCatalogEntry::GetBoundConstraints() {
204
- throw InternalException("Calling GetBoundConstraints on a TableCatalogEntry that is not a DTableCatalogEntry");
204
+ throw InternalException("Calling GetBoundConstraints on a TableCatalogEntry that is not a DuckTableEntry");
205
205
  }
206
206
  } // namespace duckdb
@@ -1,5 +1,6 @@
1
1
  #include "duckdb/catalog/dependency_list.hpp"
2
2
  #include "duckdb/catalog/catalog_entry.hpp"
3
+ #include "duckdb/catalog/catalog.hpp"
3
4
 
4
5
  namespace duckdb {
5
6
 
@@ -10,4 +11,15 @@ void DependencyList::AddDependency(CatalogEntry *entry) {
10
11
  set.insert(entry);
11
12
  }
12
13
 
14
+ void DependencyList::VerifyDependencies(Catalog *catalog, const string &name) {
15
+ for (auto &dep : set) {
16
+ if (dep->catalog != catalog) {
17
+ throw DependencyException(
18
+ "Error adding dependency for object \"%s\" - dependency \"%s\" is in catalog "
19
+ "\"%s\", which does not match the catalog \"%s\".\nCross catalog dependencies are not supported.",
20
+ name, dep->name, dep->catalog->GetName(), catalog->GetName());
21
+ }
22
+ }
23
+ }
24
+
13
25
  } // namespace duckdb
@@ -191,11 +191,14 @@ vector<string> StringUtil::Split(const string &input, const string &split) {
191
191
 
192
192
  // Push the substring [last, next) on to splits
193
193
  string substr = input.substr(last, next - last);
194
- if (substr.empty() == false) {
194
+ if (!substr.empty()) {
195
195
  splits.push_back(substr);
196
196
  }
197
197
  last = next + split_len;
198
198
  }
199
+ if (splits.empty()) {
200
+ splits.push_back(input);
201
+ }
199
202
  return splits;
200
203
  }
201
204
 
@@ -1,4 +1,5 @@
1
1
  #include "duckdb/common/types/column_data_collection_segment.hpp"
2
+ #include "duckdb/common/vector_operations/vector_operations.hpp"
2
3
 
3
4
  namespace duckdb {
4
5
 
@@ -202,12 +203,16 @@ idx_t ColumnDataCollectionSegment::ReadVector(ChunkManagementState &state, Vecto
202
203
  throw InternalException("Column Data Collection: mismatch in struct child sizes");
203
204
  }
204
205
  }
205
- } else if (internal_type == PhysicalType::VARCHAR &&
206
- allocator->GetType() == ColumnDataAllocatorType::BUFFER_MANAGER_ALLOCATOR) {
207
- for (auto &swizzle_segment : vdata.swizzle_data) {
208
- auto &string_heap_segment = GetVectorData(swizzle_segment.child_index);
209
- allocator->UnswizzlePointers(state, result, swizzle_segment.offset, swizzle_segment.count,
210
- string_heap_segment.block_id, string_heap_segment.offset);
206
+ } else if (internal_type == PhysicalType::VARCHAR) {
207
+ if (allocator->GetType() == ColumnDataAllocatorType::BUFFER_MANAGER_ALLOCATOR) {
208
+ for (auto &swizzle_segment : vdata.swizzle_data) {
209
+ auto &string_heap_segment = GetVectorData(swizzle_segment.child_index);
210
+ allocator->UnswizzlePointers(state, result, swizzle_segment.offset, swizzle_segment.count,
211
+ string_heap_segment.block_id, string_heap_segment.offset);
212
+ }
213
+ }
214
+ if (state.properties == ColumnDataScanProperties::DISALLOW_ZERO_COPY) {
215
+ VectorOperations::Copy(result, result, vdata.count, 0, 0);
211
216
  }
212
217
  }
213
218
  return vcount;
@@ -11,7 +11,8 @@ bool VectorOperations::TryCast(CastFunctionSet &set, GetCastFunctionInput &input
11
11
  auto cast_function = set.GetCastFunction(source.GetType(), result.GetType(), input);
12
12
  unique_ptr<FunctionLocalState> local_state;
13
13
  if (cast_function.init_local_state) {
14
- local_state = cast_function.init_local_state(*input.context);
14
+ CastLocalStateParameters lparameters(input.context, cast_function.cast_data);
15
+ local_state = cast_function.init_local_state(lparameters);
15
16
  }
16
17
  CastParameters parameters(cast_function.cast_data.get(), strict, error_message, local_state.get());
17
18
  return cast_function.function(source, result, count, parameters);
@@ -155,25 +155,30 @@ void GroupedAggregateHashTable::VerifyInternal() {
155
155
  D_ASSERT(count == entries);
156
156
  }
157
157
 
158
- idx_t GroupedAggregateHashTable::MaxCapacity() {
159
- idx_t max_pages = 0;
160
- idx_t max_tuples = 0;
158
+ idx_t GroupedAggregateHashTable::GetMaxCapacity(HtEntryType entry_type, idx_t tuple_size) {
159
+ idx_t max_pages;
160
+ idx_t max_tuples;
161
161
 
162
162
  switch (entry_type) {
163
163
  case HtEntryType::HT_WIDTH_32:
164
164
  max_pages = NumericLimits<uint8_t>::Maximum();
165
165
  max_tuples = NumericLimits<uint16_t>::Maximum();
166
166
  break;
167
- default:
168
- D_ASSERT(entry_type == HtEntryType::HT_WIDTH_64);
167
+ case HtEntryType::HT_WIDTH_64:
169
168
  max_pages = NumericLimits<uint32_t>::Maximum();
170
169
  max_tuples = NumericLimits<uint16_t>::Maximum();
171
170
  break;
171
+ default:
172
+ throw InternalException("Unsupported hash table width");
172
173
  }
173
174
 
174
175
  return max_pages * MinValue(max_tuples, (idx_t)Storage::BLOCK_SIZE / tuple_size);
175
176
  }
176
177
 
178
+ idx_t GroupedAggregateHashTable::MaxCapacity() {
179
+ return GetMaxCapacity(entry_type, tuple_size);
180
+ }
181
+
177
182
  void GroupedAggregateHashTable::Verify() {
178
183
  #ifdef DEBUG
179
184
  switch (entry_type) {
@@ -11,7 +11,8 @@ unique_ptr<ExpressionState> ExpressionExecutor::InitializeState(const BoundCastE
11
11
  result->AddChild(expr.child.get());
12
12
  result->Finalize();
13
13
  if (expr.bound_cast.init_local_state) {
14
- result->local_state = expr.bound_cast.init_local_state(root.executor->GetContext());
14
+ CastLocalStateParameters parameters(root.executor->GetContext(), expr.bound_cast.cast_data);
15
+ result->local_state = expr.bound_cast.init_local_state(parameters);
15
16
  }
16
17
  return std::move(result);
17
18
  }
@@ -330,8 +330,7 @@ bool ART::ConstructFromSorted(idx_t count, vector<Key> &keys, Vector &row_identi
330
330
  //===--------------------------------------------------------------------===//
331
331
  // Insert / Verification / Constraint Checking
332
332
  //===--------------------------------------------------------------------===//
333
-
334
- bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
333
+ PreservedError ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
335
334
 
336
335
  D_ASSERT(row_ids.GetType().InternalType() == ROW_TYPE);
337
336
  D_ASSERT(logical_types[0] == input.data[0].GetType());
@@ -375,12 +374,13 @@ bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
375
374
 
376
375
  IncreaseAndVerifyMemorySize(old_memory_size);
377
376
  if (failed_index != DConstants::INVALID_INDEX) {
378
- return false;
377
+ return PreservedError(ConstraintException("PRIMARY KEY or UNIQUE constraint violated: duplicate key \"%s\"",
378
+ AppendRowError(input, failed_index)));
379
379
  }
380
- return true;
380
+ return PreservedError();
381
381
  }
382
382
 
383
- bool ART::Append(IndexLock &lock, DataChunk &appended_data, Vector &row_identifiers) {
383
+ PreservedError ART::Append(IndexLock &lock, DataChunk &appended_data, Vector &row_identifiers) {
384
384
  DataChunk expression_result;
385
385
  expression_result.Initialize(Allocator::DefaultAllocator(), logical_types);
386
386
 
@@ -1559,6 +1559,9 @@ TaskExecutionResult WindowMergeTask::ExecuteTask(TaskExecutionMode mode) {
1559
1559
  size_t sorted = 0;
1560
1560
  while (sorted < hash_groups.states.size()) {
1561
1561
  // First check if there is an unfinished task for this thread
1562
+ if (executor.HasError()) {
1563
+ return TaskExecutionResult::TASK_ERROR;
1564
+ }
1562
1565
  if (!local_state.TaskFinished()) {
1563
1566
  local_state.ExecuteTask();
1564
1567
  continue;
@@ -49,6 +49,9 @@ SinkResultType PhysicalVacuum::Sink(ExecutionContext &context, GlobalSinkState &
49
49
  D_ASSERT(lstate.column_distinct_stats.size() == info->column_id_map.size());
50
50
 
51
51
  for (idx_t col_idx = 0; col_idx < input.data.size(); col_idx++) {
52
+ if (!DistinctStatistics::TypeIsSupported(input.data[col_idx].GetType())) {
53
+ continue;
54
+ }
52
55
  lstate.column_distinct_stats[col_idx]->Update(input.data[col_idx], input.size(), false);
53
56
  }
54
57
 
@@ -121,6 +121,9 @@ bool TryCastFloatingValueCommaSeparated(const string_t &value_str, const Logical
121
121
  }
122
122
 
123
123
  bool BaseCSVReader::TryCastValue(const Value &value, const LogicalType &sql_type) {
124
+ if (value.IsNull()) {
125
+ return true;
126
+ }
124
127
  if (options.has_format[LogicalTypeId::DATE] && sql_type.id() == LogicalTypeId::DATE) {
125
128
  date_t result;
126
129
  string error_message;
@@ -62,6 +62,18 @@ PartitionableHashTable::PartitionableHashTable(ClientContext &context, Allocator
62
62
  for (hash_t r = 0; r < partition_info.n_partitions; r++) {
63
63
  sel_vectors[r].Initialize();
64
64
  }
65
+
66
+ RowLayout layout;
67
+ layout.Initialize(group_types, AggregateObject::CreateAggregateObjects(bindings));
68
+ tuple_size = layout.GetRowWidth();
69
+ }
70
+
71
+ HtEntryType PartitionableHashTable::GetHTEntrySize() {
72
+ // we need at least STANDARD_VECTOR_SIZE entries to fit in the hash table
73
+ if (GroupedAggregateHashTable::GetMaxCapacity(HtEntryType::HT_WIDTH_32, tuple_size) < STANDARD_VECTOR_SIZE) {
74
+ return HtEntryType::HT_WIDTH_64;
75
+ }
76
+ return HtEntryType::HT_WIDTH_32;
65
77
  }
66
78
 
67
79
  idx_t PartitionableHashTable::ListAddChunk(HashTableList &list, DataChunk &groups, Vector &group_hashes,
@@ -74,7 +86,7 @@ idx_t PartitionableHashTable::ListAddChunk(HashTableList &list, DataChunk &group
74
86
  list.back()->Finalize();
75
87
  }
76
88
  list.push_back(make_unique<GroupedAggregateHashTable>(context, allocator, group_types, payload_types, bindings,
77
- HtEntryType::HT_WIDTH_32));
89
+ GetHTEntrySize()));
78
90
  }
79
91
  return list.back()->AddChunk(groups, group_hashes, payload, filter);
80
92
  }
@@ -141,7 +153,7 @@ void PartitionableHashTable::Partition() {
141
153
  for (auto &unpartitioned_ht : unpartitioned_hts) {
142
154
  for (idx_t r = 0; r < partition_info.n_partitions; r++) {
143
155
  radix_partitioned_hts[r].push_back(make_unique<GroupedAggregateHashTable>(
144
- context, allocator, group_types, payload_types, bindings, HtEntryType::HT_WIDTH_32));
156
+ context, allocator, group_types, payload_types, bindings, GetHTEntrySize()));
145
157
  partition_hts[r] = radix_partitioned_hts[r].back().get();
146
158
  }
147
159
  unpartitioned_ht->Partition(partition_hts, partition_info.radix_mask, partition_info.RADIX_SHIFT);
@@ -154,6 +154,9 @@ static void CanUseIndexJoin(TableScanBindData *tbl, Expression &expr, Index **re
154
154
 
155
155
  void TransformIndexJoin(ClientContext &context, LogicalComparisonJoin &op, Index **left_index, Index **right_index,
156
156
  PhysicalOperator *left, PhysicalOperator *right) {
157
+ if (op.type == LogicalOperatorType::LOGICAL_DELIM_JOIN) {
158
+ return;
159
+ }
157
160
  // check if one of the tables has an index on column
158
161
  if (op.join_type == JoinType::INNER && op.conditions.size() == 1) {
159
162
  // check if one of the children are table scans and if they have an index in the join attribute
@@ -6,6 +6,7 @@
6
6
  #include "duckdb/storage/statistics/base_statistics.hpp"
7
7
  #include "duckdb/execution/expression_executor.hpp"
8
8
  #include "duckdb/common/types/cast_helpers.hpp"
9
+ #include "duckdb/common/operator/subtract.hpp"
9
10
 
10
11
  namespace duckdb {
11
12
 
@@ -93,7 +94,16 @@ struct BitStringAggOperation {
93
94
 
94
95
  template <class INPUT_TYPE>
95
96
  static idx_t GetRange(INPUT_TYPE min, INPUT_TYPE max) {
96
- return max - min + 1;
97
+ D_ASSERT(max >= min);
98
+ INPUT_TYPE result;
99
+ if (!TrySubtractOperator::Operation(max, min, result)) {
100
+ return NumericLimits<idx_t>::Maximum();
101
+ }
102
+ idx_t val(result);
103
+ if (val == NumericLimits<idx_t>::Maximum()) {
104
+ return val;
105
+ }
106
+ return val + 1;
97
107
  }
98
108
 
99
109
  template <class INPUT_TYPE, class STATE>
@@ -162,12 +172,15 @@ void BitStringAggOperation::Execute(BitAggState<hugeint_t> *state, hugeint_t inp
162
172
 
163
173
  template <>
164
174
  idx_t BitStringAggOperation::GetRange(hugeint_t min, hugeint_t max) {
165
- idx_t val;
166
- if (Hugeint::TryCast(max - min + 1, val)) {
167
- return val;
168
- } else {
169
- throw OutOfRangeException("Range too large for bitstring aggregation");
175
+ hugeint_t result;
176
+ if (!TrySubtractOperator::Operation(max, min, result)) {
177
+ return NumericLimits<idx_t>::Maximum();
178
+ }
179
+ idx_t range;
180
+ if (!Hugeint::TryCast(result + 1, range)) {
181
+ return NumericLimits<idx_t>::Maximum();
170
182
  }
183
+ return range;
171
184
  }
172
185
 
173
186
  unique_ptr<BaseStatistics> BitstringPropagateStats(ClientContext &context, BoundAggregateExpression &expr,
@@ -185,8 +198,10 @@ unique_ptr<BaseStatistics> BitstringPropagateStats(ClientContext &context, Bound
185
198
 
186
199
  unique_ptr<FunctionData> BindBitstringAgg(ClientContext &context, AggregateFunction &function,
187
200
  vector<unique_ptr<Expression>> &arguments) {
188
-
189
201
  if (arguments.size() == 3) {
202
+ if (!arguments[1]->IsFoldable() && !arguments[2]->IsFoldable()) {
203
+ throw BinderException("bitstring_agg requires a constant min and max argument");
204
+ }
190
205
  auto min = ExpressionExecutor::EvaluateScalar(context, *arguments[1]);
191
206
  auto max = ExpressionExecutor::EvaluateScalar(context, *arguments[2]);
192
207
  Function::EraseArgument(function, arguments, 2);
@@ -79,6 +79,7 @@ struct FirstFunctionString : public FirstFunctionBase {
79
79
  }
80
80
  } else {
81
81
  state->is_set = true;
82
+ state->is_null = false;
82
83
  if (value.IsInlined()) {
83
84
  state->value = value;
84
85
  } else {
@@ -70,11 +70,14 @@ struct ApproxQuantileOperation {
70
70
 
71
71
  template <class INPUT_TYPE, class STATE, class OP>
72
72
  static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *data, ValidityMask &mask, idx_t idx) {
73
+ auto val = Cast::template Operation<INPUT_TYPE, SAVE_TYPE>(data[idx]);
74
+ if (!Value::DoubleIsFinite(val)) {
75
+ return;
76
+ }
73
77
  if (!state->h) {
74
78
  state->h = new duckdb_tdigest::TDigest(100);
75
79
  }
76
-
77
- state->h->add(Cast::template Operation<INPUT_TYPE, SAVE_TYPE>(data[idx]));
80
+ state->h->add(val);
78
81
  state->pos++;
79
82
  }
80
83
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  namespace duckdb {
8
8
 
9
- BindCastInput::BindCastInput(CastFunctionSet &function_set, BindCastInfo *info, ClientContext *context)
9
+ BindCastInput::BindCastInput(CastFunctionSet &function_set, BindCastInfo *info, optional_ptr<ClientContext> context)
10
10
  : function_set(function_set), info(info), context(context) {
11
11
  }
12
12
 
@@ -109,17 +109,39 @@ unique_ptr<BoundCastData> BindEnumCast(BindCastInput &input, const LogicalType &
109
109
  return make_unique<EnumBoundCastData>(std::move(to_varchar_cast), std::move(from_varchar_cast));
110
110
  }
111
111
 
112
+ struct EnumCastLocalState : public FunctionLocalState {
113
+ public:
114
+ unique_ptr<FunctionLocalState> to_varchar_local;
115
+ unique_ptr<FunctionLocalState> from_varchar_local;
116
+ };
117
+
118
+ static unique_ptr<FunctionLocalState> InitEnumCastLocalState(CastLocalStateParameters &parameters) {
119
+ auto &cast_data = (EnumBoundCastData &)*parameters.cast_data;
120
+ auto result = make_unique<EnumCastLocalState>();
121
+
122
+ if (cast_data.from_varchar_cast.init_local_state) {
123
+ CastLocalStateParameters from_varchar_params(parameters, cast_data.from_varchar_cast.cast_data);
124
+ result->from_varchar_local = cast_data.from_varchar_cast.init_local_state(from_varchar_params);
125
+ }
126
+ if (cast_data.to_varchar_cast.init_local_state) {
127
+ CastLocalStateParameters from_varchar_params(parameters, cast_data.to_varchar_cast.cast_data);
128
+ result->from_varchar_local = cast_data.to_varchar_cast.init_local_state(from_varchar_params);
129
+ }
130
+ return std::move(result);
131
+ }
132
+
112
133
  static bool EnumToAnyCast(Vector &source, Vector &result, idx_t count, CastParameters &parameters) {
113
134
  auto &cast_data = (EnumBoundCastData &)*parameters.cast_data;
135
+ auto &lstate = (EnumCastLocalState &)*parameters.local_state;
114
136
 
115
137
  Vector varchar_cast(LogicalType::VARCHAR, count);
116
138
 
117
139
  // cast to varchar
118
- CastParameters to_varchar_params(parameters, cast_data.to_varchar_cast.cast_data.get());
140
+ CastParameters to_varchar_params(parameters, cast_data.to_varchar_cast.cast_data, lstate.to_varchar_local);
119
141
  cast_data.to_varchar_cast.function(source, varchar_cast, count, to_varchar_params);
120
142
 
121
143
  // cast from varchar to the target
122
- CastParameters from_varchar_params(parameters, cast_data.from_varchar_cast.cast_data.get());
144
+ CastParameters from_varchar_params(parameters, cast_data.from_varchar_cast.cast_data, lstate.from_varchar_local);
123
145
  cast_data.from_varchar_cast.function(varchar_cast, result, count, from_varchar_params);
124
146
  return true;
125
147
  }
@@ -152,7 +174,7 @@ BoundCastInfo DefaultCasts::EnumCastSwitch(BindCastInput &input, const LogicalTy
152
174
  throw InternalException("ENUM can only have unsigned integers (except UINT64) as physical types");
153
175
  }
154
176
  default: {
155
- return BoundCastInfo(EnumToAnyCast, BindEnumCast(input, source, target));
177
+ return BoundCastInfo(EnumToAnyCast, BindEnumCast(input, source, target), InitEnumCastLocalState);
156
178
  }
157
179
  }
158
180
  }
@@ -1,5 +1,6 @@
1
1
  #include "duckdb/function/cast/default_casts.hpp"
2
2
  #include "duckdb/function/cast/cast_function_set.hpp"
3
+ #include "duckdb/function/cast/bound_cast_data.hpp"
3
4
 
4
5
  namespace duckdb {
5
6
 
@@ -12,6 +13,15 @@ unique_ptr<BoundCastData> ListBoundCastData::BindListToListCast(BindCastInput &i
12
13
  return make_unique<ListBoundCastData>(std::move(child_cast));
13
14
  }
14
15
 
16
+ unique_ptr<FunctionLocalState> ListBoundCastData::InitListLocalState(CastLocalStateParameters &parameters) {
17
+ auto &cast_data = (ListBoundCastData &)*parameters.cast_data;
18
+ if (!cast_data.child_cast_info.init_local_state) {
19
+ return nullptr;
20
+ }
21
+ CastLocalStateParameters child_parameters(parameters, cast_data.child_cast_info.cast_data);
22
+ return cast_data.child_cast_info.init_local_state(child_parameters);
23
+ }
24
+
15
25
  bool ListCast::ListToListCast(Vector &source, Vector &result, idx_t count, CastParameters &parameters) {
16
26
  auto &cast_data = (ListBoundCastData &)*parameters.cast_data;
17
27
 
@@ -40,7 +50,7 @@ bool ListCast::ListToListCast(Vector &source, Vector &result, idx_t count, CastP
40
50
  ListVector::Reserve(result, source_size);
41
51
  auto &append_vector = ListVector::GetEntry(result);
42
52
 
43
- CastParameters child_parameters(parameters, cast_data.child_cast_info.cast_data.get());
53
+ CastParameters child_parameters(parameters, cast_data.child_cast_info.cast_data, parameters.local_state);
44
54
  if (!cast_data.child_cast_info.function(source_cc, append_vector, source_size, child_parameters)) {
45
55
  return false;
46
56
  }
@@ -116,10 +126,13 @@ static bool ListToVarcharCast(Vector &source, Vector &result, idx_t count, CastP
116
126
  BoundCastInfo DefaultCasts::ListCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target) {
117
127
  switch (target.id()) {
118
128
  case LogicalTypeId::LIST:
119
- return BoundCastInfo(ListCast::ListToListCast, ListBoundCastData::BindListToListCast(input, source, target));
129
+ return BoundCastInfo(ListCast::ListToListCast, ListBoundCastData::BindListToListCast(input, source, target),
130
+ ListBoundCastData::InitListLocalState);
120
131
  case LogicalTypeId::VARCHAR:
121
- return BoundCastInfo(ListToVarcharCast, ListBoundCastData::BindListToListCast(
122
- input, source, LogicalType::LIST(LogicalType::VARCHAR)));
132
+ return BoundCastInfo(
133
+ ListToVarcharCast,
134
+ ListBoundCastData::BindListToListCast(input, source, LogicalType::LIST(LogicalType::VARCHAR)),
135
+ ListBoundCastData::InitListLocalState);
123
136
  default:
124
137
  return DefaultCasts::TryVectorNullCast;
125
138
  }
@@ -1,5 +1,6 @@
1
1
  #include "duckdb/function/cast/default_casts.hpp"
2
2
  #include "duckdb/function/cast/cast_function_set.hpp"
3
+ #include "duckdb/function/cast/bound_cast_data.hpp"
3
4
 
4
5
  namespace duckdb {
5
6
 
@@ -78,10 +79,12 @@ static bool MapToVarcharCast(Vector &source, Vector &result, idx_t count, CastPa
78
79
  BoundCastInfo DefaultCasts::MapCastSwitch(BindCastInput &input, const LogicalType &source, const LogicalType &target) {
79
80
  switch (target.id()) {
80
81
  case LogicalTypeId::MAP:
81
- return BoundCastInfo(ListCast::ListToListCast, ListBoundCastData::BindListToListCast(input, source, target));
82
+ return BoundCastInfo(ListCast::ListToListCast, ListBoundCastData::BindListToListCast(input, source, target),
83
+ ListBoundCastData::InitListLocalState);
82
84
  case LogicalTypeId::VARCHAR: {
83
85
  auto varchar_type = LogicalType::MAP(LogicalType::VARCHAR, LogicalType::VARCHAR);
84
- return BoundCastInfo(MapToVarcharCast, ListBoundCastData::BindListToListCast(input, source, varchar_type));
86
+ return BoundCastInfo(MapToVarcharCast, ListBoundCastData::BindListToListCast(input, source, varchar_type),
87
+ ListBoundCastData::InitListLocalState);
85
88
  }
86
89
  default:
87
90
  return TryVectorNullCast;