duckdb 0.3.2-dev273.0 → 0.3.2-dev287.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 +896 -886
- package/src/duckdb.hpp +2 -2
package/src/duckdb.cpp
CHANGED
|
@@ -21229,21 +21229,37 @@ idx_t LocalFileSystem::GetFilePointer(FileHandle &handle) {
|
|
|
21229
21229
|
return ((WindowsFileHandle &)handle).position;
|
|
21230
21230
|
}
|
|
21231
21231
|
|
|
21232
|
-
|
|
21233
|
-
|
|
21234
|
-
|
|
21232
|
+
static DWORD FSInternalRead(FileHandle &handle, HANDLE hFile, void *buffer, int64_t nr_bytes, idx_t location) {
|
|
21233
|
+
DWORD bytes_read = 0;
|
|
21234
|
+
bool overlapped_read = false;
|
|
21235
21235
|
OVERLAPPED ov = {};
|
|
21236
21236
|
ov.Internal = 0;
|
|
21237
21237
|
ov.InternalHigh = 0;
|
|
21238
21238
|
ov.Offset = location & 0xFFFFFFFF;
|
|
21239
21239
|
ov.OffsetHigh = location >> 32;
|
|
21240
21240
|
ov.hEvent = 0;
|
|
21241
|
-
ReadFile(hFile, buffer, (DWORD)nr_bytes,
|
|
21242
|
-
auto rc = GetOverlappedResult(hFile, &ov, &bytes_read, true);
|
|
21241
|
+
auto rc = ReadFile(hFile, buffer, (DWORD)nr_bytes, &bytes_read, &ov);
|
|
21243
21242
|
if (rc == 0) {
|
|
21244
|
-
|
|
21245
|
-
|
|
21243
|
+
if (GetLastError() != ERROR_IO_PENDING) {
|
|
21244
|
+
auto error = GetLastErrorAsString();
|
|
21245
|
+
throw IOException("Could not read file \"%s\" (error in ReadFile): %s", handle.path, error);
|
|
21246
|
+
} else {
|
|
21247
|
+
overlapped_read = true;
|
|
21248
|
+
}
|
|
21249
|
+
}
|
|
21250
|
+
if (overlapped_read) {
|
|
21251
|
+
rc = GetOverlappedResult(hFile, &ov, &bytes_read, true);
|
|
21252
|
+
if (rc == 0) {
|
|
21253
|
+
auto error = GetLastErrorAsString();
|
|
21254
|
+
throw IOException("Could not read file \"%s\" (error in GetOverlappedResult): %s", handle.path, error);
|
|
21255
|
+
}
|
|
21246
21256
|
}
|
|
21257
|
+
return bytes_read;
|
|
21258
|
+
}
|
|
21259
|
+
|
|
21260
|
+
void LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) {
|
|
21261
|
+
HANDLE hFile = ((WindowsFileHandle &)handle).fd;
|
|
21262
|
+
auto bytes_read = FSInternalRead(handle, hFile, buffer, nr_bytes, location);
|
|
21247
21263
|
if (bytes_read != nr_bytes) {
|
|
21248
21264
|
throw IOException("Could not read all bytes from file \"%s\": wanted=%lld read=%lld", handle.path, nr_bytes,
|
|
21249
21265
|
bytes_read);
|
|
@@ -21252,40 +21268,44 @@ void LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes, i
|
|
|
21252
21268
|
|
|
21253
21269
|
int64_t LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes) {
|
|
21254
21270
|
HANDLE hFile = ((WindowsFileHandle &)handle).fd;
|
|
21255
|
-
DWORD bytes_read;
|
|
21256
21271
|
auto &pos = ((WindowsFileHandle &)handle).position;
|
|
21257
|
-
OVERLAPPED ov = {};
|
|
21258
|
-
ov.Internal = 0;
|
|
21259
|
-
ov.InternalHigh = 0;
|
|
21260
|
-
ov.Offset = pos & 0xFFFFFFFF;
|
|
21261
|
-
ov.OffsetHigh = pos >> 32;
|
|
21262
|
-
ov.hEvent = 0;
|
|
21263
21272
|
auto n = std::min<idx_t>(std::max<idx_t>(GetFileSize(handle), pos) - pos, nr_bytes);
|
|
21264
|
-
|
|
21265
|
-
auto rc = GetOverlappedResult(hFile, &ov, &bytes_read, true);
|
|
21266
|
-
if (rc == 0) {
|
|
21267
|
-
auto error = GetLastErrorAsString();
|
|
21268
|
-
throw IOException("Could not read file \"%s\": %s", handle.path, error);
|
|
21269
|
-
}
|
|
21273
|
+
auto bytes_read = FSInternalRead(handle, hFile, buffer, n, pos);
|
|
21270
21274
|
pos += bytes_read;
|
|
21271
21275
|
return bytes_read;
|
|
21272
21276
|
}
|
|
21273
21277
|
|
|
21274
|
-
|
|
21275
|
-
|
|
21276
|
-
|
|
21278
|
+
static DWORD FSInternalWrite(FileHandle &handle, HANDLE hFile, void *buffer, int64_t nr_bytes, idx_t location) {
|
|
21279
|
+
DWORD bytes_written = 0;
|
|
21280
|
+
bool overlapped_write = false;
|
|
21277
21281
|
OVERLAPPED ov = {};
|
|
21278
21282
|
ov.Internal = 0;
|
|
21279
21283
|
ov.InternalHigh = 0;
|
|
21280
21284
|
ov.Offset = location & 0xFFFFFFFF;
|
|
21281
21285
|
ov.OffsetHigh = location >> 32;
|
|
21282
21286
|
ov.hEvent = 0;
|
|
21283
|
-
WriteFile(hFile, buffer, (DWORD)nr_bytes,
|
|
21284
|
-
auto rc = GetOverlappedResult(hFile, &ov, &bytes_written, true);
|
|
21287
|
+
auto rc = WriteFile(hFile, buffer, (DWORD)nr_bytes, &bytes_written, &ov);
|
|
21285
21288
|
if (rc == 0) {
|
|
21286
|
-
|
|
21287
|
-
|
|
21289
|
+
if (GetLastError() != ERROR_IO_PENDING) {
|
|
21290
|
+
auto error = GetLastErrorAsString();
|
|
21291
|
+
throw IOException("Could not write file \"%s\" (error in WriteFile): %s", handle.path, error);
|
|
21292
|
+
} else {
|
|
21293
|
+
overlapped_write = true;
|
|
21294
|
+
}
|
|
21288
21295
|
}
|
|
21296
|
+
if (overlapped_write) {
|
|
21297
|
+
rc = GetOverlappedResult(hFile, &ov, &bytes_written, true);
|
|
21298
|
+
if (rc == 0) {
|
|
21299
|
+
auto error = GetLastErrorAsString();
|
|
21300
|
+
throw IOException("Could not write file \"%s\" (error in GetOverlappedResult): %s", handle.path, error);
|
|
21301
|
+
}
|
|
21302
|
+
}
|
|
21303
|
+
return bytes_written;
|
|
21304
|
+
}
|
|
21305
|
+
|
|
21306
|
+
void LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) {
|
|
21307
|
+
HANDLE hFile = ((WindowsFileHandle &)handle).fd;
|
|
21308
|
+
auto bytes_written = FSInternalWrite(handle, hFile, buffer, nr_bytes, location);
|
|
21289
21309
|
if (bytes_written != nr_bytes) {
|
|
21290
21310
|
throw IOException("Could not write all bytes from file \"%s\": wanted=%lld wrote=%lld", handle.path, nr_bytes,
|
|
21291
21311
|
bytes_written);
|
|
@@ -21294,20 +21314,8 @@ void LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes,
|
|
|
21294
21314
|
|
|
21295
21315
|
int64_t LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes) {
|
|
21296
21316
|
HANDLE hFile = ((WindowsFileHandle &)handle).fd;
|
|
21297
|
-
DWORD bytes_written;
|
|
21298
21317
|
auto &pos = ((WindowsFileHandle &)handle).position;
|
|
21299
|
-
|
|
21300
|
-
ov.Internal = 0;
|
|
21301
|
-
ov.InternalHigh = 0;
|
|
21302
|
-
ov.Offset = pos & 0xFFFFFFFF;
|
|
21303
|
-
ov.OffsetHigh = pos >> 32;
|
|
21304
|
-
ov.hEvent = 0;
|
|
21305
|
-
WriteFile(hFile, buffer, (DWORD)nr_bytes, NULL, &ov);
|
|
21306
|
-
auto rc = GetOverlappedResult(hFile, &ov, &bytes_written, true);
|
|
21307
|
-
if (rc == 0) {
|
|
21308
|
-
auto error = GetLastErrorAsString();
|
|
21309
|
-
throw IOException("Could not write file \"%s\": %s", handle.path, error);
|
|
21310
|
-
}
|
|
21318
|
+
auto bytes_written = FSInternalWrite(handle, hFile, buffer, nr_bytes, pos);
|
|
21311
21319
|
pos += bytes_written;
|
|
21312
21320
|
return bytes_written;
|
|
21313
21321
|
}
|
|
@@ -29168,20 +29176,9 @@ private:
|
|
|
29168
29176
|
} // namespace duckdb
|
|
29169
29177
|
|
|
29170
29178
|
|
|
29171
|
-
//===----------------------------------------------------------------------===//
|
|
29172
|
-
// DuckDB
|
|
29173
|
-
//
|
|
29174
|
-
// duckdb/common/sort/sort.hpp
|
|
29175
|
-
//
|
|
29176
|
-
//
|
|
29177
|
-
//===----------------------------------------------------------------------===//
|
|
29178
|
-
|
|
29179
|
-
|
|
29180
|
-
|
|
29181
|
-
//===----------------------------------------------------------------------===//
|
|
29182
29179
|
// DuckDB
|
|
29183
29180
|
//
|
|
29184
|
-
// duckdb/common/
|
|
29181
|
+
// duckdb/common/fast_mem.hpp
|
|
29185
29182
|
//
|
|
29186
29183
|
//
|
|
29187
29184
|
//===----------------------------------------------------------------------===//
|
|
@@ -29189,701 +29186,17 @@ private:
|
|
|
29189
29186
|
|
|
29190
29187
|
|
|
29191
29188
|
|
|
29192
|
-
namespace duckdb {
|
|
29193
|
-
|
|
29194
|
-
class BufferManager;
|
|
29195
|
-
struct RowDataBlock;
|
|
29196
|
-
struct SortLayout;
|
|
29197
|
-
struct GlobalSortState;
|
|
29198
|
-
|
|
29199
|
-
//! Object that holds sorted rows, and an accompanying heap if there are blobs
|
|
29200
|
-
struct SortedData {
|
|
29201
|
-
public:
|
|
29202
|
-
SortedData(const RowLayout &layout, BufferManager &buffer_manager, GlobalSortState &state);
|
|
29203
|
-
//! Number of rows that this object holds
|
|
29204
|
-
idx_t Count();
|
|
29205
|
-
//! Pin the current block so it can be read
|
|
29206
|
-
void Pin();
|
|
29207
|
-
//! Pointer to the row that is currently being read from
|
|
29208
|
-
data_ptr_t DataPtr() const;
|
|
29209
|
-
//! Pointer to the heap row that corresponds to the current row
|
|
29210
|
-
data_ptr_t HeapPtr() const;
|
|
29211
|
-
//! Advance one row
|
|
29212
|
-
void Advance(const bool &adv);
|
|
29213
|
-
//! Initialize new block to write to
|
|
29214
|
-
void CreateBlock();
|
|
29215
|
-
//! Reset read indices to the given indices
|
|
29216
|
-
void ResetIndices(idx_t block_idx_to, idx_t entry_idx_to);
|
|
29217
|
-
//! Create a slice that holds the rows between the start and end indices
|
|
29218
|
-
unique_ptr<SortedData> CreateSlice(idx_t start_block_index, idx_t start_entry_index, idx_t end_block_index,
|
|
29219
|
-
idx_t end_entry_index);
|
|
29220
|
-
//! Unswizzles all
|
|
29221
|
-
void Unswizzle();
|
|
29222
|
-
|
|
29223
|
-
public:
|
|
29224
|
-
//! Layout of this data
|
|
29225
|
-
const RowLayout layout;
|
|
29226
|
-
//! Data and heap blocks
|
|
29227
|
-
vector<RowDataBlock> data_blocks;
|
|
29228
|
-
vector<RowDataBlock> heap_blocks;
|
|
29229
|
-
//! Buffer handles to the data being currently read
|
|
29230
|
-
unique_ptr<BufferHandle> data_handle;
|
|
29231
|
-
unique_ptr<BufferHandle> heap_handle;
|
|
29232
|
-
//! Read indices
|
|
29233
|
-
idx_t block_idx;
|
|
29234
|
-
idx_t entry_idx;
|
|
29235
|
-
//! Whether the pointers in this sorted data are swizzled
|
|
29236
|
-
bool swizzled;
|
|
29237
|
-
|
|
29238
|
-
private:
|
|
29239
|
-
//! Pin fixed-size row data
|
|
29240
|
-
void PinData();
|
|
29241
|
-
//! Pin the accompanying heap data (if any)
|
|
29242
|
-
void PinHeap();
|
|
29243
|
-
|
|
29244
|
-
private:
|
|
29245
|
-
//! The buffer manager
|
|
29246
|
-
BufferManager &buffer_manager;
|
|
29247
|
-
//! The global state
|
|
29248
|
-
GlobalSortState &state;
|
|
29249
|
-
//! Pointers into the buffers being currently read
|
|
29250
|
-
data_ptr_t data_ptr;
|
|
29251
|
-
data_ptr_t heap_ptr;
|
|
29252
|
-
};
|
|
29253
|
-
|
|
29254
|
-
//! Block that holds sorted rows: radix, blob and payload data
|
|
29255
|
-
struct SortedBlock {
|
|
29256
|
-
public:
|
|
29257
|
-
SortedBlock(BufferManager &buffer_manager, GlobalSortState &gstate);
|
|
29258
|
-
//! Number of rows that this object holds
|
|
29259
|
-
idx_t Count() const;
|
|
29260
|
-
//! The remaining number of rows to be read from this object
|
|
29261
|
-
idx_t Remaining() const;
|
|
29262
|
-
//! Initialize this block to write data to
|
|
29263
|
-
void InitializeWrite();
|
|
29264
|
-
//! Init new block to write to
|
|
29265
|
-
void CreateBlock();
|
|
29266
|
-
//! Pins radix block with given index
|
|
29267
|
-
void PinRadix(idx_t pin_block_idx);
|
|
29268
|
-
//! Fill this sorted block by appending the blocks held by a vector of sorted blocks
|
|
29269
|
-
void AppendSortedBlocks(vector<unique_ptr<SortedBlock>> &sorted_blocks);
|
|
29270
|
-
//! Locate the block and entry index of a row in this block,
|
|
29271
|
-
//! given an index between 0 and the total number of rows in this block
|
|
29272
|
-
void GlobalToLocalIndex(const idx_t &global_idx, idx_t &local_block_index, idx_t &local_entry_index);
|
|
29273
|
-
//! Create a slice that holds the rows between the start and end indices
|
|
29274
|
-
unique_ptr<SortedBlock> CreateSlice(const idx_t start, const idx_t end);
|
|
29275
|
-
|
|
29276
|
-
//! Size (in bytes) of the heap of this block
|
|
29277
|
-
idx_t HeapSize() const;
|
|
29278
|
-
//! Total size (in bytes) of this block
|
|
29279
|
-
idx_t SizeInBytes() const;
|
|
29280
|
-
|
|
29281
|
-
public:
|
|
29282
|
-
//! Radix/memcmp sortable data
|
|
29283
|
-
vector<RowDataBlock> radix_sorting_data;
|
|
29284
|
-
unique_ptr<BufferHandle> radix_handle;
|
|
29285
|
-
idx_t block_idx;
|
|
29286
|
-
idx_t entry_idx;
|
|
29287
|
-
//! Variable sized sorting data
|
|
29288
|
-
unique_ptr<SortedData> blob_sorting_data;
|
|
29289
|
-
//! Payload data
|
|
29290
|
-
unique_ptr<SortedData> payload_data;
|
|
29291
|
-
|
|
29292
|
-
private:
|
|
29293
|
-
//! Buffer manager, and sorting layout constants
|
|
29294
|
-
BufferManager &buffer_manager;
|
|
29295
|
-
GlobalSortState &state;
|
|
29296
|
-
const SortLayout &sort_layout;
|
|
29297
|
-
const RowLayout &payload_layout;
|
|
29298
|
-
};
|
|
29299
|
-
|
|
29300
|
-
struct SortedDataScanner {
|
|
29301
|
-
public:
|
|
29302
|
-
SortedDataScanner(SortedData &sorted_data, GlobalSortState &global_sort_state);
|
|
29303
|
-
|
|
29304
|
-
//! Scans the next data chunk from the sorted data
|
|
29305
|
-
void Scan(DataChunk &chunk);
|
|
29306
|
-
|
|
29307
|
-
private:
|
|
29308
|
-
//! The sorted data being scanned
|
|
29309
|
-
SortedData &sorted_data;
|
|
29310
|
-
//! The total count of sorted_data
|
|
29311
|
-
const idx_t total_count;
|
|
29312
|
-
//! The global sort state
|
|
29313
|
-
GlobalSortState &global_sort_state;
|
|
29314
|
-
//! Addresses used to gather from the sorted data
|
|
29315
|
-
Vector addresses = Vector(LogicalType::POINTER);
|
|
29316
|
-
//! The number of rows scanned so far
|
|
29317
|
-
idx_t total_scanned;
|
|
29318
|
-
};
|
|
29319
|
-
|
|
29320
|
-
} // namespace duckdb
|
|
29321
29189
|
|
|
29322
29190
|
|
|
29191
|
+
template <size_t SIZE>
|
|
29192
|
+
static inline void MemcpyFixed(void *dest, const void *src) {
|
|
29193
|
+
memcpy(dest, src, SIZE);
|
|
29194
|
+
}
|
|
29323
29195
|
|
|
29324
|
-
|
|
29325
|
-
|
|
29326
|
-
|
|
29327
|
-
|
|
29328
|
-
struct LocalSortState;
|
|
29329
|
-
|
|
29330
|
-
struct SortConstants {
|
|
29331
|
-
static constexpr idx_t VALUES_PER_RADIX = 256;
|
|
29332
|
-
static constexpr idx_t MSD_RADIX_LOCATIONS = VALUES_PER_RADIX + 1;
|
|
29333
|
-
static constexpr idx_t INSERTION_SORT_THRESHOLD = 24;
|
|
29334
|
-
static constexpr idx_t MSD_RADIX_SORT_SIZE_THRESHOLD = 4;
|
|
29335
|
-
};
|
|
29336
|
-
|
|
29337
|
-
struct SortLayout {
|
|
29338
|
-
public:
|
|
29339
|
-
explicit SortLayout(const vector<BoundOrderByNode> &orders);
|
|
29340
|
-
|
|
29341
|
-
public:
|
|
29342
|
-
idx_t column_count;
|
|
29343
|
-
vector<OrderType> order_types;
|
|
29344
|
-
vector<OrderByNullType> order_by_null_types;
|
|
29345
|
-
vector<LogicalType> logical_types;
|
|
29346
|
-
|
|
29347
|
-
bool all_constant;
|
|
29348
|
-
vector<bool> constant_size;
|
|
29349
|
-
vector<idx_t> column_sizes;
|
|
29350
|
-
vector<idx_t> prefix_lengths;
|
|
29351
|
-
vector<BaseStatistics *> stats;
|
|
29352
|
-
vector<bool> has_null;
|
|
29353
|
-
|
|
29354
|
-
idx_t comparison_size;
|
|
29355
|
-
idx_t entry_size;
|
|
29356
|
-
|
|
29357
|
-
RowLayout blob_layout;
|
|
29358
|
-
unordered_map<idx_t, idx_t> sorting_to_blob_col;
|
|
29359
|
-
};
|
|
29360
|
-
|
|
29361
|
-
struct GlobalSortState {
|
|
29362
|
-
public:
|
|
29363
|
-
GlobalSortState(BufferManager &buffer_manager, const vector<BoundOrderByNode> &orders, RowLayout &payload_layout);
|
|
29364
|
-
|
|
29365
|
-
//! Add local state sorted data to this global state
|
|
29366
|
-
void AddLocalState(LocalSortState &local_sort_state);
|
|
29367
|
-
//! Prepares the GlobalSortState for the merge sort phase (after completing radix sort phase)
|
|
29368
|
-
void PrepareMergePhase();
|
|
29369
|
-
//! Initializes the global sort state for another round of merging
|
|
29370
|
-
void InitializeMergeRound();
|
|
29371
|
-
//! Completes the cascaded merge sort round
|
|
29372
|
-
void CompleteMergeRound();
|
|
29373
|
-
|
|
29374
|
-
public:
|
|
29375
|
-
//! The lock for updating the order global state
|
|
29376
|
-
mutex lock;
|
|
29377
|
-
//! The buffer manager
|
|
29378
|
-
BufferManager &buffer_manager;
|
|
29379
|
-
|
|
29380
|
-
//! Sorting and payload layouts
|
|
29381
|
-
const SortLayout sort_layout;
|
|
29382
|
-
const RowLayout payload_layout;
|
|
29383
|
-
|
|
29384
|
-
//! Sorted data
|
|
29385
|
-
vector<unique_ptr<SortedBlock>> sorted_blocks;
|
|
29386
|
-
vector<vector<unique_ptr<SortedBlock>>> sorted_blocks_temp;
|
|
29387
|
-
unique_ptr<SortedBlock> odd_one_out;
|
|
29388
|
-
|
|
29389
|
-
//! Pinned heap data (if sorting in memory)
|
|
29390
|
-
vector<RowDataBlock> heap_blocks;
|
|
29391
|
-
vector<unique_ptr<BufferHandle>> pinned_blocks;
|
|
29392
|
-
|
|
29393
|
-
//! Capacity (number of rows) used to initialize blocks
|
|
29394
|
-
idx_t block_capacity;
|
|
29395
|
-
//! Whether we are doing an external sort
|
|
29396
|
-
bool external;
|
|
29397
|
-
|
|
29398
|
-
//! Progress in merge path stage
|
|
29399
|
-
idx_t pair_idx;
|
|
29400
|
-
idx_t num_pairs;
|
|
29401
|
-
idx_t l_start;
|
|
29402
|
-
idx_t r_start;
|
|
29403
|
-
};
|
|
29404
|
-
|
|
29405
|
-
struct LocalSortState {
|
|
29406
|
-
public:
|
|
29407
|
-
LocalSortState();
|
|
29408
|
-
|
|
29409
|
-
//! Initialize the layouts and RowDataCollections
|
|
29410
|
-
void Initialize(GlobalSortState &global_sort_state, BufferManager &buffer_manager_p);
|
|
29411
|
-
//! Sink one DataChunk into the local sort state
|
|
29412
|
-
void SinkChunk(DataChunk &sort, DataChunk &payload);
|
|
29413
|
-
//! Size of accumulated data in bytes
|
|
29414
|
-
idx_t SizeInBytes() const;
|
|
29415
|
-
//! Sort the data accumulated so far
|
|
29416
|
-
void Sort(GlobalSortState &global_sort_state, bool reorder_heap);
|
|
29417
|
-
|
|
29418
|
-
private:
|
|
29419
|
-
//! Concatenate the blocks held by a RowDataCollection into a single block
|
|
29420
|
-
RowDataBlock ConcatenateBlocks(RowDataCollection &row_data);
|
|
29421
|
-
//! Sorts the data in the newly created SortedBlock
|
|
29422
|
-
void SortInMemory();
|
|
29423
|
-
//! Re-order the local state after sorting
|
|
29424
|
-
void ReOrder(GlobalSortState &gstate, bool reorder_heap);
|
|
29425
|
-
//! Re-order a SortedData object after sorting
|
|
29426
|
-
void ReOrder(SortedData &sd, data_ptr_t sorting_ptr, RowDataCollection &heap, GlobalSortState &gstate,
|
|
29427
|
-
bool reorder_heap);
|
|
29428
|
-
|
|
29429
|
-
public:
|
|
29430
|
-
//! Whether this local state has been initialized
|
|
29431
|
-
bool initialized;
|
|
29432
|
-
//! The buffer manager
|
|
29433
|
-
BufferManager *buffer_manager;
|
|
29434
|
-
//! The sorting and payload layouts
|
|
29435
|
-
const SortLayout *sort_layout;
|
|
29436
|
-
const RowLayout *payload_layout;
|
|
29437
|
-
//! Radix/memcmp sortable data
|
|
29438
|
-
unique_ptr<RowDataCollection> radix_sorting_data;
|
|
29439
|
-
//! Variable sized sorting data and accompanying heap
|
|
29440
|
-
unique_ptr<RowDataCollection> blob_sorting_data;
|
|
29441
|
-
unique_ptr<RowDataCollection> blob_sorting_heap;
|
|
29442
|
-
//! Payload data and accompanying heap
|
|
29443
|
-
unique_ptr<RowDataCollection> payload_data;
|
|
29444
|
-
unique_ptr<RowDataCollection> payload_heap;
|
|
29445
|
-
//! Sorted data
|
|
29446
|
-
vector<unique_ptr<SortedBlock>> sorted_blocks;
|
|
29447
|
-
|
|
29448
|
-
private:
|
|
29449
|
-
//! Selection vector and addresses for scattering the data to rows
|
|
29450
|
-
const SelectionVector &sel_ptr = FlatVector::INCREMENTAL_SELECTION_VECTOR;
|
|
29451
|
-
Vector addresses = Vector(LogicalType::POINTER);
|
|
29452
|
-
};
|
|
29453
|
-
|
|
29454
|
-
struct MergeSorter {
|
|
29455
|
-
public:
|
|
29456
|
-
MergeSorter(GlobalSortState &state, BufferManager &buffer_manager);
|
|
29457
|
-
|
|
29458
|
-
//! Finds and merges partitions until the current cascaded merge round is finished
|
|
29459
|
-
void PerformInMergeRound();
|
|
29460
|
-
|
|
29461
|
-
private:
|
|
29462
|
-
//! Computes the left and right block that will be merged next (Merge Path partition)
|
|
29463
|
-
void GetNextPartition();
|
|
29464
|
-
//! Finds the boundary of the next partition using binary search
|
|
29465
|
-
void GetIntersection(SortedBlock &l, SortedBlock &r, const idx_t diagonal, idx_t &l_idx, idx_t &r_idx);
|
|
29466
|
-
//! Compare values within SortedBlocks using a global index
|
|
29467
|
-
int CompareUsingGlobalIndex(SortedBlock &l, SortedBlock &r, const idx_t l_idx, const idx_t r_idx);
|
|
29468
|
-
|
|
29469
|
-
//! Finds the next partition and merges it
|
|
29470
|
-
void MergePartition();
|
|
29471
|
-
|
|
29472
|
-
//! Computes how the next 'count' tuples should be merged by setting the 'left_smaller' array
|
|
29473
|
-
void ComputeMerge(const idx_t &count, bool left_smaller[]);
|
|
29474
|
-
|
|
29475
|
-
//! Merges the radix sorting blocks according to the 'left_smaller' array
|
|
29476
|
-
void MergeRadix(const idx_t &count, const bool left_smaller[]);
|
|
29477
|
-
//! Merges SortedData according to the 'left_smaller' array
|
|
29478
|
-
void MergeData(SortedData &result_data, SortedData &l_data, SortedData &r_data, const idx_t &count,
|
|
29479
|
-
const bool left_smaller[], idx_t next_entry_sizes[]);
|
|
29480
|
-
//! Merges constant size rows according to the 'left_smaller' array
|
|
29481
|
-
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,
|
|
29482
|
-
const idx_t &r_count, RowDataBlock *target_block, data_ptr_t &target_ptr, const idx_t &entry_size,
|
|
29483
|
-
const bool left_smaller[], idx_t &copied, const idx_t &count);
|
|
29484
|
-
//! Flushes constant size rows into the result
|
|
29485
|
-
void FlushRows(data_ptr_t &source_ptr, idx_t &source_entry_idx, const idx_t &source_count,
|
|
29486
|
-
RowDataBlock *target_block, data_ptr_t &target_ptr, const idx_t &entry_size, idx_t &copied,
|
|
29487
|
-
const idx_t &count);
|
|
29488
|
-
//! Flushes blob rows and accompanying heap
|
|
29489
|
-
void FlushBlobs(const RowLayout &layout, const idx_t &source_count, data_ptr_t &source_data_ptr,
|
|
29490
|
-
idx_t &source_entry_idx, data_ptr_t &source_heap_ptr, RowDataBlock *target_data_block,
|
|
29491
|
-
data_ptr_t &target_data_ptr, RowDataBlock *target_heap_block, BufferHandle &target_heap_handle,
|
|
29492
|
-
data_ptr_t &target_heap_ptr, idx_t &copied, const idx_t &count);
|
|
29493
|
-
|
|
29494
|
-
private:
|
|
29495
|
-
//! The global sorting state
|
|
29496
|
-
GlobalSortState &state;
|
|
29497
|
-
//! The sorting and payload layouts
|
|
29498
|
-
BufferManager &buffer_manager;
|
|
29499
|
-
const SortLayout &sort_layout;
|
|
29500
|
-
|
|
29501
|
-
//! The left, right and result blocks of the current partition
|
|
29502
|
-
unique_ptr<SortedBlock> left_block;
|
|
29503
|
-
unique_ptr<SortedBlock> right_block;
|
|
29504
|
-
SortedBlock *result;
|
|
29505
|
-
};
|
|
29506
|
-
|
|
29507
|
-
} // namespace duckdb
|
|
29508
|
-
|
|
29509
|
-
|
|
29510
|
-
namespace duckdb {
|
|
29511
|
-
|
|
29512
|
-
bool Comparators::TieIsBreakable(const idx_t &col_idx, const data_ptr_t row_ptr, const RowLayout &row_layout) {
|
|
29513
|
-
// Check if the blob is NULL
|
|
29514
|
-
ValidityBytes row_mask(row_ptr);
|
|
29515
|
-
idx_t entry_idx;
|
|
29516
|
-
idx_t idx_in_entry;
|
|
29517
|
-
ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry);
|
|
29518
|
-
if (!row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry)) {
|
|
29519
|
-
// Can't break a NULL tie
|
|
29520
|
-
return false;
|
|
29521
|
-
}
|
|
29522
|
-
if (row_layout.GetTypes()[col_idx].InternalType() == PhysicalType::VARCHAR) {
|
|
29523
|
-
const auto &tie_col_offset = row_layout.GetOffsets()[col_idx];
|
|
29524
|
-
string_t tie_string = Load<string_t>(row_ptr + tie_col_offset);
|
|
29525
|
-
if (tie_string.GetSize() < string_t::INLINE_LENGTH) {
|
|
29526
|
-
// No need to break the tie - we already compared the full string
|
|
29527
|
-
return false;
|
|
29528
|
-
}
|
|
29529
|
-
}
|
|
29530
|
-
return true;
|
|
29531
|
-
}
|
|
29532
|
-
|
|
29533
|
-
int Comparators::CompareTuple(const SortedBlock &left, const SortedBlock &right, const data_ptr_t &l_ptr,
|
|
29534
|
-
const data_ptr_t &r_ptr, const SortLayout &sort_layout, const bool &external_sort) {
|
|
29535
|
-
// Compare the sorting columns one by one
|
|
29536
|
-
int comp_res = 0;
|
|
29537
|
-
data_ptr_t l_ptr_offset = l_ptr;
|
|
29538
|
-
data_ptr_t r_ptr_offset = r_ptr;
|
|
29539
|
-
for (idx_t col_idx = 0; col_idx < sort_layout.column_count; col_idx++) {
|
|
29540
|
-
comp_res = memcmp(l_ptr_offset, r_ptr_offset, sort_layout.column_sizes[col_idx]);
|
|
29541
|
-
if (comp_res == 0 && !sort_layout.constant_size[col_idx]) {
|
|
29542
|
-
comp_res =
|
|
29543
|
-
BreakBlobTie(col_idx, *left.blob_sorting_data, *right.blob_sorting_data, sort_layout, external_sort);
|
|
29544
|
-
}
|
|
29545
|
-
if (comp_res != 0) {
|
|
29546
|
-
break;
|
|
29547
|
-
}
|
|
29548
|
-
l_ptr_offset += sort_layout.column_sizes[col_idx];
|
|
29549
|
-
r_ptr_offset += sort_layout.column_sizes[col_idx];
|
|
29550
|
-
}
|
|
29551
|
-
return comp_res;
|
|
29552
|
-
}
|
|
29553
|
-
|
|
29554
|
-
int Comparators::CompareVal(const data_ptr_t l_ptr, const data_ptr_t r_ptr, const LogicalType &type) {
|
|
29555
|
-
switch (type.InternalType()) {
|
|
29556
|
-
case PhysicalType::VARCHAR:
|
|
29557
|
-
return TemplatedCompareVal<string_t>(l_ptr, r_ptr);
|
|
29558
|
-
case PhysicalType::LIST:
|
|
29559
|
-
case PhysicalType::STRUCT: {
|
|
29560
|
-
auto l_nested_ptr = Load<data_ptr_t>(l_ptr);
|
|
29561
|
-
auto r_nested_ptr = Load<data_ptr_t>(r_ptr);
|
|
29562
|
-
return CompareValAndAdvance(l_nested_ptr, r_nested_ptr, type);
|
|
29563
|
-
}
|
|
29564
|
-
default:
|
|
29565
|
-
throw NotImplementedException("Unimplemented CompareVal for type %s", type.ToString());
|
|
29566
|
-
}
|
|
29567
|
-
}
|
|
29568
|
-
|
|
29569
|
-
int Comparators::BreakBlobTie(const idx_t &tie_col, const SortedData &left, const SortedData &right,
|
|
29570
|
-
const SortLayout &sort_layout, const bool &external) {
|
|
29571
|
-
const idx_t &col_idx = sort_layout.sorting_to_blob_col.at(tie_col);
|
|
29572
|
-
data_ptr_t l_data_ptr = left.DataPtr();
|
|
29573
|
-
data_ptr_t r_data_ptr = right.DataPtr();
|
|
29574
|
-
if (!TieIsBreakable(col_idx, l_data_ptr, sort_layout.blob_layout)) {
|
|
29575
|
-
// Quick check to see if ties can be broken
|
|
29576
|
-
return 0;
|
|
29577
|
-
}
|
|
29578
|
-
// Align the pointers
|
|
29579
|
-
const auto &tie_col_offset = sort_layout.blob_layout.GetOffsets()[col_idx];
|
|
29580
|
-
l_data_ptr += tie_col_offset;
|
|
29581
|
-
r_data_ptr += tie_col_offset;
|
|
29582
|
-
// Do the comparison
|
|
29583
|
-
const int order = sort_layout.order_types[tie_col] == OrderType::DESCENDING ? -1 : 1;
|
|
29584
|
-
const auto &type = left.layout.GetTypes()[col_idx];
|
|
29585
|
-
int result;
|
|
29586
|
-
if (external) {
|
|
29587
|
-
// Store heap pointers
|
|
29588
|
-
data_ptr_t l_heap_ptr = left.HeapPtr();
|
|
29589
|
-
data_ptr_t r_heap_ptr = right.HeapPtr();
|
|
29590
|
-
// Unswizzle offset to pointer
|
|
29591
|
-
UnswizzleSingleValue(l_data_ptr, l_heap_ptr, type);
|
|
29592
|
-
UnswizzleSingleValue(r_data_ptr, r_heap_ptr, type);
|
|
29593
|
-
// Compare
|
|
29594
|
-
result = CompareVal(l_data_ptr, r_data_ptr, type);
|
|
29595
|
-
// Swizzle the pointers back to offsets
|
|
29596
|
-
SwizzleSingleValue(l_data_ptr, l_heap_ptr, type);
|
|
29597
|
-
SwizzleSingleValue(r_data_ptr, r_heap_ptr, type);
|
|
29598
|
-
} else {
|
|
29599
|
-
result = CompareVal(l_data_ptr, r_data_ptr, type);
|
|
29600
|
-
}
|
|
29601
|
-
return order * result;
|
|
29602
|
-
}
|
|
29603
|
-
|
|
29604
|
-
template <class T>
|
|
29605
|
-
int Comparators::TemplatedCompareVal(const data_ptr_t &left_ptr, const data_ptr_t &right_ptr) {
|
|
29606
|
-
const auto left_val = Load<T>(left_ptr);
|
|
29607
|
-
const auto right_val = Load<T>(right_ptr);
|
|
29608
|
-
if (Equals::Operation<T>(left_val, right_val)) {
|
|
29609
|
-
return 0;
|
|
29610
|
-
} else if (LessThan::Operation<T>(left_val, right_val)) {
|
|
29611
|
-
return -1;
|
|
29612
|
-
} else {
|
|
29613
|
-
return 1;
|
|
29614
|
-
}
|
|
29615
|
-
}
|
|
29616
|
-
|
|
29617
|
-
int Comparators::CompareValAndAdvance(data_ptr_t &l_ptr, data_ptr_t &r_ptr, const LogicalType &type) {
|
|
29618
|
-
switch (type.InternalType()) {
|
|
29619
|
-
case PhysicalType::BOOL:
|
|
29620
|
-
case PhysicalType::INT8:
|
|
29621
|
-
return TemplatedCompareAndAdvance<int8_t>(l_ptr, r_ptr);
|
|
29622
|
-
case PhysicalType::INT16:
|
|
29623
|
-
return TemplatedCompareAndAdvance<int16_t>(l_ptr, r_ptr);
|
|
29624
|
-
case PhysicalType::INT32:
|
|
29625
|
-
return TemplatedCompareAndAdvance<int32_t>(l_ptr, r_ptr);
|
|
29626
|
-
case PhysicalType::INT64:
|
|
29627
|
-
return TemplatedCompareAndAdvance<int64_t>(l_ptr, r_ptr);
|
|
29628
|
-
case PhysicalType::UINT8:
|
|
29629
|
-
return TemplatedCompareAndAdvance<uint8_t>(l_ptr, r_ptr);
|
|
29630
|
-
case PhysicalType::UINT16:
|
|
29631
|
-
return TemplatedCompareAndAdvance<uint16_t>(l_ptr, r_ptr);
|
|
29632
|
-
case PhysicalType::UINT32:
|
|
29633
|
-
return TemplatedCompareAndAdvance<uint32_t>(l_ptr, r_ptr);
|
|
29634
|
-
case PhysicalType::UINT64:
|
|
29635
|
-
return TemplatedCompareAndAdvance<uint64_t>(l_ptr, r_ptr);
|
|
29636
|
-
case PhysicalType::INT128:
|
|
29637
|
-
return TemplatedCompareAndAdvance<hugeint_t>(l_ptr, r_ptr);
|
|
29638
|
-
case PhysicalType::FLOAT:
|
|
29639
|
-
return TemplatedCompareAndAdvance<float>(l_ptr, r_ptr);
|
|
29640
|
-
case PhysicalType::DOUBLE:
|
|
29641
|
-
return TemplatedCompareAndAdvance<double>(l_ptr, r_ptr);
|
|
29642
|
-
case PhysicalType::INTERVAL:
|
|
29643
|
-
return TemplatedCompareAndAdvance<interval_t>(l_ptr, r_ptr);
|
|
29644
|
-
case PhysicalType::VARCHAR:
|
|
29645
|
-
return CompareStringAndAdvance(l_ptr, r_ptr);
|
|
29646
|
-
case PhysicalType::LIST:
|
|
29647
|
-
return CompareListAndAdvance(l_ptr, r_ptr, ListType::GetChildType(type));
|
|
29648
|
-
case PhysicalType::STRUCT:
|
|
29649
|
-
return CompareStructAndAdvance(l_ptr, r_ptr, StructType::GetChildTypes(type));
|
|
29650
|
-
default:
|
|
29651
|
-
throw NotImplementedException("Unimplemented CompareValAndAdvance for type %s", type.ToString());
|
|
29652
|
-
}
|
|
29653
|
-
}
|
|
29654
|
-
|
|
29655
|
-
template <class T>
|
|
29656
|
-
int Comparators::TemplatedCompareAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr) {
|
|
29657
|
-
auto result = TemplatedCompareVal<T>(left_ptr, right_ptr);
|
|
29658
|
-
left_ptr += sizeof(T);
|
|
29659
|
-
right_ptr += sizeof(T);
|
|
29660
|
-
return result;
|
|
29661
|
-
}
|
|
29662
|
-
|
|
29663
|
-
int Comparators::CompareStringAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr) {
|
|
29664
|
-
// Construct the string_t
|
|
29665
|
-
uint32_t left_string_size = Load<uint32_t>(left_ptr);
|
|
29666
|
-
uint32_t right_string_size = Load<uint32_t>(right_ptr);
|
|
29667
|
-
left_ptr += sizeof(uint32_t);
|
|
29668
|
-
right_ptr += sizeof(uint32_t);
|
|
29669
|
-
string_t left_val((const char *)left_ptr, left_string_size);
|
|
29670
|
-
string_t right_val((const char *)right_ptr, right_string_size);
|
|
29671
|
-
left_ptr += left_string_size;
|
|
29672
|
-
right_ptr += right_string_size;
|
|
29673
|
-
// Compare
|
|
29674
|
-
return TemplatedCompareVal<string_t>((data_ptr_t)&left_val, (data_ptr_t)&right_val);
|
|
29675
|
-
}
|
|
29676
|
-
|
|
29677
|
-
int Comparators::CompareStructAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr,
|
|
29678
|
-
const child_list_t<LogicalType> &types) {
|
|
29679
|
-
idx_t count = types.size();
|
|
29680
|
-
// Load validity masks
|
|
29681
|
-
ValidityBytes left_validity(left_ptr);
|
|
29682
|
-
ValidityBytes right_validity(right_ptr);
|
|
29683
|
-
left_ptr += (count + 7) / 8;
|
|
29684
|
-
right_ptr += (count + 7) / 8;
|
|
29685
|
-
// Initialize variables
|
|
29686
|
-
bool left_valid;
|
|
29687
|
-
bool right_valid;
|
|
29688
|
-
idx_t entry_idx;
|
|
29689
|
-
idx_t idx_in_entry;
|
|
29690
|
-
// Compare
|
|
29691
|
-
int comp_res = 0;
|
|
29692
|
-
for (idx_t i = 0; i < count; i++) {
|
|
29693
|
-
ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry);
|
|
29694
|
-
left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
29695
|
-
right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
29696
|
-
auto &type = types[i].second;
|
|
29697
|
-
if ((left_valid && right_valid) || TypeIsConstantSize(type.InternalType())) {
|
|
29698
|
-
comp_res = CompareValAndAdvance(left_ptr, right_ptr, types[i].second);
|
|
29699
|
-
}
|
|
29700
|
-
if (!left_valid && !right_valid) {
|
|
29701
|
-
comp_res = 0;
|
|
29702
|
-
} else if (!left_valid) {
|
|
29703
|
-
comp_res = 1;
|
|
29704
|
-
} else if (!right_valid) {
|
|
29705
|
-
comp_res = -1;
|
|
29706
|
-
}
|
|
29707
|
-
if (comp_res != 0) {
|
|
29708
|
-
break;
|
|
29709
|
-
}
|
|
29710
|
-
}
|
|
29711
|
-
return comp_res;
|
|
29712
|
-
}
|
|
29713
|
-
|
|
29714
|
-
int Comparators::CompareListAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr, const LogicalType &type) {
|
|
29715
|
-
// Load list lengths
|
|
29716
|
-
auto left_len = Load<idx_t>(left_ptr);
|
|
29717
|
-
auto right_len = Load<idx_t>(right_ptr);
|
|
29718
|
-
left_ptr += sizeof(idx_t);
|
|
29719
|
-
right_ptr += sizeof(idx_t);
|
|
29720
|
-
// Load list validity masks
|
|
29721
|
-
ValidityBytes left_validity(left_ptr);
|
|
29722
|
-
ValidityBytes right_validity(right_ptr);
|
|
29723
|
-
left_ptr += (left_len + 7) / 8;
|
|
29724
|
-
right_ptr += (right_len + 7) / 8;
|
|
29725
|
-
// Compare
|
|
29726
|
-
int comp_res = 0;
|
|
29727
|
-
idx_t count = MinValue(left_len, right_len);
|
|
29728
|
-
if (TypeIsConstantSize(type.InternalType())) {
|
|
29729
|
-
// Templated code for fixed-size types
|
|
29730
|
-
switch (type.InternalType()) {
|
|
29731
|
-
case PhysicalType::BOOL:
|
|
29732
|
-
case PhysicalType::INT8:
|
|
29733
|
-
comp_res = TemplatedCompareListLoop<int8_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29734
|
-
break;
|
|
29735
|
-
case PhysicalType::INT16:
|
|
29736
|
-
comp_res = TemplatedCompareListLoop<int16_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29737
|
-
break;
|
|
29738
|
-
case PhysicalType::INT32:
|
|
29739
|
-
comp_res = TemplatedCompareListLoop<int32_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29740
|
-
break;
|
|
29741
|
-
case PhysicalType::INT64:
|
|
29742
|
-
comp_res = TemplatedCompareListLoop<int64_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29743
|
-
break;
|
|
29744
|
-
case PhysicalType::UINT8:
|
|
29745
|
-
comp_res = TemplatedCompareListLoop<uint8_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29746
|
-
break;
|
|
29747
|
-
case PhysicalType::UINT16:
|
|
29748
|
-
comp_res = TemplatedCompareListLoop<uint16_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29749
|
-
break;
|
|
29750
|
-
case PhysicalType::UINT32:
|
|
29751
|
-
comp_res = TemplatedCompareListLoop<uint32_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29752
|
-
break;
|
|
29753
|
-
case PhysicalType::UINT64:
|
|
29754
|
-
comp_res = TemplatedCompareListLoop<uint64_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29755
|
-
break;
|
|
29756
|
-
case PhysicalType::INT128:
|
|
29757
|
-
comp_res = TemplatedCompareListLoop<hugeint_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29758
|
-
break;
|
|
29759
|
-
case PhysicalType::FLOAT:
|
|
29760
|
-
comp_res = TemplatedCompareListLoop<float>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29761
|
-
break;
|
|
29762
|
-
case PhysicalType::DOUBLE:
|
|
29763
|
-
comp_res = TemplatedCompareListLoop<double>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29764
|
-
break;
|
|
29765
|
-
case PhysicalType::INTERVAL:
|
|
29766
|
-
comp_res = TemplatedCompareListLoop<interval_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
29767
|
-
break;
|
|
29768
|
-
default:
|
|
29769
|
-
throw NotImplementedException("CompareListAndAdvance for fixed-size type %s", type.ToString());
|
|
29770
|
-
}
|
|
29771
|
-
} else {
|
|
29772
|
-
// Variable-sized list entries
|
|
29773
|
-
bool left_valid;
|
|
29774
|
-
bool right_valid;
|
|
29775
|
-
idx_t entry_idx;
|
|
29776
|
-
idx_t idx_in_entry;
|
|
29777
|
-
// Size (in bytes) of all variable-sizes entries is stored before the entries begin,
|
|
29778
|
-
// to make deserialization easier. We need to skip over them
|
|
29779
|
-
left_ptr += left_len * sizeof(idx_t);
|
|
29780
|
-
right_ptr += right_len * sizeof(idx_t);
|
|
29781
|
-
for (idx_t i = 0; i < count; i++) {
|
|
29782
|
-
ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry);
|
|
29783
|
-
left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
29784
|
-
right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
29785
|
-
if (left_valid && right_valid) {
|
|
29786
|
-
switch (type.InternalType()) {
|
|
29787
|
-
case PhysicalType::LIST:
|
|
29788
|
-
comp_res = CompareListAndAdvance(left_ptr, right_ptr, ListType::GetChildType(type));
|
|
29789
|
-
break;
|
|
29790
|
-
case PhysicalType::VARCHAR:
|
|
29791
|
-
comp_res = CompareStringAndAdvance(left_ptr, right_ptr);
|
|
29792
|
-
break;
|
|
29793
|
-
case PhysicalType::STRUCT:
|
|
29794
|
-
comp_res = CompareStructAndAdvance(left_ptr, right_ptr, StructType::GetChildTypes(type));
|
|
29795
|
-
break;
|
|
29796
|
-
default:
|
|
29797
|
-
throw NotImplementedException("CompareListAndAdvance for variable-size type %s", type.ToString());
|
|
29798
|
-
}
|
|
29799
|
-
} else if (!left_valid && !right_valid) {
|
|
29800
|
-
comp_res = 0;
|
|
29801
|
-
} else if (left_valid) {
|
|
29802
|
-
comp_res = -1;
|
|
29803
|
-
} else {
|
|
29804
|
-
comp_res = 1;
|
|
29805
|
-
}
|
|
29806
|
-
if (comp_res != 0) {
|
|
29807
|
-
break;
|
|
29808
|
-
}
|
|
29809
|
-
}
|
|
29810
|
-
}
|
|
29811
|
-
// All values that we looped over were equal
|
|
29812
|
-
if (comp_res == 0 && left_len != right_len) {
|
|
29813
|
-
// Smaller lists first
|
|
29814
|
-
if (left_len < right_len) {
|
|
29815
|
-
comp_res = -1;
|
|
29816
|
-
} else {
|
|
29817
|
-
comp_res = 1;
|
|
29818
|
-
}
|
|
29819
|
-
}
|
|
29820
|
-
return comp_res;
|
|
29821
|
-
}
|
|
29822
|
-
|
|
29823
|
-
template <class T>
|
|
29824
|
-
int Comparators::TemplatedCompareListLoop(data_ptr_t &left_ptr, data_ptr_t &right_ptr,
|
|
29825
|
-
const ValidityBytes &left_validity, const ValidityBytes &right_validity,
|
|
29826
|
-
const idx_t &count) {
|
|
29827
|
-
int comp_res = 0;
|
|
29828
|
-
bool left_valid;
|
|
29829
|
-
bool right_valid;
|
|
29830
|
-
idx_t entry_idx;
|
|
29831
|
-
idx_t idx_in_entry;
|
|
29832
|
-
for (idx_t i = 0; i < count; i++) {
|
|
29833
|
-
ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry);
|
|
29834
|
-
left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
29835
|
-
right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
29836
|
-
comp_res = TemplatedCompareAndAdvance<T>(left_ptr, right_ptr);
|
|
29837
|
-
if (!left_valid && !right_valid) {
|
|
29838
|
-
comp_res = 0;
|
|
29839
|
-
} else if (!left_valid) {
|
|
29840
|
-
comp_res = 1;
|
|
29841
|
-
} else if (!right_valid) {
|
|
29842
|
-
comp_res = -1;
|
|
29843
|
-
}
|
|
29844
|
-
if (comp_res != 0) {
|
|
29845
|
-
break;
|
|
29846
|
-
}
|
|
29847
|
-
}
|
|
29848
|
-
return comp_res;
|
|
29849
|
-
}
|
|
29850
|
-
|
|
29851
|
-
void Comparators::UnswizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type) {
|
|
29852
|
-
if (type.InternalType() == PhysicalType::VARCHAR) {
|
|
29853
|
-
data_ptr += sizeof(uint32_t) + string_t::PREFIX_LENGTH;
|
|
29854
|
-
}
|
|
29855
|
-
Store<data_ptr_t>(heap_ptr + Load<idx_t>(data_ptr), data_ptr);
|
|
29856
|
-
}
|
|
29857
|
-
|
|
29858
|
-
void Comparators::SwizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type) {
|
|
29859
|
-
if (type.InternalType() == PhysicalType::VARCHAR) {
|
|
29860
|
-
data_ptr += sizeof(uint32_t) + string_t::PREFIX_LENGTH;
|
|
29861
|
-
}
|
|
29862
|
-
Store<idx_t>(Load<data_ptr_t>(data_ptr) - heap_ptr, data_ptr);
|
|
29863
|
-
}
|
|
29864
|
-
|
|
29865
|
-
} // namespace duckdb
|
|
29866
|
-
// DuckDB
|
|
29867
|
-
//
|
|
29868
|
-
// duckdb/common/fast_mem.hpp
|
|
29869
|
-
//
|
|
29870
|
-
//
|
|
29871
|
-
//===----------------------------------------------------------------------===//
|
|
29872
|
-
|
|
29873
|
-
|
|
29874
|
-
|
|
29875
|
-
|
|
29876
|
-
|
|
29877
|
-
|
|
29878
|
-
template <size_t SIZE>
|
|
29879
|
-
static inline void MemcpyFixed(void *dest, const void *src) {
|
|
29880
|
-
memcpy(dest, src, SIZE);
|
|
29881
|
-
}
|
|
29882
|
-
|
|
29883
|
-
template <size_t SIZE>
|
|
29884
|
-
static inline int MemcmpFixed(const void *str1, const void *str2) {
|
|
29885
|
-
return memcmp(str1, str2, SIZE);
|
|
29886
|
-
}
|
|
29196
|
+
template <size_t SIZE>
|
|
29197
|
+
static inline int MemcmpFixed(const void *str1, const void *str2) {
|
|
29198
|
+
return memcmp(str1, str2, SIZE);
|
|
29199
|
+
}
|
|
29887
29200
|
|
|
29888
29201
|
namespace duckdb {
|
|
29889
29202
|
|
|
@@ -30408,151 +29721,847 @@ static inline void FastMemcpy(void *dest, const void *src, const size_t size) {
|
|
|
30408
29721
|
case 256:
|
|
30409
29722
|
return MemcpyFixed<256>(dest, src);
|
|
30410
29723
|
default:
|
|
30411
|
-
memcpy(dest, src, size);
|
|
29724
|
+
memcpy(dest, src, size);
|
|
29725
|
+
}
|
|
29726
|
+
// LCOV_EXCL_STOP
|
|
29727
|
+
}
|
|
29728
|
+
|
|
29729
|
+
//! This templated memcmp is significantly faster than std::memcmp,
|
|
29730
|
+
//! but only when you are calling memcmp with a const size in a loop.
|
|
29731
|
+
//! For instance `while (<cond>) { memcmp(<str1>, <str2>, const_size); ... }`
|
|
29732
|
+
static inline int FastMemcmp(const void *str1, const void *str2, const size_t size) {
|
|
29733
|
+
// LCOV_EXCL_START
|
|
29734
|
+
switch (size) {
|
|
29735
|
+
case 0:
|
|
29736
|
+
return 0;
|
|
29737
|
+
case 1:
|
|
29738
|
+
return MemcmpFixed<1>(str1, str2);
|
|
29739
|
+
case 2:
|
|
29740
|
+
return MemcmpFixed<2>(str1, str2);
|
|
29741
|
+
case 3:
|
|
29742
|
+
return MemcmpFixed<3>(str1, str2);
|
|
29743
|
+
case 4:
|
|
29744
|
+
return MemcmpFixed<4>(str1, str2);
|
|
29745
|
+
case 5:
|
|
29746
|
+
return MemcmpFixed<5>(str1, str2);
|
|
29747
|
+
case 6:
|
|
29748
|
+
return MemcmpFixed<6>(str1, str2);
|
|
29749
|
+
case 7:
|
|
29750
|
+
return MemcmpFixed<7>(str1, str2);
|
|
29751
|
+
case 8:
|
|
29752
|
+
return MemcmpFixed<8>(str1, str2);
|
|
29753
|
+
case 9:
|
|
29754
|
+
return MemcmpFixed<9>(str1, str2);
|
|
29755
|
+
case 10:
|
|
29756
|
+
return MemcmpFixed<10>(str1, str2);
|
|
29757
|
+
case 11:
|
|
29758
|
+
return MemcmpFixed<11>(str1, str2);
|
|
29759
|
+
case 12:
|
|
29760
|
+
return MemcmpFixed<12>(str1, str2);
|
|
29761
|
+
case 13:
|
|
29762
|
+
return MemcmpFixed<13>(str1, str2);
|
|
29763
|
+
case 14:
|
|
29764
|
+
return MemcmpFixed<14>(str1, str2);
|
|
29765
|
+
case 15:
|
|
29766
|
+
return MemcmpFixed<15>(str1, str2);
|
|
29767
|
+
case 16:
|
|
29768
|
+
return MemcmpFixed<16>(str1, str2);
|
|
29769
|
+
case 17:
|
|
29770
|
+
return MemcmpFixed<17>(str1, str2);
|
|
29771
|
+
case 18:
|
|
29772
|
+
return MemcmpFixed<18>(str1, str2);
|
|
29773
|
+
case 19:
|
|
29774
|
+
return MemcmpFixed<19>(str1, str2);
|
|
29775
|
+
case 20:
|
|
29776
|
+
return MemcmpFixed<20>(str1, str2);
|
|
29777
|
+
case 21:
|
|
29778
|
+
return MemcmpFixed<21>(str1, str2);
|
|
29779
|
+
case 22:
|
|
29780
|
+
return MemcmpFixed<22>(str1, str2);
|
|
29781
|
+
case 23:
|
|
29782
|
+
return MemcmpFixed<23>(str1, str2);
|
|
29783
|
+
case 24:
|
|
29784
|
+
return MemcmpFixed<24>(str1, str2);
|
|
29785
|
+
case 25:
|
|
29786
|
+
return MemcmpFixed<25>(str1, str2);
|
|
29787
|
+
case 26:
|
|
29788
|
+
return MemcmpFixed<26>(str1, str2);
|
|
29789
|
+
case 27:
|
|
29790
|
+
return MemcmpFixed<27>(str1, str2);
|
|
29791
|
+
case 28:
|
|
29792
|
+
return MemcmpFixed<28>(str1, str2);
|
|
29793
|
+
case 29:
|
|
29794
|
+
return MemcmpFixed<29>(str1, str2);
|
|
29795
|
+
case 30:
|
|
29796
|
+
return MemcmpFixed<30>(str1, str2);
|
|
29797
|
+
case 31:
|
|
29798
|
+
return MemcmpFixed<31>(str1, str2);
|
|
29799
|
+
case 32:
|
|
29800
|
+
return MemcmpFixed<32>(str1, str2);
|
|
29801
|
+
case 33:
|
|
29802
|
+
return MemcmpFixed<33>(str1, str2);
|
|
29803
|
+
case 34:
|
|
29804
|
+
return MemcmpFixed<34>(str1, str2);
|
|
29805
|
+
case 35:
|
|
29806
|
+
return MemcmpFixed<35>(str1, str2);
|
|
29807
|
+
case 36:
|
|
29808
|
+
return MemcmpFixed<36>(str1, str2);
|
|
29809
|
+
case 37:
|
|
29810
|
+
return MemcmpFixed<37>(str1, str2);
|
|
29811
|
+
case 38:
|
|
29812
|
+
return MemcmpFixed<38>(str1, str2);
|
|
29813
|
+
case 39:
|
|
29814
|
+
return MemcmpFixed<39>(str1, str2);
|
|
29815
|
+
case 40:
|
|
29816
|
+
return MemcmpFixed<40>(str1, str2);
|
|
29817
|
+
case 41:
|
|
29818
|
+
return MemcmpFixed<41>(str1, str2);
|
|
29819
|
+
case 42:
|
|
29820
|
+
return MemcmpFixed<42>(str1, str2);
|
|
29821
|
+
case 43:
|
|
29822
|
+
return MemcmpFixed<43>(str1, str2);
|
|
29823
|
+
case 44:
|
|
29824
|
+
return MemcmpFixed<44>(str1, str2);
|
|
29825
|
+
case 45:
|
|
29826
|
+
return MemcmpFixed<45>(str1, str2);
|
|
29827
|
+
case 46:
|
|
29828
|
+
return MemcmpFixed<46>(str1, str2);
|
|
29829
|
+
case 47:
|
|
29830
|
+
return MemcmpFixed<47>(str1, str2);
|
|
29831
|
+
case 48:
|
|
29832
|
+
return MemcmpFixed<48>(str1, str2);
|
|
29833
|
+
case 49:
|
|
29834
|
+
return MemcmpFixed<49>(str1, str2);
|
|
29835
|
+
case 50:
|
|
29836
|
+
return MemcmpFixed<50>(str1, str2);
|
|
29837
|
+
case 51:
|
|
29838
|
+
return MemcmpFixed<51>(str1, str2);
|
|
29839
|
+
case 52:
|
|
29840
|
+
return MemcmpFixed<52>(str1, str2);
|
|
29841
|
+
case 53:
|
|
29842
|
+
return MemcmpFixed<53>(str1, str2);
|
|
29843
|
+
case 54:
|
|
29844
|
+
return MemcmpFixed<54>(str1, str2);
|
|
29845
|
+
case 55:
|
|
29846
|
+
return MemcmpFixed<55>(str1, str2);
|
|
29847
|
+
case 56:
|
|
29848
|
+
return MemcmpFixed<56>(str1, str2);
|
|
29849
|
+
case 57:
|
|
29850
|
+
return MemcmpFixed<57>(str1, str2);
|
|
29851
|
+
case 58:
|
|
29852
|
+
return MemcmpFixed<58>(str1, str2);
|
|
29853
|
+
case 59:
|
|
29854
|
+
return MemcmpFixed<59>(str1, str2);
|
|
29855
|
+
case 60:
|
|
29856
|
+
return MemcmpFixed<60>(str1, str2);
|
|
29857
|
+
case 61:
|
|
29858
|
+
return MemcmpFixed<61>(str1, str2);
|
|
29859
|
+
case 62:
|
|
29860
|
+
return MemcmpFixed<62>(str1, str2);
|
|
29861
|
+
case 63:
|
|
29862
|
+
return MemcmpFixed<63>(str1, str2);
|
|
29863
|
+
case 64:
|
|
29864
|
+
return MemcmpFixed<64>(str1, str2);
|
|
29865
|
+
default:
|
|
29866
|
+
return memcmp(str1, str2, size);
|
|
29867
|
+
}
|
|
29868
|
+
// LCOV_EXCL_STOP
|
|
29869
|
+
}
|
|
29870
|
+
|
|
29871
|
+
} // namespace duckdb
|
|
29872
|
+
|
|
29873
|
+
//===----------------------------------------------------------------------===//
|
|
29874
|
+
// DuckDB
|
|
29875
|
+
//
|
|
29876
|
+
// duckdb/common/sort/sort.hpp
|
|
29877
|
+
//
|
|
29878
|
+
//
|
|
29879
|
+
//===----------------------------------------------------------------------===//
|
|
29880
|
+
|
|
29881
|
+
|
|
29882
|
+
|
|
29883
|
+
//===----------------------------------------------------------------------===//
|
|
29884
|
+
// DuckDB
|
|
29885
|
+
//
|
|
29886
|
+
// duckdb/common/sort/sorted_block.hpp
|
|
29887
|
+
//
|
|
29888
|
+
//
|
|
29889
|
+
//===----------------------------------------------------------------------===//
|
|
29890
|
+
|
|
29891
|
+
|
|
29892
|
+
|
|
29893
|
+
|
|
29894
|
+
namespace duckdb {
|
|
29895
|
+
|
|
29896
|
+
class BufferManager;
|
|
29897
|
+
struct RowDataBlock;
|
|
29898
|
+
struct SortLayout;
|
|
29899
|
+
struct GlobalSortState;
|
|
29900
|
+
|
|
29901
|
+
//! Object that holds sorted rows, and an accompanying heap if there are blobs
|
|
29902
|
+
struct SortedData {
|
|
29903
|
+
public:
|
|
29904
|
+
SortedData(const RowLayout &layout, BufferManager &buffer_manager, GlobalSortState &state);
|
|
29905
|
+
//! Number of rows that this object holds
|
|
29906
|
+
idx_t Count();
|
|
29907
|
+
//! Pin the current block so it can be read
|
|
29908
|
+
void Pin();
|
|
29909
|
+
//! Pointer to the row that is currently being read from
|
|
29910
|
+
data_ptr_t DataPtr() const;
|
|
29911
|
+
//! Pointer to the heap row that corresponds to the current row
|
|
29912
|
+
data_ptr_t HeapPtr() const;
|
|
29913
|
+
//! Advance one row
|
|
29914
|
+
void Advance(const bool &adv);
|
|
29915
|
+
//! Initialize new block to write to
|
|
29916
|
+
void CreateBlock();
|
|
29917
|
+
//! Reset read indices to the given indices
|
|
29918
|
+
void ResetIndices(idx_t block_idx_to, idx_t entry_idx_to);
|
|
29919
|
+
//! Create a slice that holds the rows between the start and end indices
|
|
29920
|
+
unique_ptr<SortedData> CreateSlice(idx_t start_block_index, idx_t start_entry_index, idx_t end_block_index,
|
|
29921
|
+
idx_t end_entry_index);
|
|
29922
|
+
//! Unswizzles all
|
|
29923
|
+
void Unswizzle();
|
|
29924
|
+
|
|
29925
|
+
public:
|
|
29926
|
+
//! Layout of this data
|
|
29927
|
+
const RowLayout layout;
|
|
29928
|
+
//! Data and heap blocks
|
|
29929
|
+
vector<RowDataBlock> data_blocks;
|
|
29930
|
+
vector<RowDataBlock> heap_blocks;
|
|
29931
|
+
//! Buffer handles to the data being currently read
|
|
29932
|
+
unique_ptr<BufferHandle> data_handle;
|
|
29933
|
+
unique_ptr<BufferHandle> heap_handle;
|
|
29934
|
+
//! Read indices
|
|
29935
|
+
idx_t block_idx;
|
|
29936
|
+
idx_t entry_idx;
|
|
29937
|
+
//! Whether the pointers in this sorted data are swizzled
|
|
29938
|
+
bool swizzled;
|
|
29939
|
+
|
|
29940
|
+
private:
|
|
29941
|
+
//! Pin fixed-size row data
|
|
29942
|
+
void PinData();
|
|
29943
|
+
//! Pin the accompanying heap data (if any)
|
|
29944
|
+
void PinHeap();
|
|
29945
|
+
|
|
29946
|
+
private:
|
|
29947
|
+
//! The buffer manager
|
|
29948
|
+
BufferManager &buffer_manager;
|
|
29949
|
+
//! The global state
|
|
29950
|
+
GlobalSortState &state;
|
|
29951
|
+
//! Pointers into the buffers being currently read
|
|
29952
|
+
data_ptr_t data_ptr;
|
|
29953
|
+
data_ptr_t heap_ptr;
|
|
29954
|
+
};
|
|
29955
|
+
|
|
29956
|
+
//! Block that holds sorted rows: radix, blob and payload data
|
|
29957
|
+
struct SortedBlock {
|
|
29958
|
+
public:
|
|
29959
|
+
SortedBlock(BufferManager &buffer_manager, GlobalSortState &gstate);
|
|
29960
|
+
//! Number of rows that this object holds
|
|
29961
|
+
idx_t Count() const;
|
|
29962
|
+
//! The remaining number of rows to be read from this object
|
|
29963
|
+
idx_t Remaining() const;
|
|
29964
|
+
//! Initialize this block to write data to
|
|
29965
|
+
void InitializeWrite();
|
|
29966
|
+
//! Init new block to write to
|
|
29967
|
+
void CreateBlock();
|
|
29968
|
+
//! Pins radix block with given index
|
|
29969
|
+
void PinRadix(idx_t pin_block_idx);
|
|
29970
|
+
//! Fill this sorted block by appending the blocks held by a vector of sorted blocks
|
|
29971
|
+
void AppendSortedBlocks(vector<unique_ptr<SortedBlock>> &sorted_blocks);
|
|
29972
|
+
//! Locate the block and entry index of a row in this block,
|
|
29973
|
+
//! given an index between 0 and the total number of rows in this block
|
|
29974
|
+
void GlobalToLocalIndex(const idx_t &global_idx, idx_t &local_block_index, idx_t &local_entry_index);
|
|
29975
|
+
//! Create a slice that holds the rows between the start and end indices
|
|
29976
|
+
unique_ptr<SortedBlock> CreateSlice(const idx_t start, const idx_t end);
|
|
29977
|
+
|
|
29978
|
+
//! Size (in bytes) of the heap of this block
|
|
29979
|
+
idx_t HeapSize() const;
|
|
29980
|
+
//! Total size (in bytes) of this block
|
|
29981
|
+
idx_t SizeInBytes() const;
|
|
29982
|
+
|
|
29983
|
+
public:
|
|
29984
|
+
//! Radix/memcmp sortable data
|
|
29985
|
+
vector<RowDataBlock> radix_sorting_data;
|
|
29986
|
+
unique_ptr<BufferHandle> radix_handle;
|
|
29987
|
+
idx_t block_idx;
|
|
29988
|
+
idx_t entry_idx;
|
|
29989
|
+
//! Variable sized sorting data
|
|
29990
|
+
unique_ptr<SortedData> blob_sorting_data;
|
|
29991
|
+
//! Payload data
|
|
29992
|
+
unique_ptr<SortedData> payload_data;
|
|
29993
|
+
|
|
29994
|
+
private:
|
|
29995
|
+
//! Buffer manager, and sorting layout constants
|
|
29996
|
+
BufferManager &buffer_manager;
|
|
29997
|
+
GlobalSortState &state;
|
|
29998
|
+
const SortLayout &sort_layout;
|
|
29999
|
+
const RowLayout &payload_layout;
|
|
30000
|
+
};
|
|
30001
|
+
|
|
30002
|
+
struct SortedDataScanner {
|
|
30003
|
+
public:
|
|
30004
|
+
SortedDataScanner(SortedData &sorted_data, GlobalSortState &global_sort_state);
|
|
30005
|
+
|
|
30006
|
+
//! Scans the next data chunk from the sorted data
|
|
30007
|
+
void Scan(DataChunk &chunk);
|
|
30008
|
+
|
|
30009
|
+
private:
|
|
30010
|
+
//! The sorted data being scanned
|
|
30011
|
+
SortedData &sorted_data;
|
|
30012
|
+
//! The total count of sorted_data
|
|
30013
|
+
const idx_t total_count;
|
|
30014
|
+
//! The global sort state
|
|
30015
|
+
GlobalSortState &global_sort_state;
|
|
30016
|
+
//! Addresses used to gather from the sorted data
|
|
30017
|
+
Vector addresses = Vector(LogicalType::POINTER);
|
|
30018
|
+
//! The number of rows scanned so far
|
|
30019
|
+
idx_t total_scanned;
|
|
30020
|
+
};
|
|
30021
|
+
|
|
30022
|
+
} // namespace duckdb
|
|
30023
|
+
|
|
30024
|
+
|
|
30025
|
+
|
|
30026
|
+
|
|
30027
|
+
namespace duckdb {
|
|
30028
|
+
|
|
30029
|
+
class RowLayout;
|
|
30030
|
+
struct LocalSortState;
|
|
30031
|
+
|
|
30032
|
+
struct SortConstants {
|
|
30033
|
+
static constexpr idx_t VALUES_PER_RADIX = 256;
|
|
30034
|
+
static constexpr idx_t MSD_RADIX_LOCATIONS = VALUES_PER_RADIX + 1;
|
|
30035
|
+
static constexpr idx_t INSERTION_SORT_THRESHOLD = 24;
|
|
30036
|
+
static constexpr idx_t MSD_RADIX_SORT_SIZE_THRESHOLD = 4;
|
|
30037
|
+
};
|
|
30038
|
+
|
|
30039
|
+
struct SortLayout {
|
|
30040
|
+
public:
|
|
30041
|
+
explicit SortLayout(const vector<BoundOrderByNode> &orders);
|
|
30042
|
+
|
|
30043
|
+
public:
|
|
30044
|
+
idx_t column_count;
|
|
30045
|
+
vector<OrderType> order_types;
|
|
30046
|
+
vector<OrderByNullType> order_by_null_types;
|
|
30047
|
+
vector<LogicalType> logical_types;
|
|
30048
|
+
|
|
30049
|
+
bool all_constant;
|
|
30050
|
+
vector<bool> constant_size;
|
|
30051
|
+
vector<idx_t> column_sizes;
|
|
30052
|
+
vector<idx_t> prefix_lengths;
|
|
30053
|
+
vector<BaseStatistics *> stats;
|
|
30054
|
+
vector<bool> has_null;
|
|
30055
|
+
|
|
30056
|
+
idx_t comparison_size;
|
|
30057
|
+
idx_t entry_size;
|
|
30058
|
+
|
|
30059
|
+
RowLayout blob_layout;
|
|
30060
|
+
unordered_map<idx_t, idx_t> sorting_to_blob_col;
|
|
30061
|
+
};
|
|
30062
|
+
|
|
30063
|
+
struct GlobalSortState {
|
|
30064
|
+
public:
|
|
30065
|
+
GlobalSortState(BufferManager &buffer_manager, const vector<BoundOrderByNode> &orders, RowLayout &payload_layout);
|
|
30066
|
+
|
|
30067
|
+
//! Add local state sorted data to this global state
|
|
30068
|
+
void AddLocalState(LocalSortState &local_sort_state);
|
|
30069
|
+
//! Prepares the GlobalSortState for the merge sort phase (after completing radix sort phase)
|
|
30070
|
+
void PrepareMergePhase();
|
|
30071
|
+
//! Initializes the global sort state for another round of merging
|
|
30072
|
+
void InitializeMergeRound();
|
|
30073
|
+
//! Completes the cascaded merge sort round
|
|
30074
|
+
void CompleteMergeRound();
|
|
30075
|
+
|
|
30076
|
+
public:
|
|
30077
|
+
//! The lock for updating the order global state
|
|
30078
|
+
mutex lock;
|
|
30079
|
+
//! The buffer manager
|
|
30080
|
+
BufferManager &buffer_manager;
|
|
30081
|
+
|
|
30082
|
+
//! Sorting and payload layouts
|
|
30083
|
+
const SortLayout sort_layout;
|
|
30084
|
+
const RowLayout payload_layout;
|
|
30085
|
+
|
|
30086
|
+
//! Sorted data
|
|
30087
|
+
vector<unique_ptr<SortedBlock>> sorted_blocks;
|
|
30088
|
+
vector<vector<unique_ptr<SortedBlock>>> sorted_blocks_temp;
|
|
30089
|
+
unique_ptr<SortedBlock> odd_one_out;
|
|
30090
|
+
|
|
30091
|
+
//! Pinned heap data (if sorting in memory)
|
|
30092
|
+
vector<RowDataBlock> heap_blocks;
|
|
30093
|
+
vector<unique_ptr<BufferHandle>> pinned_blocks;
|
|
30094
|
+
|
|
30095
|
+
//! Capacity (number of rows) used to initialize blocks
|
|
30096
|
+
idx_t block_capacity;
|
|
30097
|
+
//! Whether we are doing an external sort
|
|
30098
|
+
bool external;
|
|
30099
|
+
|
|
30100
|
+
//! Progress in merge path stage
|
|
30101
|
+
idx_t pair_idx;
|
|
30102
|
+
idx_t num_pairs;
|
|
30103
|
+
idx_t l_start;
|
|
30104
|
+
idx_t r_start;
|
|
30105
|
+
};
|
|
30106
|
+
|
|
30107
|
+
struct LocalSortState {
|
|
30108
|
+
public:
|
|
30109
|
+
LocalSortState();
|
|
30110
|
+
|
|
30111
|
+
//! Initialize the layouts and RowDataCollections
|
|
30112
|
+
void Initialize(GlobalSortState &global_sort_state, BufferManager &buffer_manager_p);
|
|
30113
|
+
//! Sink one DataChunk into the local sort state
|
|
30114
|
+
void SinkChunk(DataChunk &sort, DataChunk &payload);
|
|
30115
|
+
//! Size of accumulated data in bytes
|
|
30116
|
+
idx_t SizeInBytes() const;
|
|
30117
|
+
//! Sort the data accumulated so far
|
|
30118
|
+
void Sort(GlobalSortState &global_sort_state, bool reorder_heap);
|
|
30119
|
+
|
|
30120
|
+
private:
|
|
30121
|
+
//! Concatenate the blocks held by a RowDataCollection into a single block
|
|
30122
|
+
RowDataBlock ConcatenateBlocks(RowDataCollection &row_data);
|
|
30123
|
+
//! Sorts the data in the newly created SortedBlock
|
|
30124
|
+
void SortInMemory();
|
|
30125
|
+
//! Re-order the local state after sorting
|
|
30126
|
+
void ReOrder(GlobalSortState &gstate, bool reorder_heap);
|
|
30127
|
+
//! Re-order a SortedData object after sorting
|
|
30128
|
+
void ReOrder(SortedData &sd, data_ptr_t sorting_ptr, RowDataCollection &heap, GlobalSortState &gstate,
|
|
30129
|
+
bool reorder_heap);
|
|
30130
|
+
|
|
30131
|
+
public:
|
|
30132
|
+
//! Whether this local state has been initialized
|
|
30133
|
+
bool initialized;
|
|
30134
|
+
//! The buffer manager
|
|
30135
|
+
BufferManager *buffer_manager;
|
|
30136
|
+
//! The sorting and payload layouts
|
|
30137
|
+
const SortLayout *sort_layout;
|
|
30138
|
+
const RowLayout *payload_layout;
|
|
30139
|
+
//! Radix/memcmp sortable data
|
|
30140
|
+
unique_ptr<RowDataCollection> radix_sorting_data;
|
|
30141
|
+
//! Variable sized sorting data and accompanying heap
|
|
30142
|
+
unique_ptr<RowDataCollection> blob_sorting_data;
|
|
30143
|
+
unique_ptr<RowDataCollection> blob_sorting_heap;
|
|
30144
|
+
//! Payload data and accompanying heap
|
|
30145
|
+
unique_ptr<RowDataCollection> payload_data;
|
|
30146
|
+
unique_ptr<RowDataCollection> payload_heap;
|
|
30147
|
+
//! Sorted data
|
|
30148
|
+
vector<unique_ptr<SortedBlock>> sorted_blocks;
|
|
30149
|
+
|
|
30150
|
+
private:
|
|
30151
|
+
//! Selection vector and addresses for scattering the data to rows
|
|
30152
|
+
const SelectionVector &sel_ptr = FlatVector::INCREMENTAL_SELECTION_VECTOR;
|
|
30153
|
+
Vector addresses = Vector(LogicalType::POINTER);
|
|
30154
|
+
};
|
|
30155
|
+
|
|
30156
|
+
struct MergeSorter {
|
|
30157
|
+
public:
|
|
30158
|
+
MergeSorter(GlobalSortState &state, BufferManager &buffer_manager);
|
|
30159
|
+
|
|
30160
|
+
//! Finds and merges partitions until the current cascaded merge round is finished
|
|
30161
|
+
void PerformInMergeRound();
|
|
30162
|
+
|
|
30163
|
+
private:
|
|
30164
|
+
//! Computes the left and right block that will be merged next (Merge Path partition)
|
|
30165
|
+
void GetNextPartition();
|
|
30166
|
+
//! Finds the boundary of the next partition using binary search
|
|
30167
|
+
void GetIntersection(SortedBlock &l, SortedBlock &r, const idx_t diagonal, idx_t &l_idx, idx_t &r_idx);
|
|
30168
|
+
//! Compare values within SortedBlocks using a global index
|
|
30169
|
+
int CompareUsingGlobalIndex(SortedBlock &l, SortedBlock &r, const idx_t l_idx, const idx_t r_idx);
|
|
30170
|
+
|
|
30171
|
+
//! Finds the next partition and merges it
|
|
30172
|
+
void MergePartition();
|
|
30173
|
+
|
|
30174
|
+
//! Computes how the next 'count' tuples should be merged by setting the 'left_smaller' array
|
|
30175
|
+
void ComputeMerge(const idx_t &count, bool left_smaller[]);
|
|
30176
|
+
|
|
30177
|
+
//! Merges the radix sorting blocks according to the 'left_smaller' array
|
|
30178
|
+
void MergeRadix(const idx_t &count, const bool left_smaller[]);
|
|
30179
|
+
//! Merges SortedData according to the 'left_smaller' array
|
|
30180
|
+
void MergeData(SortedData &result_data, SortedData &l_data, SortedData &r_data, const idx_t &count,
|
|
30181
|
+
const bool left_smaller[], idx_t next_entry_sizes[]);
|
|
30182
|
+
//! Merges constant size rows according to the 'left_smaller' array
|
|
30183
|
+
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,
|
|
30184
|
+
const idx_t &r_count, RowDataBlock *target_block, data_ptr_t &target_ptr, const idx_t &entry_size,
|
|
30185
|
+
const bool left_smaller[], idx_t &copied, const idx_t &count);
|
|
30186
|
+
//! Flushes constant size rows into the result
|
|
30187
|
+
void FlushRows(data_ptr_t &source_ptr, idx_t &source_entry_idx, const idx_t &source_count,
|
|
30188
|
+
RowDataBlock *target_block, data_ptr_t &target_ptr, const idx_t &entry_size, idx_t &copied,
|
|
30189
|
+
const idx_t &count);
|
|
30190
|
+
//! Flushes blob rows and accompanying heap
|
|
30191
|
+
void FlushBlobs(const RowLayout &layout, const idx_t &source_count, data_ptr_t &source_data_ptr,
|
|
30192
|
+
idx_t &source_entry_idx, data_ptr_t &source_heap_ptr, RowDataBlock *target_data_block,
|
|
30193
|
+
data_ptr_t &target_data_ptr, RowDataBlock *target_heap_block, BufferHandle &target_heap_handle,
|
|
30194
|
+
data_ptr_t &target_heap_ptr, idx_t &copied, const idx_t &count);
|
|
30195
|
+
|
|
30196
|
+
private:
|
|
30197
|
+
//! The global sorting state
|
|
30198
|
+
GlobalSortState &state;
|
|
30199
|
+
//! The sorting and payload layouts
|
|
30200
|
+
BufferManager &buffer_manager;
|
|
30201
|
+
const SortLayout &sort_layout;
|
|
30202
|
+
|
|
30203
|
+
//! The left, right and result blocks of the current partition
|
|
30204
|
+
unique_ptr<SortedBlock> left_block;
|
|
30205
|
+
unique_ptr<SortedBlock> right_block;
|
|
30206
|
+
SortedBlock *result;
|
|
30207
|
+
};
|
|
30208
|
+
|
|
30209
|
+
} // namespace duckdb
|
|
30210
|
+
|
|
30211
|
+
|
|
30212
|
+
namespace duckdb {
|
|
30213
|
+
|
|
30214
|
+
bool Comparators::TieIsBreakable(const idx_t &col_idx, const data_ptr_t row_ptr, const RowLayout &row_layout) {
|
|
30215
|
+
// Check if the blob is NULL
|
|
30216
|
+
ValidityBytes row_mask(row_ptr);
|
|
30217
|
+
idx_t entry_idx;
|
|
30218
|
+
idx_t idx_in_entry;
|
|
30219
|
+
ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry);
|
|
30220
|
+
if (!row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry)) {
|
|
30221
|
+
// Can't break a NULL tie
|
|
30222
|
+
return false;
|
|
30223
|
+
}
|
|
30224
|
+
if (row_layout.GetTypes()[col_idx].InternalType() == PhysicalType::VARCHAR) {
|
|
30225
|
+
const auto &tie_col_offset = row_layout.GetOffsets()[col_idx];
|
|
30226
|
+
string_t tie_string = Load<string_t>(row_ptr + tie_col_offset);
|
|
30227
|
+
if (tie_string.GetSize() < string_t::INLINE_LENGTH) {
|
|
30228
|
+
// No need to break the tie - we already compared the full string
|
|
30229
|
+
return false;
|
|
30230
|
+
}
|
|
30231
|
+
}
|
|
30232
|
+
return true;
|
|
30233
|
+
}
|
|
30234
|
+
|
|
30235
|
+
int Comparators::CompareTuple(const SortedBlock &left, const SortedBlock &right, const data_ptr_t &l_ptr,
|
|
30236
|
+
const data_ptr_t &r_ptr, const SortLayout &sort_layout, const bool &external_sort) {
|
|
30237
|
+
// Compare the sorting columns one by one
|
|
30238
|
+
int comp_res = 0;
|
|
30239
|
+
data_ptr_t l_ptr_offset = l_ptr;
|
|
30240
|
+
data_ptr_t r_ptr_offset = r_ptr;
|
|
30241
|
+
for (idx_t col_idx = 0; col_idx < sort_layout.column_count; col_idx++) {
|
|
30242
|
+
comp_res = FastMemcmp(l_ptr_offset, r_ptr_offset, sort_layout.column_sizes[col_idx]);
|
|
30243
|
+
if (comp_res == 0 && !sort_layout.constant_size[col_idx]) {
|
|
30244
|
+
comp_res =
|
|
30245
|
+
BreakBlobTie(col_idx, *left.blob_sorting_data, *right.blob_sorting_data, sort_layout, external_sort);
|
|
30246
|
+
}
|
|
30247
|
+
if (comp_res != 0) {
|
|
30248
|
+
break;
|
|
30249
|
+
}
|
|
30250
|
+
l_ptr_offset += sort_layout.column_sizes[col_idx];
|
|
30251
|
+
r_ptr_offset += sort_layout.column_sizes[col_idx];
|
|
30252
|
+
}
|
|
30253
|
+
return comp_res;
|
|
30254
|
+
}
|
|
30255
|
+
|
|
30256
|
+
int Comparators::CompareVal(const data_ptr_t l_ptr, const data_ptr_t r_ptr, const LogicalType &type) {
|
|
30257
|
+
switch (type.InternalType()) {
|
|
30258
|
+
case PhysicalType::VARCHAR:
|
|
30259
|
+
return TemplatedCompareVal<string_t>(l_ptr, r_ptr);
|
|
30260
|
+
case PhysicalType::LIST:
|
|
30261
|
+
case PhysicalType::STRUCT: {
|
|
30262
|
+
auto l_nested_ptr = Load<data_ptr_t>(l_ptr);
|
|
30263
|
+
auto r_nested_ptr = Load<data_ptr_t>(r_ptr);
|
|
30264
|
+
return CompareValAndAdvance(l_nested_ptr, r_nested_ptr, type);
|
|
30265
|
+
}
|
|
30266
|
+
default:
|
|
30267
|
+
throw NotImplementedException("Unimplemented CompareVal for type %s", type.ToString());
|
|
30268
|
+
}
|
|
30269
|
+
}
|
|
30270
|
+
|
|
30271
|
+
int Comparators::BreakBlobTie(const idx_t &tie_col, const SortedData &left, const SortedData &right,
|
|
30272
|
+
const SortLayout &sort_layout, const bool &external) {
|
|
30273
|
+
const idx_t &col_idx = sort_layout.sorting_to_blob_col.at(tie_col);
|
|
30274
|
+
data_ptr_t l_data_ptr = left.DataPtr();
|
|
30275
|
+
data_ptr_t r_data_ptr = right.DataPtr();
|
|
30276
|
+
if (!TieIsBreakable(col_idx, l_data_ptr, sort_layout.blob_layout)) {
|
|
30277
|
+
// Quick check to see if ties can be broken
|
|
30278
|
+
return 0;
|
|
30279
|
+
}
|
|
30280
|
+
// Align the pointers
|
|
30281
|
+
const auto &tie_col_offset = sort_layout.blob_layout.GetOffsets()[col_idx];
|
|
30282
|
+
l_data_ptr += tie_col_offset;
|
|
30283
|
+
r_data_ptr += tie_col_offset;
|
|
30284
|
+
// Do the comparison
|
|
30285
|
+
const int order = sort_layout.order_types[tie_col] == OrderType::DESCENDING ? -1 : 1;
|
|
30286
|
+
const auto &type = left.layout.GetTypes()[col_idx];
|
|
30287
|
+
int result;
|
|
30288
|
+
if (external) {
|
|
30289
|
+
// Store heap pointers
|
|
30290
|
+
data_ptr_t l_heap_ptr = left.HeapPtr();
|
|
30291
|
+
data_ptr_t r_heap_ptr = right.HeapPtr();
|
|
30292
|
+
// Unswizzle offset to pointer
|
|
30293
|
+
UnswizzleSingleValue(l_data_ptr, l_heap_ptr, type);
|
|
30294
|
+
UnswizzleSingleValue(r_data_ptr, r_heap_ptr, type);
|
|
30295
|
+
// Compare
|
|
30296
|
+
result = CompareVal(l_data_ptr, r_data_ptr, type);
|
|
30297
|
+
// Swizzle the pointers back to offsets
|
|
30298
|
+
SwizzleSingleValue(l_data_ptr, l_heap_ptr, type);
|
|
30299
|
+
SwizzleSingleValue(r_data_ptr, r_heap_ptr, type);
|
|
30300
|
+
} else {
|
|
30301
|
+
result = CompareVal(l_data_ptr, r_data_ptr, type);
|
|
30302
|
+
}
|
|
30303
|
+
return order * result;
|
|
30304
|
+
}
|
|
30305
|
+
|
|
30306
|
+
template <class T>
|
|
30307
|
+
int Comparators::TemplatedCompareVal(const data_ptr_t &left_ptr, const data_ptr_t &right_ptr) {
|
|
30308
|
+
const auto left_val = Load<T>(left_ptr);
|
|
30309
|
+
const auto right_val = Load<T>(right_ptr);
|
|
30310
|
+
if (Equals::Operation<T>(left_val, right_val)) {
|
|
30311
|
+
return 0;
|
|
30312
|
+
} else if (LessThan::Operation<T>(left_val, right_val)) {
|
|
30313
|
+
return -1;
|
|
30314
|
+
} else {
|
|
30315
|
+
return 1;
|
|
30316
|
+
}
|
|
30317
|
+
}
|
|
30318
|
+
|
|
30319
|
+
int Comparators::CompareValAndAdvance(data_ptr_t &l_ptr, data_ptr_t &r_ptr, const LogicalType &type) {
|
|
30320
|
+
switch (type.InternalType()) {
|
|
30321
|
+
case PhysicalType::BOOL:
|
|
30322
|
+
case PhysicalType::INT8:
|
|
30323
|
+
return TemplatedCompareAndAdvance<int8_t>(l_ptr, r_ptr);
|
|
30324
|
+
case PhysicalType::INT16:
|
|
30325
|
+
return TemplatedCompareAndAdvance<int16_t>(l_ptr, r_ptr);
|
|
30326
|
+
case PhysicalType::INT32:
|
|
30327
|
+
return TemplatedCompareAndAdvance<int32_t>(l_ptr, r_ptr);
|
|
30328
|
+
case PhysicalType::INT64:
|
|
30329
|
+
return TemplatedCompareAndAdvance<int64_t>(l_ptr, r_ptr);
|
|
30330
|
+
case PhysicalType::UINT8:
|
|
30331
|
+
return TemplatedCompareAndAdvance<uint8_t>(l_ptr, r_ptr);
|
|
30332
|
+
case PhysicalType::UINT16:
|
|
30333
|
+
return TemplatedCompareAndAdvance<uint16_t>(l_ptr, r_ptr);
|
|
30334
|
+
case PhysicalType::UINT32:
|
|
30335
|
+
return TemplatedCompareAndAdvance<uint32_t>(l_ptr, r_ptr);
|
|
30336
|
+
case PhysicalType::UINT64:
|
|
30337
|
+
return TemplatedCompareAndAdvance<uint64_t>(l_ptr, r_ptr);
|
|
30338
|
+
case PhysicalType::INT128:
|
|
30339
|
+
return TemplatedCompareAndAdvance<hugeint_t>(l_ptr, r_ptr);
|
|
30340
|
+
case PhysicalType::FLOAT:
|
|
30341
|
+
return TemplatedCompareAndAdvance<float>(l_ptr, r_ptr);
|
|
30342
|
+
case PhysicalType::DOUBLE:
|
|
30343
|
+
return TemplatedCompareAndAdvance<double>(l_ptr, r_ptr);
|
|
30344
|
+
case PhysicalType::INTERVAL:
|
|
30345
|
+
return TemplatedCompareAndAdvance<interval_t>(l_ptr, r_ptr);
|
|
30346
|
+
case PhysicalType::VARCHAR:
|
|
30347
|
+
return CompareStringAndAdvance(l_ptr, r_ptr);
|
|
30348
|
+
case PhysicalType::LIST:
|
|
30349
|
+
return CompareListAndAdvance(l_ptr, r_ptr, ListType::GetChildType(type));
|
|
30350
|
+
case PhysicalType::STRUCT:
|
|
30351
|
+
return CompareStructAndAdvance(l_ptr, r_ptr, StructType::GetChildTypes(type));
|
|
30352
|
+
default:
|
|
30353
|
+
throw NotImplementedException("Unimplemented CompareValAndAdvance for type %s", type.ToString());
|
|
30354
|
+
}
|
|
30355
|
+
}
|
|
30356
|
+
|
|
30357
|
+
template <class T>
|
|
30358
|
+
int Comparators::TemplatedCompareAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr) {
|
|
30359
|
+
auto result = TemplatedCompareVal<T>(left_ptr, right_ptr);
|
|
30360
|
+
left_ptr += sizeof(T);
|
|
30361
|
+
right_ptr += sizeof(T);
|
|
30362
|
+
return result;
|
|
30363
|
+
}
|
|
30364
|
+
|
|
30365
|
+
int Comparators::CompareStringAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr) {
|
|
30366
|
+
// Construct the string_t
|
|
30367
|
+
uint32_t left_string_size = Load<uint32_t>(left_ptr);
|
|
30368
|
+
uint32_t right_string_size = Load<uint32_t>(right_ptr);
|
|
30369
|
+
left_ptr += sizeof(uint32_t);
|
|
30370
|
+
right_ptr += sizeof(uint32_t);
|
|
30371
|
+
string_t left_val((const char *)left_ptr, left_string_size);
|
|
30372
|
+
string_t right_val((const char *)right_ptr, right_string_size);
|
|
30373
|
+
left_ptr += left_string_size;
|
|
30374
|
+
right_ptr += right_string_size;
|
|
30375
|
+
// Compare
|
|
30376
|
+
return TemplatedCompareVal<string_t>((data_ptr_t)&left_val, (data_ptr_t)&right_val);
|
|
30377
|
+
}
|
|
30378
|
+
|
|
30379
|
+
int Comparators::CompareStructAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr,
|
|
30380
|
+
const child_list_t<LogicalType> &types) {
|
|
30381
|
+
idx_t count = types.size();
|
|
30382
|
+
// Load validity masks
|
|
30383
|
+
ValidityBytes left_validity(left_ptr);
|
|
30384
|
+
ValidityBytes right_validity(right_ptr);
|
|
30385
|
+
left_ptr += (count + 7) / 8;
|
|
30386
|
+
right_ptr += (count + 7) / 8;
|
|
30387
|
+
// Initialize variables
|
|
30388
|
+
bool left_valid;
|
|
30389
|
+
bool right_valid;
|
|
30390
|
+
idx_t entry_idx;
|
|
30391
|
+
idx_t idx_in_entry;
|
|
30392
|
+
// Compare
|
|
30393
|
+
int comp_res = 0;
|
|
30394
|
+
for (idx_t i = 0; i < count; i++) {
|
|
30395
|
+
ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry);
|
|
30396
|
+
left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
30397
|
+
right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
30398
|
+
auto &type = types[i].second;
|
|
30399
|
+
if ((left_valid && right_valid) || TypeIsConstantSize(type.InternalType())) {
|
|
30400
|
+
comp_res = CompareValAndAdvance(left_ptr, right_ptr, types[i].second);
|
|
30401
|
+
}
|
|
30402
|
+
if (!left_valid && !right_valid) {
|
|
30403
|
+
comp_res = 0;
|
|
30404
|
+
} else if (!left_valid) {
|
|
30405
|
+
comp_res = 1;
|
|
30406
|
+
} else if (!right_valid) {
|
|
30407
|
+
comp_res = -1;
|
|
30408
|
+
}
|
|
30409
|
+
if (comp_res != 0) {
|
|
30410
|
+
break;
|
|
30411
|
+
}
|
|
30412
|
+
}
|
|
30413
|
+
return comp_res;
|
|
30414
|
+
}
|
|
30415
|
+
|
|
30416
|
+
int Comparators::CompareListAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr, const LogicalType &type) {
|
|
30417
|
+
// Load list lengths
|
|
30418
|
+
auto left_len = Load<idx_t>(left_ptr);
|
|
30419
|
+
auto right_len = Load<idx_t>(right_ptr);
|
|
30420
|
+
left_ptr += sizeof(idx_t);
|
|
30421
|
+
right_ptr += sizeof(idx_t);
|
|
30422
|
+
// Load list validity masks
|
|
30423
|
+
ValidityBytes left_validity(left_ptr);
|
|
30424
|
+
ValidityBytes right_validity(right_ptr);
|
|
30425
|
+
left_ptr += (left_len + 7) / 8;
|
|
30426
|
+
right_ptr += (right_len + 7) / 8;
|
|
30427
|
+
// Compare
|
|
30428
|
+
int comp_res = 0;
|
|
30429
|
+
idx_t count = MinValue(left_len, right_len);
|
|
30430
|
+
if (TypeIsConstantSize(type.InternalType())) {
|
|
30431
|
+
// Templated code for fixed-size types
|
|
30432
|
+
switch (type.InternalType()) {
|
|
30433
|
+
case PhysicalType::BOOL:
|
|
30434
|
+
case PhysicalType::INT8:
|
|
30435
|
+
comp_res = TemplatedCompareListLoop<int8_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30436
|
+
break;
|
|
30437
|
+
case PhysicalType::INT16:
|
|
30438
|
+
comp_res = TemplatedCompareListLoop<int16_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30439
|
+
break;
|
|
30440
|
+
case PhysicalType::INT32:
|
|
30441
|
+
comp_res = TemplatedCompareListLoop<int32_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30442
|
+
break;
|
|
30443
|
+
case PhysicalType::INT64:
|
|
30444
|
+
comp_res = TemplatedCompareListLoop<int64_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30445
|
+
break;
|
|
30446
|
+
case PhysicalType::UINT8:
|
|
30447
|
+
comp_res = TemplatedCompareListLoop<uint8_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30448
|
+
break;
|
|
30449
|
+
case PhysicalType::UINT16:
|
|
30450
|
+
comp_res = TemplatedCompareListLoop<uint16_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30451
|
+
break;
|
|
30452
|
+
case PhysicalType::UINT32:
|
|
30453
|
+
comp_res = TemplatedCompareListLoop<uint32_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30454
|
+
break;
|
|
30455
|
+
case PhysicalType::UINT64:
|
|
30456
|
+
comp_res = TemplatedCompareListLoop<uint64_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30457
|
+
break;
|
|
30458
|
+
case PhysicalType::INT128:
|
|
30459
|
+
comp_res = TemplatedCompareListLoop<hugeint_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30460
|
+
break;
|
|
30461
|
+
case PhysicalType::FLOAT:
|
|
30462
|
+
comp_res = TemplatedCompareListLoop<float>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30463
|
+
break;
|
|
30464
|
+
case PhysicalType::DOUBLE:
|
|
30465
|
+
comp_res = TemplatedCompareListLoop<double>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30466
|
+
break;
|
|
30467
|
+
case PhysicalType::INTERVAL:
|
|
30468
|
+
comp_res = TemplatedCompareListLoop<interval_t>(left_ptr, right_ptr, left_validity, right_validity, count);
|
|
30469
|
+
break;
|
|
30470
|
+
default:
|
|
30471
|
+
throw NotImplementedException("CompareListAndAdvance for fixed-size type %s", type.ToString());
|
|
30472
|
+
}
|
|
30473
|
+
} else {
|
|
30474
|
+
// Variable-sized list entries
|
|
30475
|
+
bool left_valid;
|
|
30476
|
+
bool right_valid;
|
|
30477
|
+
idx_t entry_idx;
|
|
30478
|
+
idx_t idx_in_entry;
|
|
30479
|
+
// Size (in bytes) of all variable-sizes entries is stored before the entries begin,
|
|
30480
|
+
// to make deserialization easier. We need to skip over them
|
|
30481
|
+
left_ptr += left_len * sizeof(idx_t);
|
|
30482
|
+
right_ptr += right_len * sizeof(idx_t);
|
|
30483
|
+
for (idx_t i = 0; i < count; i++) {
|
|
30484
|
+
ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry);
|
|
30485
|
+
left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
30486
|
+
right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
30487
|
+
if (left_valid && right_valid) {
|
|
30488
|
+
switch (type.InternalType()) {
|
|
30489
|
+
case PhysicalType::LIST:
|
|
30490
|
+
comp_res = CompareListAndAdvance(left_ptr, right_ptr, ListType::GetChildType(type));
|
|
30491
|
+
break;
|
|
30492
|
+
case PhysicalType::VARCHAR:
|
|
30493
|
+
comp_res = CompareStringAndAdvance(left_ptr, right_ptr);
|
|
30494
|
+
break;
|
|
30495
|
+
case PhysicalType::STRUCT:
|
|
30496
|
+
comp_res = CompareStructAndAdvance(left_ptr, right_ptr, StructType::GetChildTypes(type));
|
|
30497
|
+
break;
|
|
30498
|
+
default:
|
|
30499
|
+
throw NotImplementedException("CompareListAndAdvance for variable-size type %s", type.ToString());
|
|
30500
|
+
}
|
|
30501
|
+
} else if (!left_valid && !right_valid) {
|
|
30502
|
+
comp_res = 0;
|
|
30503
|
+
} else if (left_valid) {
|
|
30504
|
+
comp_res = -1;
|
|
30505
|
+
} else {
|
|
30506
|
+
comp_res = 1;
|
|
30507
|
+
}
|
|
30508
|
+
if (comp_res != 0) {
|
|
30509
|
+
break;
|
|
30510
|
+
}
|
|
30511
|
+
}
|
|
30412
30512
|
}
|
|
30413
|
-
//
|
|
30513
|
+
// All values that we looped over were equal
|
|
30514
|
+
if (comp_res == 0 && left_len != right_len) {
|
|
30515
|
+
// Smaller lists first
|
|
30516
|
+
if (left_len < right_len) {
|
|
30517
|
+
comp_res = -1;
|
|
30518
|
+
} else {
|
|
30519
|
+
comp_res = 1;
|
|
30520
|
+
}
|
|
30521
|
+
}
|
|
30522
|
+
return comp_res;
|
|
30414
30523
|
}
|
|
30415
30524
|
|
|
30416
|
-
|
|
30417
|
-
|
|
30418
|
-
|
|
30419
|
-
|
|
30420
|
-
|
|
30421
|
-
|
|
30422
|
-
|
|
30423
|
-
|
|
30424
|
-
|
|
30425
|
-
|
|
30426
|
-
|
|
30427
|
-
|
|
30428
|
-
|
|
30429
|
-
|
|
30430
|
-
|
|
30431
|
-
|
|
30432
|
-
|
|
30433
|
-
|
|
30434
|
-
|
|
30435
|
-
|
|
30436
|
-
|
|
30437
|
-
|
|
30438
|
-
|
|
30439
|
-
|
|
30440
|
-
case 9:
|
|
30441
|
-
return MemcmpFixed<9>(str1, str2);
|
|
30442
|
-
case 10:
|
|
30443
|
-
return MemcmpFixed<10>(str1, str2);
|
|
30444
|
-
case 11:
|
|
30445
|
-
return MemcmpFixed<11>(str1, str2);
|
|
30446
|
-
case 12:
|
|
30447
|
-
return MemcmpFixed<12>(str1, str2);
|
|
30448
|
-
case 13:
|
|
30449
|
-
return MemcmpFixed<13>(str1, str2);
|
|
30450
|
-
case 14:
|
|
30451
|
-
return MemcmpFixed<14>(str1, str2);
|
|
30452
|
-
case 15:
|
|
30453
|
-
return MemcmpFixed<15>(str1, str2);
|
|
30454
|
-
case 16:
|
|
30455
|
-
return MemcmpFixed<16>(str1, str2);
|
|
30456
|
-
case 17:
|
|
30457
|
-
return MemcmpFixed<17>(str1, str2);
|
|
30458
|
-
case 18:
|
|
30459
|
-
return MemcmpFixed<18>(str1, str2);
|
|
30460
|
-
case 19:
|
|
30461
|
-
return MemcmpFixed<19>(str1, str2);
|
|
30462
|
-
case 20:
|
|
30463
|
-
return MemcmpFixed<20>(str1, str2);
|
|
30464
|
-
case 21:
|
|
30465
|
-
return MemcmpFixed<21>(str1, str2);
|
|
30466
|
-
case 22:
|
|
30467
|
-
return MemcmpFixed<22>(str1, str2);
|
|
30468
|
-
case 23:
|
|
30469
|
-
return MemcmpFixed<23>(str1, str2);
|
|
30470
|
-
case 24:
|
|
30471
|
-
return MemcmpFixed<24>(str1, str2);
|
|
30472
|
-
case 25:
|
|
30473
|
-
return MemcmpFixed<25>(str1, str2);
|
|
30474
|
-
case 26:
|
|
30475
|
-
return MemcmpFixed<26>(str1, str2);
|
|
30476
|
-
case 27:
|
|
30477
|
-
return MemcmpFixed<27>(str1, str2);
|
|
30478
|
-
case 28:
|
|
30479
|
-
return MemcmpFixed<28>(str1, str2);
|
|
30480
|
-
case 29:
|
|
30481
|
-
return MemcmpFixed<29>(str1, str2);
|
|
30482
|
-
case 30:
|
|
30483
|
-
return MemcmpFixed<30>(str1, str2);
|
|
30484
|
-
case 31:
|
|
30485
|
-
return MemcmpFixed<31>(str1, str2);
|
|
30486
|
-
case 32:
|
|
30487
|
-
return MemcmpFixed<32>(str1, str2);
|
|
30488
|
-
case 33:
|
|
30489
|
-
return MemcmpFixed<33>(str1, str2);
|
|
30490
|
-
case 34:
|
|
30491
|
-
return MemcmpFixed<34>(str1, str2);
|
|
30492
|
-
case 35:
|
|
30493
|
-
return MemcmpFixed<35>(str1, str2);
|
|
30494
|
-
case 36:
|
|
30495
|
-
return MemcmpFixed<36>(str1, str2);
|
|
30496
|
-
case 37:
|
|
30497
|
-
return MemcmpFixed<37>(str1, str2);
|
|
30498
|
-
case 38:
|
|
30499
|
-
return MemcmpFixed<38>(str1, str2);
|
|
30500
|
-
case 39:
|
|
30501
|
-
return MemcmpFixed<39>(str1, str2);
|
|
30502
|
-
case 40:
|
|
30503
|
-
return MemcmpFixed<40>(str1, str2);
|
|
30504
|
-
case 41:
|
|
30505
|
-
return MemcmpFixed<41>(str1, str2);
|
|
30506
|
-
case 42:
|
|
30507
|
-
return MemcmpFixed<42>(str1, str2);
|
|
30508
|
-
case 43:
|
|
30509
|
-
return MemcmpFixed<43>(str1, str2);
|
|
30510
|
-
case 44:
|
|
30511
|
-
return MemcmpFixed<44>(str1, str2);
|
|
30512
|
-
case 45:
|
|
30513
|
-
return MemcmpFixed<45>(str1, str2);
|
|
30514
|
-
case 46:
|
|
30515
|
-
return MemcmpFixed<46>(str1, str2);
|
|
30516
|
-
case 47:
|
|
30517
|
-
return MemcmpFixed<47>(str1, str2);
|
|
30518
|
-
case 48:
|
|
30519
|
-
return MemcmpFixed<48>(str1, str2);
|
|
30520
|
-
case 49:
|
|
30521
|
-
return MemcmpFixed<49>(str1, str2);
|
|
30522
|
-
case 50:
|
|
30523
|
-
return MemcmpFixed<50>(str1, str2);
|
|
30524
|
-
case 51:
|
|
30525
|
-
return MemcmpFixed<51>(str1, str2);
|
|
30526
|
-
case 52:
|
|
30527
|
-
return MemcmpFixed<52>(str1, str2);
|
|
30528
|
-
case 53:
|
|
30529
|
-
return MemcmpFixed<53>(str1, str2);
|
|
30530
|
-
case 54:
|
|
30531
|
-
return MemcmpFixed<54>(str1, str2);
|
|
30532
|
-
case 55:
|
|
30533
|
-
return MemcmpFixed<55>(str1, str2);
|
|
30534
|
-
case 56:
|
|
30535
|
-
return MemcmpFixed<56>(str1, str2);
|
|
30536
|
-
case 57:
|
|
30537
|
-
return MemcmpFixed<57>(str1, str2);
|
|
30538
|
-
case 58:
|
|
30539
|
-
return MemcmpFixed<58>(str1, str2);
|
|
30540
|
-
case 59:
|
|
30541
|
-
return MemcmpFixed<59>(str1, str2);
|
|
30542
|
-
case 60:
|
|
30543
|
-
return MemcmpFixed<60>(str1, str2);
|
|
30544
|
-
case 61:
|
|
30545
|
-
return MemcmpFixed<61>(str1, str2);
|
|
30546
|
-
case 62:
|
|
30547
|
-
return MemcmpFixed<62>(str1, str2);
|
|
30548
|
-
case 63:
|
|
30549
|
-
return MemcmpFixed<63>(str1, str2);
|
|
30550
|
-
case 64:
|
|
30551
|
-
return MemcmpFixed<64>(str1, str2);
|
|
30552
|
-
default:
|
|
30553
|
-
return memcmp(str1, str2, size);
|
|
30525
|
+
template <class T>
|
|
30526
|
+
int Comparators::TemplatedCompareListLoop(data_ptr_t &left_ptr, data_ptr_t &right_ptr,
|
|
30527
|
+
const ValidityBytes &left_validity, const ValidityBytes &right_validity,
|
|
30528
|
+
const idx_t &count) {
|
|
30529
|
+
int comp_res = 0;
|
|
30530
|
+
bool left_valid;
|
|
30531
|
+
bool right_valid;
|
|
30532
|
+
idx_t entry_idx;
|
|
30533
|
+
idx_t idx_in_entry;
|
|
30534
|
+
for (idx_t i = 0; i < count; i++) {
|
|
30535
|
+
ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry);
|
|
30536
|
+
left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
30537
|
+
right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry);
|
|
30538
|
+
comp_res = TemplatedCompareAndAdvance<T>(left_ptr, right_ptr);
|
|
30539
|
+
if (!left_valid && !right_valid) {
|
|
30540
|
+
comp_res = 0;
|
|
30541
|
+
} else if (!left_valid) {
|
|
30542
|
+
comp_res = 1;
|
|
30543
|
+
} else if (!right_valid) {
|
|
30544
|
+
comp_res = -1;
|
|
30545
|
+
}
|
|
30546
|
+
if (comp_res != 0) {
|
|
30547
|
+
break;
|
|
30548
|
+
}
|
|
30554
30549
|
}
|
|
30555
|
-
|
|
30550
|
+
return comp_res;
|
|
30551
|
+
}
|
|
30552
|
+
|
|
30553
|
+
void Comparators::UnswizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type) {
|
|
30554
|
+
if (type.InternalType() == PhysicalType::VARCHAR) {
|
|
30555
|
+
data_ptr += sizeof(uint32_t) + string_t::PREFIX_LENGTH;
|
|
30556
|
+
}
|
|
30557
|
+
Store<data_ptr_t>(heap_ptr + Load<idx_t>(data_ptr), data_ptr);
|
|
30558
|
+
}
|
|
30559
|
+
|
|
30560
|
+
void Comparators::SwizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type) {
|
|
30561
|
+
if (type.InternalType() == PhysicalType::VARCHAR) {
|
|
30562
|
+
data_ptr += sizeof(uint32_t) + string_t::PREFIX_LENGTH;
|
|
30563
|
+
}
|
|
30564
|
+
Store<idx_t>(Load<data_ptr_t>(data_ptr) - heap_ptr, data_ptr);
|
|
30556
30565
|
}
|
|
30557
30566
|
|
|
30558
30567
|
} // namespace duckdb
|
|
@@ -31557,6 +31566,7 @@ void LocalSortState::SortInMemory() {
|
|
|
31557
31566
|
|
|
31558
31567
|
|
|
31559
31568
|
|
|
31569
|
+
|
|
31560
31570
|
//===----------------------------------------------------------------------===//
|
|
31561
31571
|
// DuckDB
|
|
31562
31572
|
//
|
|
@@ -31932,7 +31942,7 @@ void LocalSortState::ReOrder(SortedData &sd, data_ptr_t sorting_ptr, RowDataColl
|
|
|
31932
31942
|
const idx_t sorting_entry_size = gstate.sort_layout.entry_size;
|
|
31933
31943
|
for (idx_t i = 0; i < count; i++) {
|
|
31934
31944
|
auto index = Load<uint32_t>(sorting_ptr);
|
|
31935
|
-
|
|
31945
|
+
FastMemcpy(ordered_data_ptr, unordered_data_ptr + index * row_width, row_width);
|
|
31936
31946
|
ordered_data_ptr += row_width;
|
|
31937
31947
|
sorting_ptr += sorting_entry_size;
|
|
31938
31948
|
}
|