duckdb 0.8.2-dev2356.0 → 0.8.2-dev2509.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 (38) hide show
  1. package/binding.gyp +7 -7
  2. package/package.json +1 -1
  3. package/src/duckdb/extension/icu/icu-datefunc.cpp +9 -0
  4. package/src/duckdb/extension/icu/icu-datepart.cpp +7 -5
  5. package/src/duckdb/extension/icu/icu-strptime.cpp +1 -20
  6. package/src/duckdb/src/common/http_state.cpp +78 -0
  7. package/src/duckdb/src/common/types/list_segment.cpp +42 -134
  8. package/src/duckdb/src/common/types/vector.cpp +21 -0
  9. package/src/duckdb/src/core_functions/aggregate/holistic/mode.cpp +5 -7
  10. package/src/duckdb/src/core_functions/aggregate/holistic/quantile.cpp +17 -19
  11. package/src/duckdb/src/core_functions/aggregate/nested/list.cpp +80 -61
  12. package/src/duckdb/src/core_functions/function_list.cpp +2 -2
  13. package/src/duckdb/src/core_functions/scalar/list/array_slice.cpp +308 -82
  14. package/src/duckdb/src/execution/aggregate_hashtable.cpp +6 -0
  15. package/src/duckdb/src/execution/perfect_aggregate_hashtable.cpp +11 -5
  16. package/src/duckdb/src/execution/window_executor.cpp +18 -20
  17. package/src/duckdb/src/function/aggregate/distributive/count.cpp +2 -2
  18. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  19. package/src/duckdb/src/include/duckdb/common/http_state.hpp +61 -28
  20. package/src/duckdb/src/include/duckdb/common/types/list_segment.hpp +9 -11
  21. package/src/duckdb/src/include/duckdb/common/types/vector.hpp +7 -0
  22. package/src/duckdb/src/include/duckdb/common/vector_operations/aggregate_executor.hpp +7 -2
  23. package/src/duckdb/src/include/duckdb/core_functions/scalar/list_functions.hpp +4 -4
  24. package/src/duckdb/src/include/duckdb/execution/perfect_aggregate_hashtable.hpp +4 -2
  25. package/src/duckdb/src/include/duckdb/execution/window_segment_tree.hpp +0 -2
  26. package/src/duckdb/src/include/duckdb/function/aggregate_function.hpp +0 -1
  27. package/src/duckdb/src/include/duckdb/parser/expression/operator_expression.hpp +20 -3
  28. package/src/duckdb/src/main/extension/extension_helper.cpp +2 -1
  29. package/src/duckdb/src/parser/transform/expression/transform_array_access.cpp +13 -4
  30. package/src/duckdb/src/parser/transform/expression/transform_function.cpp +3 -0
  31. package/src/duckdb/src/storage/serialization/serialize_constraint.cpp +2 -2
  32. package/src/duckdb/src/storage/serialization/serialize_create_info.cpp +2 -2
  33. package/src/duckdb/src/storage/serialization/serialize_parse_info.cpp +2 -2
  34. package/src/duckdb/src/storage/serialization/serialize_tableref.cpp +2 -4
  35. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +1 -0
  36. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +11077 -10674
  37. package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +6 -6
  38. package/src/duckdb/ub_src_common.cpp +2 -0
package/binding.gyp CHANGED
@@ -244,18 +244,18 @@
244
244
  "src/duckdb/third_party/zstd/compress/zstd_lazy.cpp",
245
245
  "src/duckdb/third_party/zstd/compress/zstd_ldm.cpp",
246
246
  "src/duckdb/third_party/zstd/compress/zstd_opt.cpp",
247
- "src/duckdb/extension/icu/./icu_extension.cpp",
248
- "src/duckdb/extension/icu/./icu-datetrunc.cpp",
249
- "src/duckdb/extension/icu/./icu-datepart.cpp",
250
247
  "src/duckdb/extension/icu/./icu-strptime.cpp",
248
+ "src/duckdb/extension/icu/./icu-datepart.cpp",
249
+ "src/duckdb/extension/icu/./icu-datesub.cpp",
251
250
  "src/duckdb/extension/icu/./icu-table-range.cpp",
