duckdb 0.3.2-dev454.0 → 0.3.2-dev483.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
- "version": "0.3.2-dev454.0",
4
+ "version": "0.3.2-dev483.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -421,7 +421,7 @@ public:
421
421
  string schema_name;
422
422
  //! Table name
423
423
  string table_name;
424
- //! Alises for the column names
424
+ //! Aliases for the column names
425
425
  vector<string> column_name_alias;
426
426
 
427
427
  public:
@@ -2380,7 +2380,7 @@ namespace duckdb {
2380
2380
  enum class AlterType : uint8_t { INVALID = 0, ALTER_TABLE = 1, ALTER_VIEW = 2 };
2381
2381
 
2382
2382
  struct AlterInfo : public ParseInfo {
2383
- AlterInfo(AlterType type, string schema, string name) : type(type), schema(schema), name(name) {
2383
+ AlterInfo(AlterType type, string schema, string name) : type(type), schema(move(schema)), name(move(name)) {
2384
2384
  }
2385
2385
  ~AlterInfo() override {
2386
2386
  }
@@ -29651,8 +29651,7 @@ void Deserializer::ReadStringVector(vector<string> &list) {
29651
29651
  namespace duckdb {
29652
29652
 
29653
29653
  struct SortLayout;
29654
- struct SortedBlock;
29655
- struct SortedData;
29654
+ struct SBScanState;
29656
29655
 
29657
29656
  using ValidityBytes = RowLayout::ValidityBytes;
29658
29657
 
@@ -29662,14 +29661,14 @@ public:
29662
29661
  static bool TieIsBreakable(const idx_t &col_idx, const data_ptr_t row_ptr, const RowLayout &row_layout);
29663
29662
  //! Compares the tuples that a being read from in the 'left' and 'right blocks during merge sort
29664
29663
  //! (only in case we cannot simply 'memcmp' - if there are blob columns)
29665
- static int CompareTuple(const SortedBlock &left, const SortedBlock &right, const data_ptr_t &l_ptr,
29664
+ static int CompareTuple(const SBScanState &left, const SBScanState &right, const data_ptr_t &l_ptr,
29666
29665
  const data_ptr_t &r_ptr, const SortLayout &sort_layout, const bool &external_sort);
29667
29666
  //! Compare two blob values
29668
29667
  static int CompareVal(const data_ptr_t l_ptr, const data_ptr_t r_ptr, const LogicalType &type);
29669
29668
 
29670
29669
  private:
29671
29670
  //! Compares two blob values that were initially tied by their prefix
29672
- static int BreakBlobTie(const idx_t &tie_col, const SortedData &left, const SortedData &right,
29671
+ static int BreakBlobTie(const idx_t &tie_col, const SBScanState &left, const SBScanState &right,
29673
29672
  const SortLayout &sort_layout, const bool &external);
29674
29673
  //! Compare two fixed-size values
29675
29674
  template <class T>
@@ -30423,59 +30422,36 @@ struct RowDataBlock;
30423
30422
  struct SortLayout;
30424
30423
  struct GlobalSortState;
30425
30424
 
30425
+ enum class SortedDataType { BLOB, PAYLOAD };
30426
+
30426
30427
  //! Object that holds sorted rows, and an accompanying heap if there are blobs
30427
30428
  struct SortedData {
30428
30429
  public:
30429
- SortedData(const RowLayout &layout, BufferManager &buffer_manager, GlobalSortState &state);
30430
+ SortedData(SortedDataType type, const RowLayout &layout, BufferManager &buffer_manager, GlobalSortState &state);
30430
30431
  //! Number of rows that this object holds
30431
30432
  idx_t Count();
30432
- //! Pin the current block so it can be read
30433
- void Pin();
30434
- //! Pointer to the row that is currently being read from
30435
- data_ptr_t DataPtr() const;
30436
- //! Pointer to the heap row that corresponds to the current row
30437
- data_ptr_t HeapPtr() const;
30438
- //! Advance one row
30439
- void Advance(const bool &adv);
30440
30433
  //! Initialize new block to write to
30441
30434
  void CreateBlock();
30442
- //! Reset read indices to the given indices
30443
- void ResetIndices(idx_t block_idx_to, idx_t entry_idx_to);
30444
30435
  //! Create a slice that holds the rows between the start and end indices
30445
- unique_ptr<SortedData> CreateSlice(idx_t start_block_index, idx_t start_entry_index, idx_t end_block_index,
30446
- idx_t end_entry_index);
30436
+ unique_ptr<SortedData> CreateSlice(idx_t start_block_index, idx_t end_block_index, idx_t end_entry_index);
30447
30437
  //! Unswizzles all
30448
30438
  void Unswizzle();
30449
30439
 
30450
30440
  public:
30441
+ const SortedDataType type;
30451
30442
  //! Layout of this data
30452
30443
  const RowLayout layout;
30453
30444
  //! Data and heap blocks
30454
30445
  vector<RowDataBlock> data_blocks;
30455
30446
  vector<RowDataBlock> heap_blocks;
30456
- //! Buffer handles to the data being currently read
30457
- unique_ptr<BufferHandle> data_handle;
30458
- unique_ptr<BufferHandle> heap_handle;
30459
- //! Read indices
30460
- idx_t block_idx;
30461
- idx_t entry_idx;
30462
30447
  //! Whether the pointers in this sorted data are swizzled
30463
30448
  bool swizzled;
30464
30449
 
30465
- private:
30466
- //! Pin fixed-size row data
30467
- void PinData();
30468
- //! Pin the accompanying heap data (if any)
30469
- void PinHeap();
30470
-
30471
30450
  private:
30472
30451
  //! The buffer manager
30473
30452
  BufferManager &buffer_manager;
30474
30453
  //! The global state
30475
30454
  GlobalSortState &state;
30476
- //! Pointers into the buffers being currently read
30477
- data_ptr_t data_ptr;
30478
- data_ptr_t heap_ptr;
30479
30455
  };
30480
30456
 
30481
30457
  //! Block that holds sorted rows: radix, blob and payload data
@@ -30484,21 +30460,17 @@ public:
30484
30460
  SortedBlock(BufferManager &buffer_manager, GlobalSortState &gstate);
30485
30461
  //! Number of rows that this object holds
30486
30462
  idx_t Count() const;
30487
- //! The remaining number of rows to be read from this object
30488
- idx_t Remaining() const;
30489
30463
  //! Initialize this block to write data to
30490
30464
  void InitializeWrite();
30491
30465
  //! Init new block to write to
30492
30466
  void CreateBlock();
30493
- //! Pins radix block with given index
30494
- void PinRadix(idx_t pin_block_idx);
30495
30467
  //! Fill this sorted block by appending the blocks held by a vector of sorted blocks
30496
30468
  void AppendSortedBlocks(vector<unique_ptr<SortedBlock>> &sorted_blocks);
30497
30469
  //! Locate the block and entry index of a row in this block,
30498
30470
  //! given an index between 0 and the total number of rows in this block
30499
30471
  void GlobalToLocalIndex(const idx_t &global_idx, idx_t &local_block_index, idx_t &local_entry_index);
30500
30472
  //! Create a slice that holds the rows between the start and end indices
30501
- unique_ptr<SortedBlock> CreateSlice(const idx_t start, const idx_t end);
30473
+ unique_ptr<SortedBlock> CreateSlice(const idx_t start, const idx_t end, idx_t &entry_idx);
30502
30474
 
30503
30475
  //! Size (in bytes) of the heap of this block
30504
30476
  idx_t HeapSize() const;
@@ -30508,25 +30480,59 @@ public:
30508
30480
  public:
30509
30481
  //! Radix/memcmp sortable data
30510
30482
  vector<RowDataBlock> radix_sorting_data;
30511
- unique_ptr<BufferHandle> radix_handle;
30512
- idx_t block_idx;
30513
- idx_t entry_idx;
30514
30483
  //! Variable sized sorting data
30515
30484
  unique_ptr<SortedData> blob_sorting_data;
30516
30485
  //! Payload data
30517
30486
  unique_ptr<SortedData> payload_data;
30518
30487
 
30519
30488
  private:
30520
- //! Buffer manager, and sorting layout constants
30489
+ //! Buffer manager, global state, and sorting layout constants
30521
30490
  BufferManager &buffer_manager;
30522
30491
  GlobalSortState &state;
30523
30492
  const SortLayout &sort_layout;
30524
30493
  const RowLayout &payload_layout;
30525
30494
  };
30526
30495
 
30527
- struct SortedDataScanner {
30496
+ //! State used to scan a SortedBlock e.g. during merge sort
30497
+ struct SBScanState {
30498
+ public:
30499
+ SBScanState(BufferManager &buffer_manager, GlobalSortState &state);
30500
+
30501
+ void PinRadix(idx_t block_idx_to);
30502
+ void PinData(SortedData &sd);
30503
+
30504
+ data_ptr_t RadixPtr() const;
30505
+ data_ptr_t DataPtr(SortedData &sd) const;
30506
+ data_ptr_t HeapPtr(SortedData &sd) const;
30507
+ data_ptr_t BaseHeapPtr(SortedData &sd) const;
30508
+
30509
+ idx_t Remaining() const;
30510
+
30511
+ void SetIndices(idx_t block_idx_to, idx_t entry_idx_to);
30512
+
30513
+ public:
30514
+ BufferManager &buffer_manager;
30515
+ const SortLayout &sort_layout;
30516
+ GlobalSortState &state;
30517
+
30518
+ SortedBlock *sb;
30519
+
30520
+ idx_t block_idx;
30521
+ idx_t entry_idx;
30522
+
30523
+ unique_ptr<BufferHandle> radix_handle = nullptr;
30524
+
30525
+ unique_ptr<BufferHandle> blob_sorting_data_handle = nullptr;
30526
+ unique_ptr<BufferHandle> blob_sorting_heap_handle = nullptr;
30527
+
30528
+ unique_ptr<BufferHandle> payload_data_handle = nullptr;
30529
+ unique_ptr<BufferHandle> payload_heap_handle = nullptr;
30530
+ };
30531
+
30532
+ //! Used to scan the data into DataChunks after sorting
30533
+ struct PayloadScanner {
30528
30534
  public:
30529
- SortedDataScanner(SortedData &sorted_data, GlobalSortState &global_sort_state);
30535
+ PayloadScanner(SortedData &sorted_data, GlobalSortState &global_sort_state);
30530
30536
 
30531
30537
  //! Scans the next data chunk from the sorted data
30532
30538
  void Scan(DataChunk &chunk);
@@ -30534,6 +30540,8 @@ public:
30534
30540
  private:
30535
30541
  //! The sorted data being scanned
30536
30542
  SortedData &sorted_data;
30543
+ //! Read state
30544
+ SBScanState read_state;
30537
30545
  //! The total count of sorted_data
30538
30546
  const idx_t total_count;
30539
30547
  //! The global sort state
@@ -30685,13 +30693,29 @@ public:
30685
30693
  //! Finds and merges partitions until the current cascaded merge round is finished
30686
30694
  void PerformInMergeRound();
30687
30695
 
30696
+ private:
30697
+ //! The global sorting state
30698
+ GlobalSortState &state;
30699
+ //! The sorting and payload layouts
30700
+ BufferManager &buffer_manager;
30701
+ const SortLayout &sort_layout;
30702
+
30703
+ //! The left and right reader
30704
+ unique_ptr<SBScanState> left;
30705
+ unique_ptr<SBScanState> right;
30706
+
30707
+ //! Input and output blocks
30708
+ unique_ptr<SortedBlock> left_input;
30709
+ unique_ptr<SortedBlock> right_input;
30710
+ SortedBlock *result;
30711
+
30688
30712
  private:
30689
30713
  //! Computes the left and right block that will be merged next (Merge Path partition)
30690
30714
  void GetNextPartition();
30691
30715
  //! Finds the boundary of the next partition using binary search
30692
- void GetIntersection(SortedBlock &l, SortedBlock &r, const idx_t diagonal, idx_t &l_idx, idx_t &r_idx);
30716
+ void GetIntersection(const idx_t diagonal, idx_t &l_idx, idx_t &r_idx);
30693
30717
  //! Compare values within SortedBlocks using a global index
30694
- int CompareUsingGlobalIndex(SortedBlock &l, SortedBlock &r, const idx_t l_idx, const idx_t r_idx);
30718
+ int CompareUsingGlobalIndex(SBScanState &l, SBScanState &r, const idx_t l_idx, const idx_t r_idx);
30695
30719
 
30696
30720
  //! Finds the next partition and merges it
30697
30721
  void MergePartition();
@@ -30703,7 +30727,7 @@ private:
30703
30727
  void MergeRadix(const idx_t &count, const bool left_smaller[]);
30704
30728
  //! Merges SortedData according to the 'left_smaller' array
30705
30729
  void MergeData(SortedData &result_data, SortedData &l_data, SortedData &r_data, const idx_t &count,
30706
- const bool left_smaller[], idx_t next_entry_sizes[]);
30730
+ const bool left_smaller[], idx_t next_entry_sizes[], bool reset_indices);
30707
30731
  //! Merges constant size rows according to the 'left_smaller' array
30708
30732
  void MergeRows(data_ptr_t &l_ptr, idx_t &l_entry_idx, const idx_t &l_count, data_ptr_t &r_ptr, idx_t &r_entry_idx,
30709
30733
  const idx_t &r_count, RowDataBlock *target_block, data_ptr_t &target_ptr, const idx_t &entry_size,
@@ -30717,18 +30741,6 @@ private:
30717
30741
  idx_t &source_entry_idx, data_ptr_t &source_heap_ptr, RowDataBlock *target_data_block,
30718
30742
  data_ptr_t &target_data_ptr, RowDataBlock *target_heap_block, BufferHandle &target_heap_handle,
30719
30743
  data_ptr_t &target_heap_ptr, idx_t &copied, const idx_t &count);
30720
-
30721
- private:
30722
- //! The global sorting state
30723
- GlobalSortState &state;
30724
- //! The sorting and payload layouts
30725
- BufferManager &buffer_manager;
30726
- const SortLayout &sort_layout;
30727
-
30728
- //! The left, right and result blocks of the current partition
30729
- unique_ptr<SortedBlock> left_block;
30730
- unique_ptr<SortedBlock> right_block;
30731
- SortedBlock *result;
30732
30744
  };
30733
30745
 
30734
30746
  } // namespace duckdb
@@ -30757,7 +30769,7 @@ bool Comparators::TieIsBreakable(const idx_t &col_idx, const data_ptr_t row_ptr,
30757
30769
  return true;
30758
30770
  }
30759
30771
 
30760
- int Comparators::CompareTuple(const SortedBlock &left, const SortedBlock &right, const data_ptr_t &l_ptr,
30772
+ int Comparators::CompareTuple(const SBScanState &left, const SBScanState &right, const data_ptr_t &l_ptr,
30761
30773
  const data_ptr_t &r_ptr, const SortLayout &sort_layout, const bool &external_sort) {
30762
30774
  // Compare the sorting columns one by one
30763
30775
  int comp_res = 0;
@@ -30766,8 +30778,7 @@ int Comparators::CompareTuple(const SortedBlock &left, const SortedBlock &right,
30766
30778
  for (idx_t col_idx = 0; col_idx < sort_layout.column_count; col_idx++) {
30767
30779
  comp_res = FastMemcmp(l_ptr_offset, r_ptr_offset, sort_layout.column_sizes[col_idx]);
30768
30780
  if (comp_res == 0 && !sort_layout.constant_size[col_idx]) {
30769
- comp_res =
30770
- BreakBlobTie(col_idx, *left.blob_sorting_data, *right.blob_sorting_data, sort_layout, external_sort);
30781
+ comp_res = BreakBlobTie(col_idx, left, right, sort_layout, external_sort);
30771
30782
  }
30772
30783
  if (comp_res != 0) {
30773
30784
  break;
@@ -30793,11 +30804,11 @@ int Comparators::CompareVal(const data_ptr_t l_ptr, const data_ptr_t r_ptr, cons
30793
30804
  }
30794
30805
  }
30795
30806
 
30796
- int Comparators::BreakBlobTie(const idx_t &tie_col, const SortedData &left, const SortedData &right,
30807
+ int Comparators::BreakBlobTie(const idx_t &tie_col, const SBScanState &left, const SBScanState &right,
30797
30808
  const SortLayout &sort_layout, const bool &external) {
30798
30809
  const idx_t &col_idx = sort_layout.sorting_to_blob_col.at(tie_col);
30799
- data_ptr_t l_data_ptr = left.DataPtr();
30800
- data_ptr_t r_data_ptr = right.DataPtr();
30810
+ data_ptr_t l_data_ptr = left.DataPtr(*left.sb->blob_sorting_data);
30811
+ data_ptr_t r_data_ptr = right.DataPtr(*right.sb->blob_sorting_data);
30801
30812
  if (!TieIsBreakable(col_idx, l_data_ptr, sort_layout.blob_layout)) {
30802
30813
  // Quick check to see if ties can be broken
30803
30814
  return 0;
@@ -30808,12 +30819,12 @@ int Comparators::BreakBlobTie(const idx_t &tie_col, const SortedData &left, cons
30808
30819
  r_data_ptr += tie_col_offset;
30809
30820
  // Do the comparison
30810
30821
  const int order = sort_layout.order_types[tie_col] == OrderType::DESCENDING ? -1 : 1;
30811
- const auto &type = left.layout.GetTypes()[col_idx];
30822
+ const auto &type = sort_layout.blob_layout.GetTypes()[col_idx];
30812
30823
  int result;
30813
30824
  if (external) {
30814
30825
  // Store heap pointers
30815
- data_ptr_t l_heap_ptr = left.HeapPtr();
30816
- data_ptr_t r_heap_ptr = right.HeapPtr();
30826
+ data_ptr_t l_heap_ptr = left.HeapPtr(*left.sb->blob_sorting_data);
30827
+ data_ptr_t r_heap_ptr = right.HeapPtr(*right.sb->blob_sorting_data);
30817
30828
  // Unswizzle offset to pointer
30818
30829
  UnswizzleSingleValue(l_data_ptr, l_heap_ptr, type);
30819
30830
  UnswizzleSingleValue(r_data_ptr, r_heap_ptr, type);
@@ -31114,21 +31125,23 @@ void MergeSorter::PerformInMergeRound() {
31114
31125
  }
31115
31126
 
31116
31127
  void MergeSorter::MergePartition() {
31117
- auto &left = *left_block;
31118
- auto &right = *right_block;
31128
+ auto &left_block = *left->sb;
31129
+ auto &right_block = *right->sb;
31119
31130
  #ifdef DEBUG
31120
- D_ASSERT(left.radix_sorting_data.size() == left.payload_data->data_blocks.size());
31121
- D_ASSERT(right.radix_sorting_data.size() == right.payload_data->data_blocks.size());
31131
+ D_ASSERT(left_block.radix_sorting_data.size() == left_block.payload_data->data_blocks.size());
31132
+ D_ASSERT(right_block.radix_sorting_data.size() == right_block.payload_data->data_blocks.size());
31122
31133
  if (!state.payload_layout.AllConstant() && state.external) {
31123
- D_ASSERT(left.payload_data->data_blocks.size() == left.payload_data->heap_blocks.size());
31124
- D_ASSERT(right.payload_data->data_blocks.size() == right.payload_data->heap_blocks.size());
31134
+ D_ASSERT(left_block.payload_data->data_blocks.size() == left_block.payload_data->heap_blocks.size());
31135
+ D_ASSERT(right_block.payload_data->data_blocks.size() == right_block.payload_data->heap_blocks.size());
31125
31136
  }
31126
31137
  if (!sort_layout.all_constant) {
31127
- D_ASSERT(left.radix_sorting_data.size() == left.blob_sorting_data->data_blocks.size());
31128
- D_ASSERT(right.radix_sorting_data.size() == right.blob_sorting_data->data_blocks.size());
31138
+ D_ASSERT(left_block.radix_sorting_data.size() == left_block.blob_sorting_data->data_blocks.size());
31139
+ D_ASSERT(right_block.radix_sorting_data.size() == right_block.blob_sorting_data->data_blocks.size());
31129
31140
  if (state.external) {
31130
- D_ASSERT(left.blob_sorting_data->data_blocks.size() == left.blob_sorting_data->heap_blocks.size());
31131
- D_ASSERT(right.blob_sorting_data->data_blocks.size() == right.blob_sorting_data->heap_blocks.size());
31141
+ D_ASSERT(left_block.blob_sorting_data->data_blocks.size() ==
31142
+ left_block.blob_sorting_data->heap_blocks.size());
31143
+ D_ASSERT(right_block.blob_sorting_data->data_blocks.size() ==
31144
+ right_block.blob_sorting_data->heap_blocks.size());
31132
31145
  }
31133
31146
  }
31134
31147
  #endif
@@ -31140,12 +31153,12 @@ void MergeSorter::MergePartition() {
31140
31153
  idx_t next_entry_sizes[STANDARD_VECTOR_SIZE];
31141
31154
  // Merge loop
31142
31155
  #ifdef DEBUG
31143
- auto l_count = left.Remaining();
31144
- auto r_count = right.Remaining();
31156
+ auto l_count = left->Remaining();
31157
+ auto r_count = right->Remaining();
31145
31158
  #endif
31146
31159
  while (true) {
31147
- auto l_remaining = left.Remaining();
31148
- auto r_remaining = right.Remaining();
31160
+ auto l_remaining = left->Remaining();
31161
+ auto r_remaining = right->Remaining();
31149
31162
  if (l_remaining + r_remaining == 0) {
31150
31163
  // Done
31151
31164
  break;
@@ -31158,17 +31171,12 @@ void MergeSorter::MergePartition() {
31158
31171
  // Actually merge the data (radix, blob, and payload)
31159
31172
  MergeRadix(next, left_smaller);
31160
31173
  if (!sort_layout.all_constant) {
31161
- MergeData(*result->blob_sorting_data, *left.blob_sorting_data, *right.blob_sorting_data, next, left_smaller,
31162
- next_entry_sizes);
31163
- D_ASSERT(left.block_idx == left.blob_sorting_data->block_idx &&
31164
- left.entry_idx == left.blob_sorting_data->entry_idx);
31165
- D_ASSERT(right.block_idx == right.blob_sorting_data->block_idx &&
31166
- right.entry_idx == right.blob_sorting_data->entry_idx);
31174
+ MergeData(*result->blob_sorting_data, *left_block.blob_sorting_data, *right_block.blob_sorting_data, next,
31175
+ left_smaller, next_entry_sizes, true);
31167
31176
  D_ASSERT(result->radix_sorting_data.size() == result->blob_sorting_data->data_blocks.size());
31168
31177
  }
31169
- MergeData(*result->payload_data, *left.payload_data, *right.payload_data, next, left_smaller, next_entry_sizes);
31170
- D_ASSERT(left.block_idx == left.payload_data->block_idx && left.entry_idx == left.payload_data->entry_idx);
31171
- D_ASSERT(right.block_idx == right.payload_data->block_idx && right.entry_idx == right.payload_data->entry_idx);
31178
+ MergeData(*result->payload_data, *left_block.payload_data, *right_block.payload_data, next, left_smaller,
31179
+ next_entry_sizes, false);
31172
31180
  D_ASSERT(result->radix_sorting_data.size() == result->payload_data->data_blocks.size());
31173
31181
  }
31174
31182
  #ifdef DEBUG
@@ -31181,34 +31189,39 @@ void MergeSorter::GetNextPartition() {
31181
31189
  state.sorted_blocks_temp[state.pair_idx].push_back(make_unique<SortedBlock>(buffer_manager, state));
31182
31190
  result = state.sorted_blocks_temp[state.pair_idx].back().get();
31183
31191
  // Determine which blocks must be merged
31184
- auto &left = *state.sorted_blocks[state.pair_idx * 2];
31185
- auto &right = *state.sorted_blocks[state.pair_idx * 2 + 1];
31186
- const idx_t l_count = left.Count();
31187
- const idx_t r_count = right.Count();
31192
+ auto &left_block = *state.sorted_blocks[state.pair_idx * 2];
31193
+ auto &right_block = *state.sorted_blocks[state.pair_idx * 2 + 1];
31194
+ const idx_t l_count = left_block.Count();
31195
+ const idx_t r_count = right_block.Count();
31196
+ // Initialize left and right reader
31197
+ left = make_unique<SBScanState>(buffer_manager, state);
31198
+ right = make_unique<SBScanState>(buffer_manager, state);
31188
31199
  // Compute the work that this thread must do using Merge Path
31189
31200
  idx_t l_end;
31190
31201
  idx_t r_end;
31191
31202
  if (state.l_start + state.r_start + state.block_capacity < l_count + r_count) {
31203
+ left->sb = state.sorted_blocks[state.pair_idx * 2].get();
31204
+ right->sb = state.sorted_blocks[state.pair_idx * 2 + 1].get();
31192
31205
  const idx_t intersection = state.l_start + state.r_start + state.block_capacity;
31193
- GetIntersection(left, right, intersection, l_end, r_end);
31206
+ GetIntersection(intersection, l_end, r_end);
31194
31207
  D_ASSERT(l_end <= l_count);
31195
31208
  D_ASSERT(r_end <= r_count);
31196
31209
  D_ASSERT(intersection == l_end + r_end);
31197
- // Unpin after finding the intersection
31198
- if (!sort_layout.blob_layout.AllConstant()) {
31199
- left.blob_sorting_data->ResetIndices(0, 0);
31200
- right.blob_sorting_data->ResetIndices(0, 0);
31201
- }
31202
31210
  } else {
31203
31211
  l_end = l_count;
31204
31212
  r_end = r_count;
31205
31213
  }
31206
31214
  // Create slices of the data that this thread must merge
31207
- left_block = left.CreateSlice(state.l_start, l_end);
31208
- right_block = right.CreateSlice(state.r_start, r_end);
31209
- // Update global state
31215
+ left->SetIndices(0, 0);
31216
+ right->SetIndices(0, 0);
31217
+ left_input = left_block.CreateSlice(state.l_start, l_end, left->entry_idx);
31218
+ right_input = right_block.CreateSlice(state.r_start, r_end, right->entry_idx);
31219
+ left->sb = left_input.get();
31220
+ right->sb = right_input.get();
31210
31221
  state.l_start = l_end;
31211
31222
  state.r_start = r_end;
31223
+ D_ASSERT(left->Remaining() + right->Remaining() == state.block_capacity || (l_end == l_count && r_end == r_count));
31224
+ // Update global state
31212
31225
  if (state.l_start == l_count && state.r_start == r_count) {
31213
31226
  // Delete references to previous pair
31214
31227
  state.sorted_blocks[state.pair_idx * 2] = nullptr;
@@ -31220,9 +31233,9 @@ void MergeSorter::GetNextPartition() {
31220
31233
  }
31221
31234
  }
31222
31235
 
31223
- int MergeSorter::CompareUsingGlobalIndex(SortedBlock &l, SortedBlock &r, const idx_t l_idx, const idx_t r_idx) {
31224
- D_ASSERT(l_idx < l.Count());
31225
- D_ASSERT(r_idx < r.Count());
31236
+ int MergeSorter::CompareUsingGlobalIndex(SBScanState &l, SBScanState &r, const idx_t l_idx, const idx_t r_idx) {
31237
+ D_ASSERT(l_idx < l.sb->Count());
31238
+ D_ASSERT(r_idx < r.sb->Count());
31226
31239
 
31227
31240
  // Easy comparison using the previous result (intersections must increase monotonically)
31228
31241
  if (l_idx < state.l_start) {
@@ -31232,37 +31245,28 @@ int MergeSorter::CompareUsingGlobalIndex(SortedBlock &l, SortedBlock &r, const i
31232
31245
  return 1;
31233
31246
  }
31234
31247
 
31235
- idx_t l_block_idx;
31236
- idx_t l_entry_idx;
31237
- l.GlobalToLocalIndex(l_idx, l_block_idx, l_entry_idx);
31238
-
31239
- idx_t r_block_idx;
31240
- idx_t r_entry_idx;
31241
- r.GlobalToLocalIndex(r_idx, r_block_idx, r_entry_idx);
31248
+ l.sb->GlobalToLocalIndex(l_idx, l.block_idx, l.entry_idx);
31249
+ r.sb->GlobalToLocalIndex(r_idx, r.block_idx, r.entry_idx);
31242
31250
 
31243
- l.PinRadix(l_block_idx);
31244
- r.PinRadix(r_block_idx);
31245
- data_ptr_t l_ptr = l.radix_handle->Ptr() + l_entry_idx * sort_layout.entry_size;
31246
- data_ptr_t r_ptr = r.radix_handle->Ptr() + r_entry_idx * sort_layout.entry_size;
31251
+ l.PinRadix(l.block_idx);
31252
+ r.PinRadix(r.block_idx);
31253
+ data_ptr_t l_ptr = l.radix_handle->Ptr() + l.entry_idx * sort_layout.entry_size;
31254
+ data_ptr_t r_ptr = r.radix_handle->Ptr() + r.entry_idx * sort_layout.entry_size;
31247
31255
 
31248
31256
  int comp_res;
31249
31257
  if (sort_layout.all_constant) {
31250
31258
  comp_res = FastMemcmp(l_ptr, r_ptr, sort_layout.comparison_size);
31251
31259
  } else {
31252
- l.blob_sorting_data->block_idx = l_block_idx;
31253
- l.blob_sorting_data->entry_idx = l_entry_idx;
31254
- l.blob_sorting_data->Pin();
31255
- r.blob_sorting_data->block_idx = r_block_idx;
31256
- r.blob_sorting_data->entry_idx = r_entry_idx;
31257
- r.blob_sorting_data->Pin();
31260
+ l.PinData(*l.sb->blob_sorting_data);
31261
+ r.PinData(*r.sb->blob_sorting_data);
31258
31262
  comp_res = Comparators::CompareTuple(l, r, l_ptr, r_ptr, sort_layout, state.external);
31259
31263
  }
31260
31264
  return comp_res;
31261
31265
  }
31262
31266
 
31263
- void MergeSorter::GetIntersection(SortedBlock &l, SortedBlock &r, const idx_t diagonal, idx_t &l_idx, idx_t &r_idx) {
31264
- const idx_t l_count = l.Count();
31265
- const idx_t r_count = r.Count();
31267
+ void MergeSorter::GetIntersection(const idx_t diagonal, idx_t &l_idx, idx_t &r_idx) {
31268
+ const idx_t l_count = left->sb->Count();
31269
+ const idx_t r_count = right->sb->Count();
31266
31270
  // Cover some edge cases
31267
31271
  // Code coverage off because these edge cases cannot happen unless other code changes
31268
31272
  // Edge cases have been tested extensively while developing Merge Path in a script
@@ -31292,16 +31296,16 @@ void MergeSorter::GetIntersection(SortedBlock &l, SortedBlock &r, const idx_t di
31292
31296
  const idx_t search_space = diagonal > MaxValue(l_count, r_count) ? l_count + r_count - diagonal
31293
31297
  : MinValue(diagonal, MinValue(l_count, r_count));
31294
31298
  // Double binary search
31295
- idx_t left = 0;
31296
- idx_t right = search_space - 1;
31299
+ idx_t li = 0;
31300
+ idx_t ri = search_space - 1;
31297
31301
  idx_t middle;
31298
31302
  int comp_res;
31299
- while (left <= right) {
31300
- middle = (left + right) / 2;
31303
+ while (li <= ri) {
31304
+ middle = (li + ri) / 2;
31301
31305
  l_idx = l_offset - middle;
31302
31306
  r_idx = r_offset + middle;
31303
31307
  if (l_idx == l_count || r_idx == 0) {
31304
- comp_res = CompareUsingGlobalIndex(l, r, l_idx - 1, r_idx);
31308
+ comp_res = CompareUsingGlobalIndex(*left, *right, l_idx - 1, r_idx);
31305
31309
  if (comp_res > 0) {
31306
31310
  l_idx--;
31307
31311
  r_idx++;
@@ -31318,15 +31322,15 @@ void MergeSorter::GetIntersection(SortedBlock &l, SortedBlock &r, const idx_t di
31318
31322
  break;
31319
31323
  }
31320
31324
  }
31321
- comp_res = CompareUsingGlobalIndex(l, r, l_idx, r_idx);
31325
+ comp_res = CompareUsingGlobalIndex(*left, *right, l_idx, r_idx);
31322
31326
  if (comp_res > 0) {
31323
- left = middle + 1;
31327
+ li = middle + 1;
31324
31328
  } else {
31325
- right = middle - 1;
31329
+ ri = middle - 1;
31326
31330
  }
31327
31331
  }
31328
- int l_r_min1 = CompareUsingGlobalIndex(l, r, l_idx, r_idx - 1);
31329
- int l_min1_r = CompareUsingGlobalIndex(l, r, l_idx - 1, r_idx);
31332
+ int l_r_min1 = CompareUsingGlobalIndex(*left, *right, l_idx, r_idx - 1);
31333
+ int l_min1_r = CompareUsingGlobalIndex(*left, *right, l_idx - 1, r_idx);
31330
31334
  if (l_r_min1 > 0 && l_min1_r < 0) {
31331
31335
  return;
31332
31336
  } else if (l_r_min1 > 0) {
@@ -31339,13 +31343,15 @@ void MergeSorter::GetIntersection(SortedBlock &l, SortedBlock &r, const idx_t di
31339
31343
  }
31340
31344
 
31341
31345
  void MergeSorter::ComputeMerge(const idx_t &count, bool left_smaller[]) {
31342
- auto &left = *left_block;
31343
- auto &right = *right_block;
31344
- // Store indices to restore after computing the merge
31345
- idx_t l_block_idx = left.block_idx;
31346
- idx_t r_block_idx = right.block_idx;
31347
- idx_t l_entry_idx = left.entry_idx;
31348
- idx_t r_entry_idx = right.entry_idx;
31346
+ auto &l = *left;
31347
+ auto &r = *right;
31348
+ auto &l_sorted_block = *l.sb;
31349
+ auto &r_sorted_block = *r.sb;
31350
+ // Save indices to restore afterwards
31351
+ idx_t l_block_idx_before = l.block_idx;
31352
+ idx_t l_entry_idx_before = l.entry_idx;
31353
+ idx_t r_block_idx_before = r.block_idx;
31354
+ idx_t r_entry_idx_before = r.entry_idx;
31349
31355
  // Data pointers for both sides
31350
31356
  data_ptr_t l_radix_ptr;
31351
31357
  data_ptr_t r_radix_ptr;
@@ -31353,91 +31359,84 @@ void MergeSorter::ComputeMerge(const idx_t &count, bool left_smaller[]) {
31353
31359
  idx_t compared = 0;
31354
31360
  while (compared < count) {
31355
31361
  // Move to the next block (if needed)
31356
- if (l_block_idx < left.radix_sorting_data.size() && l_entry_idx == left.radix_sorting_data[l_block_idx].count) {
31357
- l_block_idx++;
31358
- l_entry_idx = 0;
31359
- if (!sort_layout.all_constant) {
31360
- left.blob_sorting_data->block_idx = l_block_idx;
31361
- left.blob_sorting_data->entry_idx = l_entry_idx;
31362
- }
31363
- }
31364
- if (r_block_idx < right.radix_sorting_data.size() &&
31365
- r_entry_idx == right.radix_sorting_data[r_block_idx].count) {
31366
- r_block_idx++;
31367
- r_entry_idx = 0;
31368
- if (!sort_layout.all_constant) {
31369
- right.blob_sorting_data->block_idx = r_block_idx;
31370
- right.blob_sorting_data->entry_idx = r_entry_idx;
31371
- }
31372
- }
31373
- const bool l_done = l_block_idx == left.radix_sorting_data.size();
31374
- const bool r_done = r_block_idx == right.radix_sorting_data.size();
31362
+ if (l.block_idx < l_sorted_block.radix_sorting_data.size() &&
31363
+ l.entry_idx == l_sorted_block.radix_sorting_data[l.block_idx].count) {
31364
+ l.block_idx++;
31365
+ l.entry_idx = 0;
31366
+ }
31367
+ if (r.block_idx < r_sorted_block.radix_sorting_data.size() &&
31368
+ r.entry_idx == r_sorted_block.radix_sorting_data[r.block_idx].count) {
31369
+ r.block_idx++;
31370
+ r.entry_idx = 0;
31371
+ }
31372
+ const bool l_done = l.block_idx == l_sorted_block.radix_sorting_data.size();
31373
+ const bool r_done = r.block_idx == r_sorted_block.radix_sorting_data.size();
31375
31374
  if (l_done || r_done) {
31376
31375
  // One of the sides is exhausted, no need to compare
31377
31376
  break;
31378
31377
  }
31379
31378
  // Pin the radix sorting data
31380
31379
  if (!l_done) {
31381
- left.PinRadix(l_block_idx);
31382
- l_radix_ptr = left.radix_handle->Ptr() + l_entry_idx * sort_layout.entry_size;
31380
+ left->PinRadix(l.block_idx);
31381
+ l_radix_ptr = left->RadixPtr();
31383
31382
  }
31384
31383
  if (!r_done) {
31385
- right.PinRadix(r_block_idx);
31386
- r_radix_ptr = right.radix_handle->Ptr() + r_entry_idx * sort_layout.entry_size;
31384
+ right->PinRadix(r.block_idx);
31385
+ r_radix_ptr = right->RadixPtr();
31387
31386
  }
31388
- const idx_t &l_count = !l_done ? left.radix_sorting_data[l_block_idx].count : 0;
31389
- const idx_t &r_count = !r_done ? right.radix_sorting_data[r_block_idx].count : 0;
31387
+ const idx_t &l_count = !l_done ? l_sorted_block.radix_sorting_data[l.block_idx].count : 0;
31388
+ const idx_t &r_count = !r_done ? r_sorted_block.radix_sorting_data[r.block_idx].count : 0;
31390
31389
  // Compute the merge
31391
31390
  if (sort_layout.all_constant) {
31392
31391
  // All sorting columns are constant size
31393
- for (; compared < count && l_entry_idx < l_count && r_entry_idx < r_count; compared++) {
31392
+ for (; compared < count && l.entry_idx < l_count && r.entry_idx < r_count; compared++) {
31394
31393
  left_smaller[compared] = FastMemcmp(l_radix_ptr, r_radix_ptr, sort_layout.comparison_size) < 0;
31395
31394
  const bool &l_smaller = left_smaller[compared];
31396
31395
  const bool r_smaller = !l_smaller;
31397
31396
  // Use comparison bool (0 or 1) to increment entries and pointers
31398
- l_entry_idx += l_smaller;
31399
- r_entry_idx += r_smaller;
31397
+ l.entry_idx += l_smaller;
31398
+ r.entry_idx += r_smaller;
31400
31399
  l_radix_ptr += l_smaller * sort_layout.entry_size;
31401
31400
  r_radix_ptr += r_smaller * sort_layout.entry_size;
31402
31401
  }
31403
31402
  } else {
31404
31403
  // Pin the blob data
31405
31404
  if (!l_done) {
31406
- left.blob_sorting_data->Pin();
31405
+ left->PinData(*l_sorted_block.blob_sorting_data);
31407
31406
  }
31408
31407
  if (!r_done) {
31409
- right.blob_sorting_data->Pin();
31408
+ right->PinData(*r_sorted_block.blob_sorting_data);
31410
31409
  }
31411
31410
  // Merge with variable size sorting columns
31412
- for (; compared < count && l_entry_idx < l_count && r_entry_idx < r_count; compared++) {
31413
- D_ASSERT(l_block_idx == left.blob_sorting_data->block_idx &&
31414
- l_entry_idx == left.blob_sorting_data->entry_idx);
31415
- D_ASSERT(r_block_idx == right.blob_sorting_data->block_idx &&
31416
- r_entry_idx == right.blob_sorting_data->entry_idx);
31411
+ for (; compared < count && l.entry_idx < l_count && r.entry_idx < r_count; compared++) {
31417
31412
  left_smaller[compared] =
31418
- Comparators::CompareTuple(left, right, l_radix_ptr, r_radix_ptr, sort_layout, state.external) < 0;
31413
+ Comparators::CompareTuple(*left, *right, l_radix_ptr, r_radix_ptr, sort_layout, state.external) < 0;
31419
31414
  const bool &l_smaller = left_smaller[compared];
31420
31415
  const bool r_smaller = !l_smaller;
31421
31416
  // Use comparison bool (0 or 1) to increment entries and pointers
31422
- l_entry_idx += l_smaller;
31423
- r_entry_idx += r_smaller;
31417
+ l.entry_idx += l_smaller;
31418
+ r.entry_idx += r_smaller;
31424
31419
  l_radix_ptr += l_smaller * sort_layout.entry_size;
31425
31420
  r_radix_ptr += r_smaller * sort_layout.entry_size;
31426
- left.blob_sorting_data->Advance(l_smaller);
31427
- right.blob_sorting_data->Advance(r_smaller);
31428
31421
  }
31429
31422
  }
31430
31423
  }
31431
- // Reset block indices before the actual merge
31432
- if (!sort_layout.all_constant) {
31433
- left.blob_sorting_data->ResetIndices(left.block_idx, left.entry_idx);
31434
- right.blob_sorting_data->ResetIndices(right.block_idx, right.entry_idx);
31435
- }
31424
+ // Reset block indices
31425
+ left->SetIndices(l_block_idx_before, l_entry_idx_before);
31426
+ right->SetIndices(r_block_idx_before, r_entry_idx_before);
31436
31427
  }
31437
31428
 
31438
31429
  void MergeSorter::MergeRadix(const idx_t &count, const bool left_smaller[]) {
31439
- auto &left = *left_block;
31440
- auto &right = *right_block;
31430
+ auto &l = *left;
31431
+ auto &r = *right;
31432
+ // Save indices to restore afterwards
31433
+ idx_t l_block_idx_before = l.block_idx;
31434
+ idx_t l_entry_idx_before = l.entry_idx;
31435
+ idx_t r_block_idx_before = r.block_idx;
31436
+ idx_t r_entry_idx_before = r.entry_idx;
31437
+
31438
+ auto &l_blocks = l.sb->radix_sorting_data;
31439
+ auto &r_blocks = r.sb->radix_sorting_data;
31441
31440
  RowDataBlock *l_block;
31442
31441
  RowDataBlock *r_block;
31443
31442
 
@@ -31451,54 +31450,63 @@ void MergeSorter::MergeRadix(const idx_t &count, const bool left_smaller[]) {
31451
31450
  idx_t copied = 0;
31452
31451
  while (copied < count) {
31453
31452
  // Move to the next block (if needed)
31454
- if (left.block_idx < left.radix_sorting_data.size() &&
31455
- left.entry_idx == left.radix_sorting_data[left.block_idx].count) {
31453
+ if (l.block_idx < l_blocks.size() && l.entry_idx == l_blocks[l.block_idx].count) {
31456
31454
  // Delete reference to previous block
31457
- left.radix_sorting_data[left.block_idx].block = nullptr;
31455
+ l_blocks[l.block_idx].block = nullptr;
31458
31456
  // Advance block
31459
- left.block_idx++;
31460
- left.entry_idx = 0;
31457
+ l.block_idx++;
31458
+ l.entry_idx = 0;
31461
31459
  }
31462
- if (right.block_idx < right.radix_sorting_data.size() &&
31463
- right.entry_idx == right.radix_sorting_data[right.block_idx].count) {
31460
+ if (r.block_idx < r_blocks.size() && r.entry_idx == r_blocks[r.block_idx].count) {
31464
31461
  // Delete reference to previous block
31465
- right.radix_sorting_data[right.block_idx].block = nullptr;
31462
+ r_blocks[r.block_idx].block = nullptr;
31466
31463
  // Advance block
31467
- right.block_idx++;
31468
- right.entry_idx = 0;
31464
+ r.block_idx++;
31465
+ r.entry_idx = 0;
31469
31466
  }
31470
- const bool l_done = left.block_idx == left.radix_sorting_data.size();
31471
- const bool r_done = right.block_idx == right.radix_sorting_data.size();
31467
+ const bool l_done = l.block_idx == l_blocks.size();
31468
+ const bool r_done = r.block_idx == r_blocks.size();
31472
31469
  // Pin the radix sortable blocks
31473
31470
  if (!l_done) {
31474
- l_block = &left.radix_sorting_data[left.block_idx];
31475
- left.PinRadix(left.block_idx);
31476
- l_ptr = left.radix_handle->Ptr() + left.entry_idx * sort_layout.entry_size;
31471
+ l_block = &l_blocks[l.block_idx];
31472
+ left->PinRadix(l.block_idx);
31473
+ l_ptr = l.RadixPtr();
31477
31474
  }
31478
31475
  if (!r_done) {
31479
- r_block = &right.radix_sorting_data[right.block_idx];
31480
- right.PinRadix(right.block_idx);
31481
- r_ptr = right.radix_handle->Ptr() + right.entry_idx * sort_layout.entry_size;
31476
+ r_block = &r_blocks[r.block_idx];
31477
+ r.PinRadix(r.block_idx);
31478
+ r_ptr = r.RadixPtr();
31482
31479
  }
31483
31480
  const idx_t &l_count = !l_done ? l_block->count : 0;
31484
31481
  const idx_t &r_count = !r_done ? r_block->count : 0;
31485
31482
  // Copy using computed merge
31486
31483
  if (!l_done && !r_done) {
31487
31484
  // Both sides have data - merge
31488
- MergeRows(l_ptr, left.entry_idx, l_count, r_ptr, right.entry_idx, r_count, result_block, result_ptr,
31485
+ MergeRows(l_ptr, l.entry_idx, l_count, r_ptr, r.entry_idx, r_count, result_block, result_ptr,
31489
31486
  sort_layout.entry_size, left_smaller, copied, count);
31490
31487
  } else if (r_done) {
31491
31488
  // Right side is exhausted
31492
- FlushRows(l_ptr, left.entry_idx, l_count, result_block, result_ptr, sort_layout.entry_size, copied, count);
31489
+ FlushRows(l_ptr, l.entry_idx, l_count, result_block, result_ptr, sort_layout.entry_size, copied, count);
31493
31490
  } else {
31494
31491
  // Left side is exhausted
31495
- FlushRows(r_ptr, right.entry_idx, r_count, result_block, result_ptr, sort_layout.entry_size, copied, count);
31492
+ FlushRows(r_ptr, r.entry_idx, r_count, result_block, result_ptr, sort_layout.entry_size, copied, count);
31496
31493
  }
31497
31494
  }
31495
+ // Reset block indices
31496
+ left->SetIndices(l_block_idx_before, l_entry_idx_before);
31497
+ right->SetIndices(r_block_idx_before, r_entry_idx_before);
31498
31498
  }
31499
31499
 
31500
31500
  void MergeSorter::MergeData(SortedData &result_data, SortedData &l_data, SortedData &r_data, const idx_t &count,
31501
- const bool left_smaller[], idx_t next_entry_sizes[]) {
31501
+ const bool left_smaller[], idx_t next_entry_sizes[], bool reset_indices) {
31502
+ auto &l = *left;
31503
+ auto &r = *right;
31504
+ // Save indices to restore afterwards
31505
+ idx_t l_block_idx_before = l.block_idx;
31506
+ idx_t l_entry_idx_before = l.entry_idx;
31507
+ idx_t r_block_idx_before = r.block_idx;
31508
+ idx_t r_entry_idx_before = r.entry_idx;
31509
+
31502
31510
  const auto &layout = result_data.layout;
31503
31511
  const idx_t row_width = layout.GetRowWidth();
31504
31512
  const idx_t heap_pointer_offset = layout.GetHeapPointerOffset();
@@ -31527,76 +31535,70 @@ void MergeSorter::MergeData(SortedData &result_data, SortedData &l_data, SortedD
31527
31535
  idx_t copied = 0;
31528
31536
  while (copied < count) {
31529
31537
  // Move to new data blocks (if needed)
31530
- if (l_data.block_idx < l_data.data_blocks.size() &&
31531
- l_data.entry_idx == l_data.data_blocks[l_data.block_idx].count) {
31538
+ if (l.block_idx < l_data.data_blocks.size() && l.entry_idx == l_data.data_blocks[l.block_idx].count) {
31532
31539
  // Delete reference to previous block
31533
- l_data.data_blocks[l_data.block_idx].block = nullptr;
31540
+ l_data.data_blocks[l.block_idx].block = nullptr;
31534
31541
  if (!layout.AllConstant() && state.external) {
31535
- l_data.heap_blocks[l_data.block_idx].block = nullptr;
31542
+ l_data.heap_blocks[l.block_idx].block = nullptr;
31536
31543
  }
31537
31544
  // Advance block
31538
- l_data.block_idx++;
31539
- l_data.entry_idx = 0;
31545
+ l.block_idx++;
31546
+ l.entry_idx = 0;
31540
31547
  }
31541
- if (r_data.block_idx < r_data.data_blocks.size() &&
31542
- r_data.entry_idx == r_data.data_blocks[r_data.block_idx].count) {
31548
+ if (r.block_idx < r_data.data_blocks.size() && r.entry_idx == r_data.data_blocks[r.block_idx].count) {
31543
31549
  // Delete reference to previous block
31544
- r_data.data_blocks[r_data.block_idx].block = nullptr;
31550
+ r_data.data_blocks[r.block_idx].block = nullptr;
31545
31551
  if (!layout.AllConstant() && state.external) {
31546
- r_data.heap_blocks[r_data.block_idx].block = nullptr;
31552
+ r_data.heap_blocks[r.block_idx].block = nullptr;
31547
31553
  }
31548
31554
  // Advance block
31549
- r_data.block_idx++;
31550
- r_data.entry_idx = 0;
31555
+ r.block_idx++;
31556
+ r.entry_idx = 0;
31551
31557
  }
31552
- const bool l_done = l_data.block_idx == l_data.data_blocks.size();
31553
- const bool r_done = r_data.block_idx == r_data.data_blocks.size();
31558
+ const bool l_done = l.block_idx == l_data.data_blocks.size();
31559
+ const bool r_done = r.block_idx == r_data.data_blocks.size();
31554
31560
  // Pin the row data blocks
31555
31561
  if (!l_done) {
31556
- l_data.Pin();
31557
- l_ptr = l_data.data_handle->Ptr() + l_data.entry_idx * row_width;
31562
+ l.PinData(l_data);
31563
+ l_ptr = l.DataPtr(l_data);
31558
31564
  }
31559
31565
  if (!r_done) {
31560
- r_data.Pin();
31561
- r_ptr = r_data.data_handle->Ptr() + r_data.entry_idx * row_width;
31566
+ r.PinData(r_data);
31567
+ r_ptr = r.DataPtr(r_data);
31562
31568
  }
31563
- const idx_t &l_count = !l_done ? l_data.data_blocks[l_data.block_idx].count : 0;
31564
- const idx_t &r_count = !r_done ? r_data.data_blocks[r_data.block_idx].count : 0;
31569
+ const idx_t &l_count = !l_done ? l_data.data_blocks[l.block_idx].count : 0;
31570
+ const idx_t &r_count = !r_done ? r_data.data_blocks[r.block_idx].count : 0;
31565
31571
  // Perform the merge
31566
31572
  if (layout.AllConstant() || !state.external) {
31567
31573
  // If all constant size, or if we are doing an in-memory sort, we do not need to touch the heap
31568
31574
  if (!l_done && !r_done) {
31569
31575
  // Both sides have data - merge
31570
- MergeRows(l_ptr, l_data.entry_idx, l_count, r_ptr, r_data.entry_idx, r_count, result_data_block,
31571
- result_data_ptr, row_width, left_smaller, copied, count);
31576
+ MergeRows(l_ptr, l.entry_idx, l_count, r_ptr, r.entry_idx, r_count, result_data_block, result_data_ptr,
31577
+ row_width, left_smaller, copied, count);
31572
31578
  } else if (r_done) {
31573
31579
  // Right side is exhausted
31574
- FlushRows(l_ptr, l_data.entry_idx, l_count, result_data_block, result_data_ptr, row_width, copied,
31575
- count);
31580
+ FlushRows(l_ptr, l.entry_idx, l_count, result_data_block, result_data_ptr, row_width, copied, count);
31576
31581
  } else {
31577
31582
  // Left side is exhausted
31578
- FlushRows(r_ptr, r_data.entry_idx, r_count, result_data_block, result_data_ptr, row_width, copied,
31579
- count);
31583
+ FlushRows(r_ptr, r.entry_idx, r_count, result_data_block, result_data_ptr, row_width, copied, count);
31580
31584
  }
31581
31585
  } else {
31582
31586
  // External sorting with variable size data. Pin the heap blocks too
31583
31587
  if (!l_done) {
31584
- l_heap_ptr = l_data.heap_handle->Ptr() + Load<idx_t>(l_ptr + heap_pointer_offset);
31585
- D_ASSERT(l_heap_ptr - l_data.heap_handle->Ptr() >= 0);
31586
- D_ASSERT((idx_t)(l_heap_ptr - l_data.heap_handle->Ptr()) <
31587
- l_data.heap_blocks[l_data.block_idx].byte_offset);
31588
+ l_heap_ptr = l.BaseHeapPtr(l_data) + Load<idx_t>(l_ptr + heap_pointer_offset);
31589
+ D_ASSERT(l_heap_ptr - l.BaseHeapPtr(l_data) >= 0);
31590
+ D_ASSERT((idx_t)(l_heap_ptr - l.BaseHeapPtr(l_data)) < l_data.heap_blocks[l.block_idx].byte_offset);
31588
31591
  }
31589
31592
  if (!r_done) {
31590
- r_heap_ptr = r_data.heap_handle->Ptr() + Load<idx_t>(r_ptr + heap_pointer_offset);
31591
- D_ASSERT(r_heap_ptr - r_data.heap_handle->Ptr() >= 0);
31592
- D_ASSERT((idx_t)(r_heap_ptr - r_data.heap_handle->Ptr()) <
31593
- r_data.heap_blocks[r_data.block_idx].byte_offset);
31593
+ r_heap_ptr = r.BaseHeapPtr(r_data) + Load<idx_t>(r_ptr + heap_pointer_offset);
31594
+ D_ASSERT(r_heap_ptr - r.BaseHeapPtr(r_data) >= 0);
31595
+ D_ASSERT((idx_t)(r_heap_ptr - r.BaseHeapPtr(r_data)) < r_data.heap_blocks[r.block_idx].byte_offset);
31594
31596
  }
31595
31597
  // Both the row and heap data need to be dealt with
31596
31598
  if (!l_done && !r_done) {
31597
31599
  // Both sides have data - merge
31598
- idx_t l_idx_copy = l_data.entry_idx;
31599
- idx_t r_idx_copy = r_data.entry_idx;
31600
+ idx_t l_idx_copy = l.entry_idx;
31601
+ idx_t r_idx_copy = r.entry_idx;
31600
31602
  data_ptr_t result_data_ptr_copy = result_data_ptr;
31601
31603
  idx_t copied_copy = copied;
31602
31604
  // Merge row data
@@ -31618,10 +31620,10 @@ void MergeSorter::MergeData(SortedData &result_data, SortedData &l_data, SortedD
31618
31620
  entry_size =
31619
31621
  l_smaller * Load<uint32_t>(l_heap_ptr_copy) + r_smaller * Load<uint32_t>(r_heap_ptr_copy);
31620
31622
  D_ASSERT(entry_size >= sizeof(uint32_t));
31621
- D_ASSERT(l_heap_ptr_copy - l_data.heap_handle->Ptr() + l_smaller * entry_size <=
31622
- l_data.heap_blocks[l_data.block_idx].byte_offset);
31623
- D_ASSERT(r_heap_ptr_copy - r_data.heap_handle->Ptr() + r_smaller * entry_size <=
31624
- r_data.heap_blocks[r_data.block_idx].byte_offset);
31623
+ D_ASSERT(l_heap_ptr_copy - l.BaseHeapPtr(l_data) + l_smaller * entry_size <=
31624
+ l_data.heap_blocks[l.block_idx].byte_offset);
31625
+ D_ASSERT(r_heap_ptr_copy - r.BaseHeapPtr(r_data) + r_smaller * entry_size <=
31626
+ r_data.heap_blocks[r.block_idx].byte_offset);
31625
31627
  l_heap_ptr_copy += l_smaller * entry_size;
31626
31628
  r_heap_ptr_copy += r_smaller * entry_size;
31627
31629
  copy_bytes += entry_size;
@@ -31645,8 +31647,8 @@ void MergeSorter::MergeData(SortedData &result_data, SortedData &l_data, SortedD
31645
31647
  result_heap_ptr += entry_size;
31646
31648
  l_heap_ptr += l_smaller * entry_size;
31647
31649
  r_heap_ptr += r_smaller * entry_size;
31648
- l_data.entry_idx += l_smaller;
31649
- r_data.entry_idx += r_smaller;
31650
+ l.entry_idx += l_smaller;
31651
+ r.entry_idx += r_smaller;
31650
31652
  }
31651
31653
  // Update result indices and pointers
31652
31654
  result_heap_block->count += merged;
@@ -31654,16 +31656,20 @@ void MergeSorter::MergeData(SortedData &result_data, SortedData &l_data, SortedD
31654
31656
  copied += merged;
31655
31657
  } else if (r_done) {
31656
31658
  // Right side is exhausted - flush left
31657
- FlushBlobs(layout, l_count, l_ptr, l_data.entry_idx, l_heap_ptr, result_data_block, result_data_ptr,
31659
+ FlushBlobs(layout, l_count, l_ptr, l.entry_idx, l_heap_ptr, result_data_block, result_data_ptr,
31658
31660
  result_heap_block, *result_heap_handle, result_heap_ptr, copied, count);
31659
31661
  } else {
31660
31662
  // Left side is exhausted - flush right
31661
- FlushBlobs(layout, r_count, r_ptr, r_data.entry_idx, r_heap_ptr, result_data_block, result_data_ptr,
31663
+ FlushBlobs(layout, r_count, r_ptr, r.entry_idx, r_heap_ptr, result_data_block, result_data_ptr,
31662
31664
  result_heap_block, *result_heap_handle, result_heap_ptr, copied, count);
31663
31665
  }
31664
31666
  D_ASSERT(result_data_block->count == result_heap_block->count);
31665
31667
  }
31666
31668
  }
31669
+ if (reset_indices) {
31670
+ left->SetIndices(l_block_idx_before, l_entry_idx_before);
31671
+ right->SetIndices(r_block_idx_before, r_entry_idx_before);
31672
+ }
31667
31673
  }
31668
31674
 
31669
31675
  void MergeSorter::MergeRows(data_ptr_t &l_ptr, idx_t &l_entry_idx, const idx_t &l_count, data_ptr_t &r_ptr,
@@ -32638,8 +32644,9 @@ void GlobalSortState::CompleteMergeRound() {
32638
32644
 
32639
32645
  namespace duckdb {
32640
32646
 
32641
- SortedData::SortedData(const RowLayout &layout, BufferManager &buffer_manager, GlobalSortState &state)
32642
- : layout(layout), block_idx(0), entry_idx(0), swizzled(false), buffer_manager(buffer_manager), state(state) {
32647
+ SortedData::SortedData(SortedDataType type, const RowLayout &layout, BufferManager &buffer_manager,
32648
+ GlobalSortState &state)
32649
+ : type(type), layout(layout), swizzled(false), buffer_manager(buffer_manager), state(state) {
32643
32650
  }
32644
32651
 
32645
32652
  idx_t SortedData::Count() {
@@ -32652,37 +32659,6 @@ idx_t SortedData::Count() {
32652
32659
  return count;
32653
32660
  }
32654
32661
 
32655
- void SortedData::Pin() {
32656
- PinData();
32657
- if (!layout.AllConstant() && state.external) {
32658
- PinHeap();
32659
- }
32660
- }
32661
-
32662
- data_ptr_t SortedData::DataPtr() const {
32663
- D_ASSERT(data_blocks[block_idx].block->Readers() != 0 &&
32664
- data_handle->handle->BlockId() == data_blocks[block_idx].block->BlockId());
32665
- return data_ptr + entry_idx * layout.GetRowWidth();
32666
- }
32667
-
32668
- data_ptr_t SortedData::HeapPtr() const {
32669
- D_ASSERT(!layout.AllConstant() && state.external);
32670
- D_ASSERT(heap_blocks[block_idx].block->Readers() != 0 &&
32671
- heap_handle->handle->BlockId() == heap_blocks[block_idx].block->BlockId());
32672
- return heap_ptr + Load<idx_t>(DataPtr() + layout.GetHeapPointerOffset());
32673
- }
32674
-
32675
- void SortedData::Advance(const bool &adv) {
32676
- entry_idx += adv;
32677
- if (entry_idx == data_blocks[block_idx].count) {
32678
- block_idx++;
32679
- entry_idx = 0;
32680
- if (block_idx < data_blocks.size()) {
32681
- Pin();
32682
- }
32683
- }
32684
- }
32685
-
32686
32662
  void SortedData::CreateBlock() {
32687
32663
  auto capacity =
32688
32664
  MaxValue(((idx_t)Storage::BLOCK_SIZE + layout.GetRowWidth() - 1) / layout.GetRowWidth(), state.block_capacity);
@@ -32693,15 +32669,9 @@ void SortedData::CreateBlock() {
32693
32669
  }
32694
32670
  }
32695
32671
 
32696
- void SortedData::ResetIndices(idx_t block_idx_to, idx_t entry_idx_to) {
32697
- block_idx = block_idx_to;
32698
- entry_idx = entry_idx_to;
32699
- }
32700
-
32701
- unique_ptr<SortedData> SortedData::CreateSlice(idx_t start_block_index, idx_t start_entry_index, idx_t end_block_index,
32702
- idx_t end_entry_index) {
32672
+ unique_ptr<SortedData> SortedData::CreateSlice(idx_t start_block_index, idx_t end_block_index, idx_t end_entry_index) {
32703
32673
  // Add the corresponding blocks to the result
32704
- auto result = make_unique<SortedData>(layout, buffer_manager, state);
32674
+ auto result = make_unique<SortedData>(type, layout, buffer_manager, state);
32705
32675
  for (idx_t i = start_block_index; i <= end_block_index; i++) {
32706
32676
  result->data_blocks.push_back(data_blocks[i]);
32707
32677
  if (!layout.AllConstant() && state.external) {
@@ -32716,7 +32686,6 @@ unique_ptr<SortedData> SortedData::CreateSlice(idx_t start_block_index, idx_t st
32716
32686
  }
32717
32687
  }
32718
32688
  // Use start and end entry indices to set the boundaries
32719
- result->entry_idx = start_entry_index;
32720
32689
  D_ASSERT(end_entry_index <= result->data_blocks.back().count);
32721
32690
  result->data_blocks.back().count = end_entry_index;
32722
32691
  if (!layout.AllConstant() && state.external) {
@@ -32742,29 +32711,11 @@ void SortedData::Unswizzle() {
32742
32711
  heap_blocks.clear();
32743
32712
  }
32744
32713
 
32745
- void SortedData::PinData() {
32746
- D_ASSERT(block_idx < data_blocks.size());
32747
- auto &block = data_blocks[block_idx];
32748
- if (!data_handle || data_handle->handle->BlockId() != block.block->BlockId()) {
32749
- data_handle = buffer_manager.Pin(data_blocks[block_idx].block);
32750
- }
32751
- data_ptr = data_handle->Ptr();
32752
- }
32753
-
32754
- void SortedData::PinHeap() {
32755
- D_ASSERT(!layout.AllConstant() && state.external);
32756
- auto &block = heap_blocks[block_idx];
32757
- if (!heap_handle || heap_handle->handle->BlockId() != block.block->BlockId()) {
32758
- heap_handle = buffer_manager.Pin(heap_blocks[block_idx].block);
32759
- }
32760
- heap_ptr = heap_handle->Ptr();
32761
- }
32762
-
32763
32714
  SortedBlock::SortedBlock(BufferManager &buffer_manager, GlobalSortState &state)
32764
- : block_idx(0), entry_idx(0), buffer_manager(buffer_manager), state(state), sort_layout(state.sort_layout),
32715
+ : buffer_manager(buffer_manager), state(state), sort_layout(state.sort_layout),
32765
32716
  payload_layout(state.payload_layout) {
32766
- blob_sorting_data = make_unique<SortedData>(sort_layout.blob_layout, buffer_manager, state);
32767
- payload_data = make_unique<SortedData>(payload_layout, buffer_manager, state);
32717
+ blob_sorting_data = make_unique<SortedData>(SortedDataType::BLOB, sort_layout.blob_layout, buffer_manager, state);
32718
+ payload_data = make_unique<SortedData>(SortedDataType::PAYLOAD, payload_layout, buffer_manager, state);
32768
32719
  }
32769
32720
 
32770
32721
  idx_t SortedBlock::Count() const {
@@ -32777,17 +32728,6 @@ idx_t SortedBlock::Count() const {
32777
32728
  return count;
32778
32729
  }
32779
32730
 
32780
- idx_t SortedBlock::Remaining() const {
32781
- idx_t remaining = 0;
32782
- if (block_idx < radix_sorting_data.size()) {
32783
- remaining += radix_sorting_data[block_idx].count - entry_idx;
32784
- for (idx_t i = block_idx + 1; i < radix_sorting_data.size(); i++) {
32785
- remaining += radix_sorting_data[i].count;
32786
- }
32787
- }
32788
- return remaining;
32789
- }
32790
-
32791
32731
  void SortedBlock::InitializeWrite() {
32792
32732
  CreateBlock();
32793
32733
  if (!sort_layout.all_constant) {
@@ -32802,14 +32742,6 @@ void SortedBlock::CreateBlock() {
32802
32742
  radix_sorting_data.emplace_back(buffer_manager, capacity, sort_layout.entry_size);
32803
32743
  }
32804
32744
 
32805
- void SortedBlock::PinRadix(idx_t pin_block_idx) {
32806
- D_ASSERT(pin_block_idx < radix_sorting_data.size());
32807
- auto &block = radix_sorting_data[pin_block_idx];
32808
- if (!radix_handle || radix_handle->handle->BlockId() != block.block->BlockId()) {
32809
- radix_handle = buffer_manager.Pin(block.block);
32810
- }
32811
- }
32812
-
32813
32745
  void SortedBlock::AppendSortedBlocks(vector<unique_ptr<SortedBlock>> &sorted_blocks) {
32814
32746
  D_ASSERT(Count() == 0);
32815
32747
  for (auto &sb : sorted_blocks) {
@@ -32854,7 +32786,7 @@ void SortedBlock::GlobalToLocalIndex(const idx_t &global_idx, idx_t &local_block
32854
32786
  D_ASSERT(local_entry_index < radix_sorting_data[local_block_index].count);
32855
32787
  }
32856
32788
 
32857
- unique_ptr<SortedBlock> SortedBlock::CreateSlice(const idx_t start, const idx_t end) {
32789
+ unique_ptr<SortedBlock> SortedBlock::CreateSlice(const idx_t start, const idx_t end, idx_t &entry_idx) {
32858
32790
  // Identify blocks/entry indices of this slice
32859
32791
  idx_t start_block_index;
32860
32792
  idx_t start_entry_index;
@@ -32872,18 +32804,15 @@ unique_ptr<SortedBlock> SortedBlock::CreateSlice(const idx_t start, const idx_t
32872
32804
  radix_sorting_data[i].block = nullptr;
32873
32805
  }
32874
32806
  // Use start and end entry indices to set the boundaries
32875
- result->entry_idx = start_entry_index;
32807
+ entry_idx = start_entry_index;
32876
32808
  D_ASSERT(end_entry_index <= result->radix_sorting_data.back().count);
32877
32809
  result->radix_sorting_data.back().count = end_entry_index;
32878
32810
  // Same for the var size sorting data
32879
32811
  if (!sort_layout.all_constant) {
32880
- result->blob_sorting_data =
32881
- blob_sorting_data->CreateSlice(start_block_index, start_entry_index, end_block_index, end_entry_index);
32812
+ result->blob_sorting_data = blob_sorting_data->CreateSlice(start_block_index, end_block_index, end_entry_index);
32882
32813
  }
32883
32814
  // And the payload data
32884
- result->payload_data =
32885
- payload_data->CreateSlice(start_block_index, start_entry_index, end_block_index, end_entry_index);
32886
- D_ASSERT(result->Remaining() == end - start);
32815
+ result->payload_data = payload_data->CreateSlice(start_block_index, end_block_index, end_entry_index);
32887
32816
  return result;
32888
32817
  }
32889
32818
 
@@ -32918,19 +32847,90 @@ idx_t SortedBlock::SizeInBytes() const {
32918
32847
  return bytes;
32919
32848
  }
32920
32849
 
32921
- SortedDataScanner::SortedDataScanner(SortedData &sorted_data, GlobalSortState &global_sort_state)
32922
- : sorted_data(sorted_data), total_count(sorted_data.Count()), global_sort_state(global_sort_state),
32923
- total_scanned(0) {
32850
+ SBScanState::SBScanState(BufferManager &buffer_manager, GlobalSortState &state)
32851
+ : buffer_manager(buffer_manager), sort_layout(state.sort_layout), state(state), block_idx(0), entry_idx(0) {
32852
+ }
32853
+
32854
+ void SBScanState::PinRadix(idx_t block_idx_to) {
32855
+ auto &radix_sorting_data = sb->radix_sorting_data;
32856
+ D_ASSERT(block_idx_to < radix_sorting_data.size());
32857
+ auto &block = radix_sorting_data[block_idx_to];
32858
+ if (!radix_handle || radix_handle->handle->BlockId() != block.block->BlockId()) {
32859
+ radix_handle = buffer_manager.Pin(block.block);
32860
+ }
32861
+ }
32862
+
32863
+ void SBScanState::PinData(SortedData &sd) {
32864
+ D_ASSERT(block_idx < sd.data_blocks.size());
32865
+ auto &data_handle = sd.type == SortedDataType::BLOB ? blob_sorting_data_handle : payload_data_handle;
32866
+ auto &heap_handle = sd.type == SortedDataType::BLOB ? blob_sorting_heap_handle : payload_heap_handle;
32867
+
32868
+ auto &data_block = sd.data_blocks[block_idx];
32869
+ if (!data_handle || data_handle->handle->BlockId() != data_block.block->BlockId()) {
32870
+ data_handle = buffer_manager.Pin(data_block.block);
32871
+ }
32872
+ if (sd.layout.AllConstant() || !state.external) {
32873
+ return;
32874
+ }
32875
+ auto &heap_block = sd.heap_blocks[block_idx];
32876
+ if (!heap_handle || heap_handle->handle->BlockId() != heap_block.block->BlockId()) {
32877
+ heap_handle = buffer_manager.Pin(heap_block.block);
32878
+ }
32879
+ }
32880
+
32881
+ data_ptr_t SBScanState::RadixPtr() const {
32882
+ return radix_handle->Ptr() + entry_idx * sort_layout.entry_size;
32883
+ }
32884
+
32885
+ data_ptr_t SBScanState::DataPtr(SortedData &sd) const {
32886
+ auto &data_handle = sd.type == SortedDataType::BLOB ? *blob_sorting_data_handle : *payload_data_handle;
32887
+ D_ASSERT(sd.data_blocks[block_idx].block->Readers() != 0 &&
32888
+ data_handle.handle->BlockId() == sd.data_blocks[block_idx].block->BlockId());
32889
+ return data_handle.Ptr() + entry_idx * sd.layout.GetRowWidth();
32890
+ }
32891
+
32892
+ data_ptr_t SBScanState::HeapPtr(SortedData &sd) const {
32893
+ return BaseHeapPtr(sd) + Load<idx_t>(DataPtr(sd) + sd.layout.GetHeapPointerOffset());
32894
+ }
32895
+
32896
+ data_ptr_t SBScanState::BaseHeapPtr(SortedData &sd) const {
32897
+ auto &heap_handle = sd.type == SortedDataType::BLOB ? *blob_sorting_heap_handle : *payload_heap_handle;
32898
+ D_ASSERT(!sd.layout.AllConstant() && state.external);
32899
+ D_ASSERT(sd.heap_blocks[block_idx].block->Readers() != 0 &&
32900
+ heap_handle.handle->BlockId() == sd.heap_blocks[block_idx].block->BlockId());
32901
+ return heap_handle.Ptr();
32902
+ }
32903
+
32904
+ idx_t SBScanState::Remaining() const {
32905
+ const auto &blocks = sb->radix_sorting_data;
32906
+ idx_t remaining = 0;
32907
+ if (block_idx < blocks.size()) {
32908
+ remaining += blocks[block_idx].count - entry_idx;
32909
+ for (idx_t i = block_idx + 1; i < blocks.size(); i++) {
32910
+ remaining += blocks[i].count;
32911
+ }
32912
+ }
32913
+ return remaining;
32914
+ }
32915
+
32916
+ void SBScanState::SetIndices(idx_t block_idx_to, idx_t entry_idx_to) {
32917
+ block_idx = block_idx_to;
32918
+ entry_idx = entry_idx_to;
32919
+ }
32920
+
32921
+ PayloadScanner::PayloadScanner(SortedData &sorted_data, GlobalSortState &global_sort_state)
32922
+ : sorted_data(sorted_data), read_state(global_sort_state.buffer_manager, global_sort_state),
32923
+ total_count(sorted_data.Count()), global_sort_state(global_sort_state), total_scanned(0) {
32924
32924
  }
32925
32925
 
32926
- void SortedDataScanner::Scan(DataChunk &chunk) {
32926
+ void PayloadScanner::Scan(DataChunk &chunk) {
32927
32927
  auto count = MinValue((idx_t)STANDARD_VECTOR_SIZE, total_count - total_scanned);
32928
32928
  if (count == 0) {
32929
- D_ASSERT(sorted_data.block_idx == sorted_data.data_blocks.size());
32929
+ D_ASSERT(read_state.block_idx == sorted_data.data_blocks.size());
32930
32930
  return;
32931
32931
  }
32932
32932
  // Eagerly delete references to blocks that we've passed
32933
- for (idx_t i = 0; i < sorted_data.block_idx; i++) {
32933
+ for (idx_t i = 0; i < read_state.block_idx; i++) {
32934
32934
  sorted_data.data_blocks[i].block = nullptr;
32935
32935
  }
32936
32936
  const idx_t &row_width = sorted_data.layout.GetRowWidth();
@@ -32938,10 +32938,10 @@ void SortedDataScanner::Scan(DataChunk &chunk) {
32938
32938
  idx_t scanned = 0;
32939
32939
  auto data_pointers = FlatVector::GetData<data_ptr_t>(addresses);
32940
32940
  while (scanned < count) {
32941
- sorted_data.Pin();
32942
- auto &data_block = sorted_data.data_blocks[sorted_data.block_idx];
32943
- idx_t next = MinValue(data_block.count - sorted_data.entry_idx, count - scanned);
32944
- const data_ptr_t data_ptr = sorted_data.data_handle->Ptr() + sorted_data.entry_idx * row_width;
32941
+ read_state.PinData(sorted_data);
32942
+ auto &data_block = sorted_data.data_blocks[read_state.block_idx];
32943
+ idx_t next = MinValue(data_block.count - read_state.entry_idx, count - scanned);
32944
+ const data_ptr_t data_ptr = read_state.payload_data_handle->Ptr() + read_state.entry_idx * row_width;
32945
32945
  // Set up the next pointers
32946
32946
  data_ptr_t row_ptr = data_ptr;
32947
32947
  for (idx_t i = 0; i < next; i++) {
@@ -32950,14 +32950,15 @@ void SortedDataScanner::Scan(DataChunk &chunk) {
32950
32950
  }
32951
32951
  // Unswizzle the offsets back to pointers (if needed)
32952
32952
  if (!sorted_data.layout.AllConstant() && global_sort_state.external) {
32953
- RowOperations::UnswizzleHeapPointer(sorted_data.layout, data_ptr, sorted_data.heap_handle->Ptr(), next);
32953
+ RowOperations::UnswizzleHeapPointer(sorted_data.layout, data_ptr, read_state.payload_heap_handle->Ptr(),
32954
+ next);
32954
32955
  RowOperations::UnswizzleColumns(sorted_data.layout, data_ptr, next);
32955
32956
  }
32956
32957
  // Update state indices
32957
- sorted_data.entry_idx += next;
32958
- if (sorted_data.entry_idx == data_block.count) {
32959
- sorted_data.block_idx++;
32960
- sorted_data.entry_idx = 0;
32958
+ read_state.entry_idx += next;
32959
+ if (read_state.entry_idx == data_block.count) {
32960
+ read_state.block_idx++;
32961
+ read_state.entry_idx = 0;
32961
32962
  }
32962
32963
  scanned += next;
32963
32964
  }
@@ -56551,7 +56552,7 @@ static void ScanSortedPartition(WindowOperatorState &state, ChunkCollection &inp
56551
56552
  payload_types.insert(payload_types.end(), over_types.begin(), over_types.end());
56552
56553
 
56553
56554
  // scan the sorted row data
56554
- SortedDataScanner scanner(*global_sort_state.sorted_blocks[0]->payload_data, global_sort_state);
56555
+ PayloadScanner scanner(*global_sort_state.sorted_blocks[0]->payload_data, global_sort_state);
56555
56556
  for (;;) {
56556
56557
  DataChunk payload_chunk;
56557
56558
  payload_chunk.Initialize(payload_types);
@@ -62364,7 +62365,7 @@ void PhysicalOrder::ScheduleMergeTasks(Pipeline &pipeline, Event &event, OrderGl
62364
62365
  class PhysicalOrderOperatorState : public GlobalSourceState {
62365
62366
  public:
62366
62367
  //! Payload scanner
62367
- unique_ptr<SortedDataScanner> scanner;
62368
+ unique_ptr<PayloadScanner> scanner;
62368
62369
  };
62369
62370
 
62370
62371
  unique_ptr<GlobalSourceState> PhysicalOrder::GetGlobalSourceState(ClientContext &context) const {
@@ -62383,7 +62384,7 @@ void PhysicalOrder::GetData(ExecutionContext &context, DataChunk &chunk, GlobalS
62383
62384
  return;
62384
62385
  }
62385
62386
  state.scanner =
62386
- make_unique<SortedDataScanner>(*global_sort_state.sorted_blocks[0]->payload_data, global_sort_state);
62387
+ make_unique<PayloadScanner>(*global_sort_state.sorted_blocks[0]->payload_data, global_sort_state);
62387
62388
  }
62388
62389
 
62389
62390
  // Scan the next data chunk
@@ -62483,7 +62484,7 @@ PhysicalTopN::PhysicalTopN(vector<LogicalType> types, vector<BoundOrderByNode> o
62483
62484
  class TopNHeap;
62484
62485
 
62485
62486
  struct TopNScanState {
62486
- unique_ptr<SortedDataScanner> scanner;
62487
+ unique_ptr<PayloadScanner> scanner;
62487
62488
  idx_t pos;
62488
62489
  bool exclude_offset;
62489
62490
  };
@@ -62613,7 +62614,7 @@ void TopNSortState::InitializeScan(TopNScanState &state, bool exclude_offset) {
62613
62614
  state.scanner = nullptr;
62614
62615
  } else {
62615
62616
  D_ASSERT(global_state->sorted_blocks.size() == 1);
62616
- state.scanner = make_unique<SortedDataScanner>(*global_state->sorted_blocks[0]->payload_data, *global_state);
62617
+ state.scanner = make_unique<PayloadScanner>(*global_state->sorted_blocks[0]->payload_data, *global_state);
62617
62618
  }
62618
62619
  state.pos = 0;
62619
62620
  state.exclude_offset = exclude_offset && heap.offset > 0;
@@ -114512,7 +114513,7 @@ public:
114512
114513
 
114513
114514
  //! The subquery
114514
114515
  unique_ptr<SelectStatement> subquery;
114515
- //! Alises for the column names
114516
+ //! Aliases for the column names
114516
114517
  vector<string> column_name_alias;
114517
114518
 
114518
114519
  public:
package/src/duckdb.hpp CHANGED
@@ -10,8 +10,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
10
10
 
11
11
  #pragma once
12
12
  #define DUCKDB_AMALGAMATION 1
13
- #define DUCKDB_SOURCE_ID "29e6c2865"
14
- #define DUCKDB_VERSION "0.3.2-dev454"
13
+ #define DUCKDB_SOURCE_ID "9ee0227d8"
14
+ #define DUCKDB_VERSION "0.3.2-dev483"
15
15
  //===----------------------------------------------------------------------===//
16
16
  // DuckDB
17
17
  //