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 +1 -1
- package/src/duckdb.cpp +369 -368
- package/src/duckdb.hpp +2 -2
package/package.json
CHANGED
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
|
-
//!
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
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 &
|
|
31118
|
-
auto &
|
|
31128
|
+
auto &left_block = *left->sb;
|
|
31129
|
+
auto &right_block = *right->sb;
|
|
31119
31130
|
#ifdef DEBUG
|
|
31120
|
-
D_ASSERT(
|
|
31121
|
-
D_ASSERT(
|
|
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(
|
|
31124
|
-
D_ASSERT(
|
|
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(
|
|
31128
|
-
D_ASSERT(
|
|
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(
|
|
31131
|
-
|
|
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
|
|
31144
|
-
auto r_count = right
|
|
31156
|
+
auto l_count = left->Remaining();
|
|
31157
|
+
auto r_count = right->Remaining();
|
|
31145
31158
|
#endif
|
|
31146
31159
|
while (true) {
|
|
31147
|
-
auto l_remaining = left
|
|
31148
|
-
auto r_remaining = right
|
|
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, *
|
|
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, *
|
|
31170
|
-
|
|
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 &
|
|
31185
|
-
auto &
|
|
31186
|
-
const idx_t l_count =
|
|
31187
|
-
const idx_t r_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(
|
|
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
|
-
|
|
31208
|
-
|
|
31209
|
-
|
|
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(
|
|
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
|
-
|
|
31236
|
-
|
|
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(
|
|
31244
|
-
r.PinRadix(
|
|
31245
|
-
data_ptr_t l_ptr = l.radix_handle->Ptr() +
|
|
31246
|
-
data_ptr_t r_ptr = r.radix_handle->Ptr() +
|
|
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
|
|
31253
|
-
|
|
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(
|
|
31264
|
-
const idx_t l_count =
|
|
31265
|
-
const idx_t 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
|
|
31296
|
-
idx_t
|
|
31299
|
+
idx_t li = 0;
|
|
31300
|
+
idx_t ri = search_space - 1;
|
|
31297
31301
|
idx_t middle;
|
|
31298
31302
|
int comp_res;
|
|
31299
|
-
while (
|
|
31300
|
-
middle = (
|
|
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(
|
|
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(
|
|
31325
|
+
comp_res = CompareUsingGlobalIndex(*left, *right, l_idx, r_idx);
|
|
31322
31326
|
if (comp_res > 0) {
|
|
31323
|
-
|
|
31327
|
+
li = middle + 1;
|
|
31324
31328
|
} else {
|
|
31325
|
-
|
|
31329
|
+
ri = middle - 1;
|
|
31326
31330
|
}
|
|
31327
31331
|
}
|
|
31328
|
-
int l_r_min1 = CompareUsingGlobalIndex(
|
|
31329
|
-
int l_min1_r = CompareUsingGlobalIndex(
|
|
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 &
|
|
31343
|
-
auto &
|
|
31344
|
-
|
|
31345
|
-
|
|
31346
|
-
|
|
31347
|
-
idx_t
|
|
31348
|
-
idx_t
|
|
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 (
|
|
31357
|
-
|
|
31358
|
-
|
|
31359
|
-
|
|
31360
|
-
|
|
31361
|
-
|
|
31362
|
-
|
|
31363
|
-
|
|
31364
|
-
|
|
31365
|
-
|
|
31366
|
-
|
|
31367
|
-
|
|
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
|
|
31382
|
-
l_radix_ptr = left
|
|
31380
|
+
left->PinRadix(l.block_idx);
|
|
31381
|
+
l_radix_ptr = left->RadixPtr();
|
|
31383
31382
|
}
|
|
31384
31383
|
if (!r_done) {
|
|
31385
|
-
right
|
|
31386
|
-
r_radix_ptr = right
|
|
31384
|
+
right->PinRadix(r.block_idx);
|
|
31385
|
+
r_radix_ptr = right->RadixPtr();
|
|
31387
31386
|
}
|
|
31388
|
-
const idx_t &l_count = !l_done ?
|
|
31389
|
-
const idx_t &r_count = !r_done ?
|
|
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 &&
|
|
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
|
-
|
|
31399
|
-
|
|
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
|
|
31405
|
+
left->PinData(*l_sorted_block.blob_sorting_data);
|
|
31407
31406
|
}
|
|
31408
31407
|
if (!r_done) {
|
|
31409
|
-
right.blob_sorting_data
|
|
31408
|
+
right->PinData(*r_sorted_block.blob_sorting_data);
|
|
31410
31409
|
}
|
|
31411
31410
|
// Merge with variable size sorting columns
|
|
31412
|
-
for (; compared < count &&
|
|
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
|
-
|
|
31423
|
-
|
|
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
|
|
31432
|
-
|
|
31433
|
-
|
|
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 &
|
|
31440
|
-
auto &
|
|
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 (
|
|
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
|
-
|
|
31455
|
+
l_blocks[l.block_idx].block = nullptr;
|
|
31458
31456
|
// Advance block
|
|
31459
|
-
|
|
31460
|
-
|
|
31457
|
+
l.block_idx++;
|
|
31458
|
+
l.entry_idx = 0;
|
|
31461
31459
|
}
|
|
31462
|
-
if (
|
|
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
|
-
|
|
31462
|
+
r_blocks[r.block_idx].block = nullptr;
|
|
31466
31463
|
// Advance block
|
|
31467
|
-
|
|
31468
|
-
|
|
31464
|
+
r.block_idx++;
|
|
31465
|
+
r.entry_idx = 0;
|
|
31469
31466
|
}
|
|
31470
|
-
const bool l_done =
|
|
31471
|
-
const bool r_done =
|
|
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 = &
|
|
31475
|
-
left
|
|
31476
|
-
l_ptr =
|
|
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 = &
|
|
31480
|
-
|
|
31481
|
-
r_ptr =
|
|
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,
|
|
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,
|
|
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,
|
|
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 (
|
|
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[
|
|
31540
|
+
l_data.data_blocks[l.block_idx].block = nullptr;
|
|
31534
31541
|
if (!layout.AllConstant() && state.external) {
|
|
31535
|
-
l_data.heap_blocks[
|
|
31542
|
+
l_data.heap_blocks[l.block_idx].block = nullptr;
|
|
31536
31543
|
}
|
|
31537
31544
|
// Advance block
|
|
31538
|
-
|
|
31539
|
-
|
|
31545
|
+
l.block_idx++;
|
|
31546
|
+
l.entry_idx = 0;
|
|
31540
31547
|
}
|
|
31541
|
-
if (
|
|
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[
|
|
31550
|
+
r_data.data_blocks[r.block_idx].block = nullptr;
|
|
31545
31551
|
if (!layout.AllConstant() && state.external) {
|
|
31546
|
-
r_data.heap_blocks[
|
|
31552
|
+
r_data.heap_blocks[r.block_idx].block = nullptr;
|
|
31547
31553
|
}
|
|
31548
31554
|
// Advance block
|
|
31549
|
-
|
|
31550
|
-
|
|
31555
|
+
r.block_idx++;
|
|
31556
|
+
r.entry_idx = 0;
|
|
31551
31557
|
}
|
|
31552
|
-
const bool l_done =
|
|
31553
|
-
const bool r_done =
|
|
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
|
-
|
|
31557
|
-
l_ptr =
|
|
31562
|
+
l.PinData(l_data);
|
|
31563
|
+
l_ptr = l.DataPtr(l_data);
|
|
31558
31564
|
}
|
|
31559
31565
|
if (!r_done) {
|
|
31560
|
-
|
|
31561
|
-
r_ptr =
|
|
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[
|
|
31564
|
-
const idx_t &r_count = !r_done ? r_data.data_blocks[
|
|
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,
|
|
31571
|
-
|
|
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,
|
|
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,
|
|
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 =
|
|
31585
|
-
D_ASSERT(l_heap_ptr -
|
|
31586
|
-
D_ASSERT((idx_t)(l_heap_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 =
|
|
31591
|
-
D_ASSERT(r_heap_ptr -
|
|
31592
|
-
D_ASSERT((idx_t)(r_heap_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 =
|
|
31599
|
-
idx_t r_idx_copy =
|
|
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 -
|
|
31622
|
-
l_data.heap_blocks[
|
|
31623
|
-
D_ASSERT(r_heap_ptr_copy -
|
|
31624
|
-
r_data.heap_blocks[
|
|
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
|
-
|
|
31649
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
32642
|
-
|
|
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
|
-
|
|
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
|
-
:
|
|
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
|
-
|
|
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
|
-
|
|
32922
|
-
:
|
|
32923
|
-
|
|
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
|
|
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(
|
|
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 <
|
|
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
|
-
|
|
32942
|
-
auto &data_block = sorted_data.data_blocks[
|
|
32943
|
-
idx_t next = MinValue(data_block.count -
|
|
32944
|
-
const data_ptr_t data_ptr =
|
|
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,
|
|
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
|
-
|
|
32958
|
-
if (
|
|
32959
|
-
|
|
32960
|
-
|
|
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
|
-
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
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
|
-
//!
|
|
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 "
|
|
14
|
-
#define DUCKDB_VERSION "0.3.2-
|
|
13
|
+
#define DUCKDB_SOURCE_ID "9ee0227d8"
|
|
14
|
+
#define DUCKDB_VERSION "0.3.2-dev483"
|
|
15
15
|
//===----------------------------------------------------------------------===//
|
|
16
16
|
// DuckDB
|
|
17
17
|
//
|