252
- "src/duckdb/extension/icu/./icu-makedate.cpp",
253
- "src/duckdb/extension/icu/./icu-datefunc.cpp",
254
- "src/duckdb/extension/icu/./icu-list-range.cpp",
251
+ "src/duckdb/extension/icu/./icu-datetrunc.cpp",
255
252
  "src/duckdb/extension/icu/./icu-timebucket.cpp",
256
253
  "src/duckdb/extension/icu/./icu-dateadd.cpp",
254
+ "src/duckdb/extension/icu/./icu-list-range.cpp",
257
255
  "src/duckdb/extension/icu/./icu-timezone.cpp",
258
- "src/duckdb/extension/icu/./icu-datesub.cpp",
256
+ "src/duckdb/extension/icu/./icu-datefunc.cpp",
257
+ "src/duckdb/extension/icu/./icu_extension.cpp",
258
+ "src/duckdb/extension/icu/./icu-makedate.cpp",
259
259
  "src/duckdb/ub_extension_icu_third_party_icu_common.cpp",
260
260
  "src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp",
261
261
  "src/duckdb/extension/icu/third_party/icu/stubdata/stubdata.cpp",
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.8.2-dev2356.0",
5
+ "version": "0.8.2-dev2509.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
@@ -5,6 +5,8 @@
5
5
  #include "duckdb/common/operator/multiply.hpp"
6
6
  #include "duckdb/common/types/timestamp.hpp"
7
7
 
8
+ #include "unicode/ucal.h"
9
+
8
10
  namespace duckdb {
9
11
 
10
12
  ICUDateFunc::BindData::BindData(const BindData &other)
@@ -34,6 +36,13 @@ ICUDateFunc::BindData::BindData(ClientContext &context) {
34
36
  if (U_FAILURE(success)) {
35
37
  throw Exception("Unable to create ICU calendar.");
36
38
  }
39
+
40
+ // Postgres always assumes times are given in the proleptic Gregorian calendar.
41
+ // ICU defaults to the Gregorian change in 1582, so we reset the change to the minimum date
42
+ // so that all dates are proleptic Gregorian.
43
+ // The only error here is if we have a non-Gregorian calendar,
44
+ // and we just ignore that and hope for the best...
45
+ ucal_setGregorianChange((UCalendar *)calendar.get(), U_DATE_MIN, &success); // NOLINT
37
46
  }
38
47
 
39
48
  bool ICUDateFunc::BindData::Equals(const FunctionData &other_p) const {
@@ -109,11 +109,8 @@ struct ICUDatePart : public ICUDateFunc {
109
109
 
110
110
  static int64_t ExtractEpoch(icu::Calendar *calendar, const uint64_t micros) {
111
111
  UErrorCode status = U_ZERO_ERROR;
112
- auto millis = calendar->getTime(status);
113
- millis += ExtractField(calendar, UCAL_ZONE_OFFSET);
114
- millis += ExtractField(calendar, UCAL_DST_OFFSET);
115
112
  // Truncate
116
- return millis / Interval::MSECS_PER_SEC;
113
+ return calendar->getTime(status) / Interval::MSECS_PER_SEC;
117
114
  }
118
115
 
119
116
  static int64_t ExtractTimezone(icu::Calendar *calendar, const uint64_t micros) {
@@ -200,7 +197,12 @@ struct ICUDatePart : public ICUDateFunc {
200
197
 
201
198
  calendar->set(UCAL_DATE, dd);
202
199
 
203
- return Date::EpochToDate(ExtractEpoch(calendar, 0));
200
+ // Offset to UTC
201
+ auto millis = calendar->getTime(status);
202
+ millis += ExtractField(calendar, UCAL_ZONE_OFFSET);
203
+ millis += ExtractField(calendar, UCAL_DST_OFFSET);
204
+
205
+ return Date::EpochToDate(millis / Interval::MSECS_PER_SEC);
204
206
  }
205
207
 
206
208
  static string_t MonthName(icu::Calendar *calendar, const uint64_t micros) {
@@ -273,26 +273,7 @@ struct ICUStrptime : public ICUDateFunc {
273
273
  }
274
274
 
275
275
  // Now get the parts in the given time zone
276
- date_t d;
277
- dtime_t t;
278
- Timestamp::Convert(result, d, t);
279
-
280
- int32_t data[7];
281
- Date::Convert(d, data[0], data[1], data[2]);
282
- calendar->set(UCAL_EXTENDED_YEAR, data[0]); // strptime doesn't understand eras
283
- calendar->set(UCAL_MONTH, data[1] - 1);
284
- calendar->set(UCAL_DATE, data[2]);
285
-
286
- Time::Convert(t, data[3], data[4], data[5], data[6]);
287
- calendar->set(UCAL_HOUR_OF_DAY, data[3]);
288
- calendar->set(UCAL_MINUTE, data[4]);
289
- calendar->set(UCAL_SECOND, data[5]);
290
-
291
- int32_t millis = data[6] / Interval::MICROS_PER_MSEC;
292
- uint64_t micros = data[6] % Interval::MICROS_PER_MSEC;
293
- calendar->set(UCAL_MILLISECOND, millis);
294
-
295
- result = GetTime(calendar, micros);
276
+ result = FromNaive(calendar, result);
296
277
  }
297
278
 
298
279
  return result;
@@ -0,0 +1,78 @@
1
+ #include "duckdb/common/http_state.hpp"
2
+
3
+ namespace duckdb {
4
+
5
+ CachedFileHandle::CachedFileHandle(shared_ptr<CachedFile> &file_p) {
6
+ // If the file was not yet initialized, we need to grab a lock.
7
+ if (!file_p->initialized) {
8
+ lock = make_uniq<lock_guard<mutex>>(file_p->lock);
9
+ }
10
+ file = file_p;
11
+ }
12
+
13
+ void CachedFileHandle::SetInitialized() {
14
+ if (file->initialized) {
15
+ throw InternalException("Cannot set initialized on cached file that was already initialized");
16
+ }
17
+ if (!lock) {
18
+ throw InternalException("Cannot set initialized on cached file without lock");
19
+ }
20
+ file->initialized = true;
21
+ lock = nullptr;
22
+ }
23
+
24
+ void CachedFileHandle::AllocateBuffer(idx_t size) {
25
+ if (file->initialized) {
26
+ throw InternalException("Cannot allocate a buffer for a cached file that was already initialized");
27
+ }
28
+ file->data = std::shared_ptr<char>(new char[size], std::default_delete<char[]>());
29
+ file->capacity = size;
30
+ }
31
+
32
+ void CachedFileHandle::GrowBuffer(idx_t new_capacity, idx_t bytes_to_copy) {
33
+ // copy shared ptr to old data
34
+ auto old_data = file->data;
35
+ // allocate new buffer that can hold the new capacity
36
+ AllocateBuffer(new_capacity);
37
+ // copy the old data
38
+ Write(old_data.get(), bytes_to_copy);
39
+ }
40
+
41
+ void CachedFileHandle::Write(const char *buffer, idx_t length, idx_t offset) {
42
+ //! Only write to non-initialized files with a lock;
43
+ D_ASSERT(!file->initialized && lock);
44
+ memcpy(file->data.get() + offset, buffer, length);
45
+ }
46
+
47
+ void HTTPState::Reset() {
48
+ // Reset Counters
49
+ head_count = 0;
50
+ get_count = 0;
51
+ put_count = 0;
52
+ post_count = 0;
53
+ total_bytes_received = 0;
54
+ total_bytes_sent = 0;
55
+
56
+ // Reset cached files
57
+ cached_files.clear();
58
+ }
59
+
60
+ shared_ptr<HTTPState> HTTPState::TryGetState(FileOpener *opener) {
61
+ auto client_context = FileOpener::TryGetClientContext(opener);
62
+ if (client_context) {
63
+ return client_context->client_data->http_state;
64
+ }
65
+ return nullptr;
66
+ }
67
+
68
+ //! Get cache entry, create if not exists
69
+ shared_ptr<CachedFile> &HTTPState::GetCachedFile(const string &path) {
70
+ lock_guard<mutex> lock(cached_files_mutex);
71
+ auto &cache_entry_ref = cached_files[path];
72
+ if (!cache_entry_ref) {
73
+ cache_entry_ref = make_shared<CachedFile>();
74
+ }
75
+ return cache_entry_ref;
76
+ }
77
+
78
+ } // namespace duckdb
@@ -96,7 +96,7 @@ static uint16_t GetCapacityForNewSegment(uint16_t capacity) {
96
96
  }
97
97
 
98
98
  //===--------------------------------------------------------------------===//
99
- // Create & Destroy
99
+ // Create
100
100
  //===--------------------------------------------------------------------===//
101
101
  template <class T>
102
102
  static ListSegment *CreatePrimitiveSegment(const ListSegmentFunctions &, ArenaAllocator &allocator, uint16_t capacity) {
@@ -174,56 +174,55 @@ static ListSegment *GetSegment(const ListSegmentFunctions &functions, ArenaAlloc
174
174
  // Append
175
175
  //===--------------------------------------------------------------------===//
176
176
  template <class T>
177
- static void WriteDataToPrimitiveSegment(const ListSegmentFunctions &functions, ArenaAllocator &allocator,
178
- ListSegment *segment, Vector &input, idx_t &entry_idx, idx_t &count) {
177
+ static void WriteDataToPrimitiveSegment(const ListSegmentFunctions &, ArenaAllocator &, ListSegment *segment,
178
+ RecursiveUnifiedVectorFormat &input_data, idx_t &entry_idx) {
179
179
 
180
- // get the vector data and the source index of the entry that we want to write
181
- auto input_data = FlatVector::GetData(input);
180
+ auto sel_entry_idx = input_data.unified.sel->get_index(entry_idx);
182
181
 
183
182
  // write null validity
184
183
  auto null_mask = GetNullMask(segment);
185
- auto is_null = FlatVector::IsNull(input, entry_idx);
186
- null_mask[segment->count] = is_null;
184
+ auto valid = input_data.unified.validity.RowIsValid(sel_entry_idx);
185
+ null_mask[segment->count] = !valid;
187
186
 
188
187
  // write value
189
- if (!is_null) {
190
- auto data = GetPrimitiveData<T>(segment);
191
- Store<T>(((T *)input_data)[entry_idx], data_ptr_cast(data + segment->count));
188
+ if (valid) {
189
+ auto segment_data = GetPrimitiveData<T>(segment);
190
+ auto input_data_ptr = UnifiedVectorFormat::GetData<T>(input_data.unified);
191
+ Store<T>(input_data_ptr[sel_entry_idx], data_ptr_cast(segment_data + segment->count));
192
192
  }
193
193
  }
194
194
 
195
195
  static void WriteDataToVarcharSegment(const ListSegmentFunctions &functions, ArenaAllocator &allocator,
196
- ListSegment *segment, Vector &input, idx_t &entry_idx, idx_t &count) {
196
+ ListSegment *segment, RecursiveUnifiedVectorFormat &input_data,
197
+ idx_t &entry_idx) {
197
198
 
198
- // get the vector data and the source index of the entry that we want to write
199
- auto input_data = FlatVector::GetData<string_t>(input);
199
+ auto sel_entry_idx = input_data.unified.sel->get_index(entry_idx);
200
200
 
201
201
  // write null validity
202
202
  auto null_mask = GetNullMask(segment);
203
- auto is_null = FlatVector::IsNull(input, entry_idx);
204
- null_mask[segment->count] = is_null;
203
+ auto valid = input_data.unified.validity.RowIsValid(sel_entry_idx);
204
+ null_mask[segment->count] = !valid;
205
205
 
206
206
  // set the length of this string
207
207
  auto str_length_data = GetListLengthData(segment);
208
208
  uint64_t str_length = 0;
209
209
 
210
210
  // get the string
211
- string_t str_t;
212
- if (!is_null) {
213
- str_t = input_data[entry_idx];
214
- str_length = str_t.GetSize();
211
+ string_t str_entry;
212
+ if (valid) {
213
+ str_entry = UnifiedVectorFormat::GetData<string_t>(input_data.unified)[sel_entry_idx];
214
+ str_length = str_entry.GetSize();
215
215
  }
216
216
 
217
217
  // we can reconstruct the offset from the length
218
218
  Store<uint64_t>(str_length, data_ptr_cast(str_length_data + segment->count));
219
-
220
- if (is_null) {
219
+ if (!valid) {
221
220
  return;
222
221
  }
223
222
 
224
223
  // write the characters to the linked list of child segments
225
224
  auto child_segments = Load<LinkedList>(data_ptr_cast(GetListChildData(segment)));
226
- for (char &c : str_t.GetString()) {
225
+ for (char &c : str_entry.GetString()) {
227
226
  auto child_segment = GetSegment(functions.child_functions.back(), allocator, child_segments);
228
227
  auto data = GetPrimitiveData<char>(child_segment);
229
228
  data[child_segment->count] = c;
@@ -236,37 +235,31 @@ static void WriteDataToVarcharSegment(const ListSegmentFunctions &functions, Are
236
235
  }
237
236
 
238
237
  static void WriteDataToListSegment(const ListSegmentFunctions &functions, ArenaAllocator &allocator,
239
- ListSegment *segment, Vector &input, idx_t &entry_idx, idx_t &count) {
238
+ ListSegment *segment, RecursiveUnifiedVectorFormat &input_data, idx_t &entry_idx) {
240
239
 
241
- // get the vector data and the source index of the entry that we want to write
242
- auto input_data = FlatVector::GetData<list_entry_t>(input);
240
+ auto sel_entry_idx = input_data.unified.sel->get_index(entry_idx);
243
241
 
244
242
  // write null validity
245
243
  auto null_mask = GetNullMask(segment);
246
- auto is_null = FlatVector::IsNull(input, entry_idx);
247
- null_mask[segment->count] = is_null;
244
+ auto valid = input_data.unified.validity.RowIsValid(sel_entry_idx);
245
+ null_mask[segment->count] = !valid;
248
246
 
249
247
  // set the length of this list
250
248
  auto list_length_data = GetListLengthData(segment);
251
249
  uint64_t list_length = 0;
252
250
 
253
- if (!is_null) {
251
+ if (valid) {
254
252
  // get list entry information
255
- auto list_entries = input_data;
256
- const auto &list_entry = list_entries[entry_idx];
253
+ const auto &list_entry = UnifiedVectorFormat::GetData<list_entry_t>(input_data.unified)[sel_entry_idx];
257
254
  list_length = list_entry.length;
258
255
 
259
- // get the child vector and its data
260
- auto lists_size = ListVector::GetListSize(input);
261
- auto &child_vector = ListVector::GetEntry(input);
262
-
263
256
  // loop over the child vector entries and recurse on them
264
257
  auto child_segments = Load<LinkedList>(data_ptr_cast(GetListChildData(segment)));
265
258
  D_ASSERT(functions.child_functions.size() == 1);
266
259
  for (idx_t child_idx = 0; child_idx < list_entry.length; child_idx++) {
267
260
  auto source_idx_child = list_entry.offset + child_idx;
268
- functions.child_functions[0].AppendRow(allocator, child_segments, child_vector, source_idx_child,
269
- lists_size);
261
+ functions.child_functions[0].AppendRow(allocator, child_segments, input_data.children.back(),
262
+ source_idx_child);
270
263
  }
271
264
  // store the updated linked list
272
265
  Store<LinkedList>(child_segments, data_ptr_cast(GetListChildData(segment)));
@@ -276,35 +269,34 @@ static void WriteDataToListSegment(const ListSegmentFunctions &functions, ArenaA
276
269
  }
277
270
 
278
271
  static void WriteDataToStructSegment(const ListSegmentFunctions &functions, ArenaAllocator &allocator,
279
- ListSegment *segment, Vector &input, idx_t &entry_idx, idx_t &count) {
272
+ ListSegment *segment, RecursiveUnifiedVectorFormat &input_data, idx_t &entry_idx) {
273
+
274
+ auto sel_entry_idx = input_data.unified.sel->get_index(entry_idx);
280
275
 
281
276
  // write null validity
282
277
  auto null_mask = GetNullMask(segment);
283
- auto is_null = FlatVector::IsNull(input, entry_idx);
284
- null_mask[segment->count] = is_null;
278
+ auto valid = input_data.unified.validity.RowIsValid(sel_entry_idx);
279
+ null_mask[segment->count] = !valid;
285
280
 
286
281
  // write value
287
- auto &children = StructVector::GetEntries(input);
288
- D_ASSERT(children.size() == functions.child_functions.size());
282
+ D_ASSERT(input_data.children.size() == functions.child_functions.size());
289
283
  auto child_list = GetStructData(segment);
290
284
 
291
285
  // write the data of each of the children of the struct
292
- for (idx_t child_count = 0; child_count < children.size(); child_count++) {
293
- auto child_list_segment = Load<ListSegment *>(data_ptr_cast(child_list + child_count));
294
- auto &child_function = functions.child_functions[child_count];
295
- child_function.write_data(child_function, allocator, child_list_segment, *children[child_count], entry_idx,
296
- count);
286
+ for (idx_t i = 0; i < input_data.children.size(); i++) {
287
+ auto child_list_segment = Load<ListSegment *>(data_ptr_cast(child_list + i));
288
+ auto &child_function = functions.child_functions[i];
289
+ child_function.write_data(child_function, allocator, child_list_segment, input_data.children[i], entry_idx);
297
290
  child_list_segment->count++;
298
291
  }
299
292
  }
300
293
 
301
- void ListSegmentFunctions::AppendRow(ArenaAllocator &allocator, LinkedList &linked_list, Vector &input,
302
- idx_t &entry_idx, idx_t &count) const {
294
+ void ListSegmentFunctions::AppendRow(ArenaAllocator &allocator, LinkedList &linked_list,
295
+ RecursiveUnifiedVectorFormat &input_data, idx_t &entry_idx) const {
303
296
 
304
- D_ASSERT(input.GetVectorType() == VectorType::FLAT_VECTOR);
305
297
  auto &write_data_to_segment = *this;
306
298
  auto segment = GetSegment(write_data_to_segment, allocator, linked_list);
307
- write_data_to_segment.write_data(write_data_to_segment, allocator, segment, input, entry_idx, count);
299
+ write_data_to_segment.write_data(write_data_to_segment, allocator, segment, input_data, entry_idx);
308
300
 
309
301
  linked_list.total_capacity++;
310
302
  segment->count++;
@@ -458,86 +450,6 @@ void ListSegmentFunctions::BuildListVector(const LinkedList &linked_list, Vector
458
450
  }
459
451
  }
460
452
 
461
- //===--------------------------------------------------------------------===//
462
- // Copy
463
- //===--------------------------------------------------------------------===//
464
- template <class T>
465
- static ListSegment *CopyDataFromPrimitiveSegment(const ListSegmentFunctions &, const ListSegment *source,
466
- ArenaAllocator &allocator) {
467
-
468
- auto target = (ListSegment *)AllocatePrimitiveData<T>(allocator, source->capacity);
469
- memcpy(target, source, sizeof(ListSegment) + source->capacity * (sizeof(bool) + sizeof(T)));
470
- target->next = nullptr;
471
- return target;
472
- }
473
-
474
- static ListSegment *CopyDataFromListSegment(const ListSegmentFunctions &functions, const ListSegment *source,
475
- ArenaAllocator &allocator) {
476
-
477
- // create an empty linked list for the child vector of target
478
- auto source_linked_child_list = Load<LinkedList>(const_data_ptr_cast(GetListChildData(source)));
479
-
480
- // create the segment
481
- auto target = reinterpret_cast<ListSegment *>(AllocateListData(allocator, source->capacity));
482
- memcpy(target, source,
483
- sizeof(ListSegment) + source->capacity * (sizeof(bool) + sizeof(uint64_t)) + sizeof(LinkedList));
484
- target->next = nullptr;
485
-
486
- auto target_linked_list = GetListChildData(target);
487
- LinkedList linked_list(source_linked_child_list.total_capacity, nullptr, nullptr);
488
- Store<LinkedList>(linked_list, data_ptr_cast(target_linked_list));
489
-
490
- // recurse to copy the linked child list
491
- auto target_linked_child_list = Load<LinkedList>(data_ptr_cast(GetListChildData(target)));
492
- D_ASSERT(functions.child_functions.size() == 1);
493
- functions.child_functions[0].CopyLinkedList(source_linked_child_list, target_linked_child_list, allocator);
494
-
495
- // store the updated linked list
496
- Store<LinkedList>(target_linked_child_list, data_ptr_cast(GetListChildData(target)));
497
- return target;
498
- }
499
-
500
- static ListSegment *CopyDataFromStructSegment(const ListSegmentFunctions &functions, const ListSegment *source,
501
- ArenaAllocator &allocator) {
502
-
503
- auto source_child_count = functions.child_functions.size();
504
- auto target = reinterpret_cast<ListSegment *>(AllocateStructData(allocator, source->capacity, source_child_count));
505
- memcpy(target, source,
506
- sizeof(ListSegment) + source->capacity * sizeof(bool) + source_child_count * sizeof(ListSegment *));
507
- target->next = nullptr;
508
-
509
- // recurse and copy the children
510
- auto source_child_segments = GetStructData(source);
511
- auto target_child_segments = GetStructData(target);
512
-
513
- for (idx_t i = 0; i < functions.child_functions.size(); i++) {
514
- auto child_function = functions.child_functions[i];
515
- auto source_child_segment = Load<ListSegment *>(const_data_ptr_cast(source_child_segments + i));
516
- auto target_child_segment = child_function.copy_data(child_function, source_child_segment, allocator);
517
- Store<ListSegment *>(target_child_segment, data_ptr_cast(target_child_segments + i));
518
- }
519
- return target;
520
- }
521
-
522
- void ListSegmentFunctions::CopyLinkedList(const LinkedList &source_list, LinkedList &target_list,
523
- ArenaAllocator &allocator) const {
524
- auto &copy_data_from_segment = *this;
525
- auto source_segment = source_list.first_segment;
526
-
527
- while (source_segment) {
528
- auto target_segment = copy_data_from_segment.copy_data(copy_data_from_segment, source_segment, allocator);
529
- source_segment = source_segment->next;
530
-
531
- if (!target_list.first_segment) {
532
- target_list.first_segment = target_segment;
533
- }
534
- if (target_list.last_segment) {
535
- target_list.last_segment->next = target_segment;
536
- }
537
- target_list.last_segment = target_segment;
538
- }
539
- }
540
-
541
453
  //===--------------------------------------------------------------------===//
542
454
  // Functions
543
455
  //===--------------------------------------------------------------------===//
@@ -546,7 +458,6 @@ void SegmentPrimitiveFunction(ListSegmentFunctions &functions) {
546
458
  functions.create_segment = CreatePrimitiveSegment<T>;
547
459
  functions.write_data = WriteDataToPrimitiveSegment<T>;
548
460
  functions.read_data = ReadDataFromPrimitiveSegment<T>;
549
- functions.copy_data = CopyDataFromPrimitiveSegment<T>;
550
461
  }
551
462
 
552
463
  void GetSegmentDataFunctions(ListSegmentFunctions &functions, const LogicalType &type) {
@@ -597,7 +508,6 @@ void GetSegmentDataFunctions(ListSegmentFunctions &functions, const LogicalType
597
508
  functions.create_segment = CreateListSegment;
598
509
  functions.write_data = WriteDataToVarcharSegment;
599
510
  functions.read_data = ReadDataFromVarcharSegment;
600
- functions.copy_data = CopyDataFromListSegment;
601
511
 
602
512
  functions.child_functions.emplace_back();
603
513
  SegmentPrimitiveFunction<char>(functions.child_functions.back());
@@ -607,7 +517,6 @@ void GetSegmentDataFunctions(ListSegmentFunctions &functions, const LogicalType
607
517
  functions.create_segment = CreateListSegment;
608
518
  functions.write_data = WriteDataToListSegment;
609
519
  functions.read_data = ReadDataFromListSegment;
610
- functions.copy_data = CopyDataFromListSegment;
611
520
 
612
521
  // recurse
613
522
  functions.child_functions.emplace_back();
@@ -618,7 +527,6 @@ void GetSegmentDataFunctions(ListSegmentFunctions &functions, const LogicalType
618
527
  functions.create_segment = CreateStructSegment;
619
528
  functions.write_data = WriteDataToStructSegment;
620
529
  functions.read_data = ReadDataFromStructSegment;
621
- functions.copy_data = CopyDataFromStructSegment;
622
530
 
623
531
  // recurse
624
532
  auto child_types = StructType::GetChildTypes(type);
@@ -892,6 +892,27 @@ void Vector::ToUnifiedFormat(idx_t count, UnifiedVectorFormat &format) {
892
892
  }
893
893
  }
894
894
 
895
+ void Vector::RecursiveToUnifiedFormat(Vector &input, idx_t count, RecursiveUnifiedVectorFormat &data) {
896
+
897
+ input.ToUnifiedFormat(count, data.unified);
898
+
899
+ if (input.GetType().InternalType() == PhysicalType::LIST) {
900
+ auto &child = ListVector::GetEntry(input);
901
+ auto child_count = ListVector::GetListSize(input);
902
+ data.children.emplace_back();
903
+ Vector::RecursiveToUnifiedFormat(child, child_count, data.children.back());
904
+
905
+ } else if (input.GetType().InternalType() == PhysicalType::STRUCT) {
906
+ auto &children = StructVector::GetEntries(input);
907
+ for (idx_t i = 0; i < children.size(); i++) {
908
+ data.children.emplace_back();
909
+ }
910
+ for (idx_t i = 0; i < children.size(); i++) {
911
+ Vector::RecursiveToUnifiedFormat(*children[i], count, data.children[i]);
912
+ }
913
+ }
914
+ }
915
+
895
916
  void Vector::Sequence(int64_t start, int64_t increment, idx_t count) {
896
917
  this->vector_type = VectorType::SEQUENCE_VECTOR;
897
918
  this->buffer = make_buffer<VectorBuffer>(sizeof(int64_t) * 3);
@@ -31,8 +31,6 @@ struct hash<duckdb::hugeint_t> {
31
31
 
32
32
  namespace duckdb {
33
33
 
34
- using FrameBounds = std::pair<idx_t, idx_t>;
35
-
36
34
  template <class KEY_TYPE>
37
35
  struct ModeState {
38
36
  struct ModeAttr {
@@ -225,31 +223,31 @@ struct ModeFunction {
225
223
  if (state.nonzero <= tau * state.frequency_map->size()) {
226
224
  state.Reset();
227
225
  // for f ∈ F do
228
- for (auto f = frame.first; f < frame.second; ++f) {
226
+ for (auto f = frame.start; f < frame.end; ++f) {
229
227
  if (included(f)) {
230
228
  state.ModeAdd(KEY_TYPE(data[f]), f);
231
229
  }
232
230
  }
233
231
  } else {
234
232
  // for f ∈ P \ F do
235
- for (auto p = prev.first; p < frame.first; ++p) {
233
+ for (auto p = prev.start; p < frame.start; ++p) {
236
234
  if (included(p)) {
237
235
  state.ModeRm(KEY_TYPE(data[p]), p);
238
236
  }
239
237
  }
240
- for (auto p = frame.second; p < prev.second; ++p) {
238
+ for (auto p = frame.end; p < prev.end; ++p) {
241
239
  if (included(p)) {
242
240
  state.ModeRm(KEY_TYPE(data[p]), p);
243
241
  }
244
242
  }
245
243
 
246
244
  // for f ∈ F \ P do
247
- for (auto f = frame.first; f < prev.first; ++f) {
245
+ for (auto f = frame.start; f < prev.start; ++f) {
248
246
  if (included(f)) {
249
247
  state.ModeAdd(KEY_TYPE(data[f]), f);
250
248
  }
251
249
  }
252
- for (auto f = prev.second; f < frame.second; ++f) {
250
+ for (auto f = prev.end; f < frame.end; ++f) {
253
251
  if (included(f)) {
254
252
  state.ModeAdd(KEY_TYPE(data[f]), f);
255
253
  }