duckdb 0.3.1-dev511.0 → 0.3.1-dev532.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 +329 -45
- package/src/duckdb.hpp +12 -7
package/package.json
CHANGED
package/src/duckdb.cpp
CHANGED
|
@@ -9435,7 +9435,11 @@ static DefaultMacro internal_macros[] = {
|
|
|
9435
9435
|
{DEFAULT_SCHEMA, "round_even", {"x", "n", nullptr}, "CASE ((abs(x) * power(10, n+1)) % 10) WHEN 5 THEN round(x/2, n) * 2 ELSE round(x, n) END"},
|
|
9436
9436
|
{DEFAULT_SCHEMA, "roundbankers", {"x", "n", nullptr}, "round_even(x, n)"},
|
|
9437
9437
|
{DEFAULT_SCHEMA, "nullif", {"a", "b", nullptr}, "CASE WHEN a=b THEN NULL ELSE a END"},
|
|
9438
|
-
|
|
9438
|
+
{DEFAULT_SCHEMA, "list_append", {"l", "e", nullptr}, "list_concat(l, list_value(e))"},
|
|
9439
|
+
{DEFAULT_SCHEMA, "array_append", {"arr", "el", nullptr}, "list_append(arr, el)"},
|
|
9440
|
+
{DEFAULT_SCHEMA, "list_prepend", {"e", "l", nullptr}, "list_concat(list_value(e), l)"},
|
|
9441
|
+
{DEFAULT_SCHEMA, "array_prepend", {"el", "arr", nullptr}, "list_prepend(el, arr)"},
|
|
9442
|
+
{nullptr, nullptr, {nullptr}, nullptr}};
|
|
9439
9443
|
|
|
9440
9444
|
static unique_ptr<CreateFunctionInfo> GetDefaultFunction(const string &schema, const string &name) {
|
|
9441
9445
|
for (idx_t index = 0; internal_macros[index].name != nullptr; index++) {
|
|
@@ -9897,10 +9901,11 @@ public:
|
|
|
9897
9901
|
|
|
9898
9902
|
class ResultArrowArrayStreamWrapper {
|
|
9899
9903
|
public:
|
|
9900
|
-
explicit ResultArrowArrayStreamWrapper(unique_ptr<QueryResult> result);
|
|
9904
|
+
explicit ResultArrowArrayStreamWrapper(unique_ptr<QueryResult> result, idx_t approx_batch_size);
|
|
9901
9905
|
ArrowArrayStream stream;
|
|
9902
9906
|
unique_ptr<QueryResult> result;
|
|
9903
9907
|
std::string last_error;
|
|
9908
|
+
idx_t vectors_per_chunk;
|
|
9904
9909
|
|
|
9905
9910
|
private:
|
|
9906
9911
|
static int MyStreamGetSchema(struct ArrowArrayStream *stream, struct ArrowSchema *out);
|
|
@@ -10017,13 +10022,21 @@ int ResultArrowArrayStreamWrapper::MyStreamGetNext(struct ArrowArrayStream *stre
|
|
|
10017
10022
|
return -1;
|
|
10018
10023
|
}
|
|
10019
10024
|
}
|
|
10020
|
-
|
|
10021
|
-
if (!
|
|
10022
|
-
|
|
10025
|
+
unique_ptr<DataChunk> chunk_result = result.Fetch();
|
|
10026
|
+
if (!chunk_result) {
|
|
10027
|
+
// Nothing to output
|
|
10023
10028
|
out->release = nullptr;
|
|
10024
10029
|
return 0;
|
|
10025
10030
|
}
|
|
10026
|
-
|
|
10031
|
+
for (idx_t i = 1; i < my_stream->vectors_per_chunk; i++) {
|
|
10032
|
+
auto new_chunk = result.Fetch();
|
|
10033
|
+
if (!new_chunk) {
|
|
10034
|
+
break;
|
|
10035
|
+
} else {
|
|
10036
|
+
chunk_result->Append(*new_chunk, true);
|
|
10037
|
+
}
|
|
10038
|
+
}
|
|
10039
|
+
chunk_result->ToArrowArray(out);
|
|
10027
10040
|
return 0;
|
|
10028
10041
|
}
|
|
10029
10042
|
|
|
@@ -10043,11 +10056,15 @@ const char *ResultArrowArrayStreamWrapper::MyStreamGetLastError(struct ArrowArra
|
|
|
10043
10056
|
auto my_stream = (ResultArrowArrayStreamWrapper *)stream->private_data;
|
|
10044
10057
|
return my_stream->last_error.c_str();
|
|
10045
10058
|
}
|
|
10046
|
-
ResultArrowArrayStreamWrapper::ResultArrowArrayStreamWrapper(unique_ptr<QueryResult> result_p)
|
|
10059
|
+
ResultArrowArrayStreamWrapper::ResultArrowArrayStreamWrapper(unique_ptr<QueryResult> result_p, idx_t approx_batch_size)
|
|
10047
10060
|
: result(move(result_p)) {
|
|
10048
10061
|
//! We first initialize the private data of the stream
|
|
10049
10062
|
stream.private_data = this;
|
|
10050
|
-
|
|
10063
|
+
//! Ceil Approx_Batch_Size/STANDARD_VECTOR_SIZE
|
|
10064
|
+
if (approx_batch_size == 0) {
|
|
10065
|
+
throw std::runtime_error("Approximate Batch Size of Record Batch MUST be higher than 0");
|
|
10066
|
+
}
|
|
10067
|
+
vectors_per_chunk = (approx_batch_size + STANDARD_VECTOR_SIZE - 1) / STANDARD_VECTOR_SIZE;
|
|
10051
10068
|
//! We initialize the stream functions
|
|
10052
10069
|
stream.get_schema = ResultArrowArrayStreamWrapper::MyStreamGetSchema;
|
|
10053
10070
|
stream.get_next = ResultArrowArrayStreamWrapper::MyStreamGetNext;
|
|
@@ -29102,6 +29119,13 @@ namespace duckdb {
|
|
|
29102
29119
|
class RowLayout;
|
|
29103
29120
|
struct LocalSortState;
|
|
29104
29121
|
|
|
29122
|
+
struct SortConstants {
|
|
29123
|
+
static constexpr idx_t VALUES_PER_RADIX = 256;
|
|
29124
|
+
static constexpr idx_t MSD_RADIX_LOCATIONS = VALUES_PER_RADIX + 1;
|
|
29125
|
+
static constexpr idx_t INSERTION_SORT_THRESHOLD = 24;
|
|
29126
|
+
static constexpr idx_t MSD_RADIX_SORT_SIZE_THRESHOLD = 4;
|
|
29127
|
+
};
|
|
29128
|
+
|
|
29105
29129
|
struct SortLayout {
|
|
29106
29130
|
public:
|
|
29107
29131
|
explicit SortLayout(const vector<BoundOrderByNode> &orders);
|
|
@@ -30403,12 +30427,12 @@ static void ComputeTies(data_ptr_t dataptr, const idx_t &count, const idx_t &col
|
|
|
30403
30427
|
}
|
|
30404
30428
|
|
|
30405
30429
|
//! Textbook LSD radix sort
|
|
30406
|
-
|
|
30407
|
-
|
|
30408
|
-
auto temp_block = buffer_manager.Allocate(MaxValue(count *
|
|
30430
|
+
void RadixSortLSD(BufferManager &buffer_manager, const data_ptr_t &dataptr, const idx_t &count, const idx_t &col_offset,
|
|
30431
|
+
const idx_t &row_width, const idx_t &sorting_size) {
|
|
30432
|
+
auto temp_block = buffer_manager.Allocate(MaxValue(count * row_width, (idx_t)Storage::BLOCK_SIZE));
|
|
30409
30433
|
bool swap = false;
|
|
30410
30434
|
|
|
30411
|
-
idx_t counts[
|
|
30435
|
+
idx_t counts[SortConstants::VALUES_PER_RADIX];
|
|
30412
30436
|
for (idx_t r = 1; r <= sorting_size; r++) {
|
|
30413
30437
|
// Init counts to 0
|
|
30414
30438
|
memset(counts, 0, sizeof(counts));
|
|
@@ -30420,24 +30444,129 @@ static void RadixSort(BufferManager &buffer_manager, const data_ptr_t &dataptr,
|
|
|
30420
30444
|
data_ptr_t offset_ptr = source_ptr + offset;
|
|
30421
30445
|
for (idx_t i = 0; i < count; i++) {
|
|
30422
30446
|
counts[*offset_ptr]++;
|
|
30423
|
-
offset_ptr +=
|
|
30447
|
+
offset_ptr += row_width;
|
|
30424
30448
|
}
|
|
30425
30449
|
// Compute offsets from counts
|
|
30426
|
-
|
|
30450
|
+
idx_t max_count = counts[0];
|
|
30451
|
+
for (idx_t val = 1; val < SortConstants::VALUES_PER_RADIX; val++) {
|
|
30452
|
+
max_count = MaxValue<idx_t>(max_count, counts[val]);
|
|
30427
30453
|
counts[val] = counts[val] + counts[val - 1];
|
|
30428
30454
|
}
|
|
30455
|
+
if (max_count == count) {
|
|
30456
|
+
continue;
|
|
30457
|
+
}
|
|
30429
30458
|
// Re-order the data in temporary array
|
|
30430
|
-
data_ptr_t row_ptr = source_ptr + (count - 1) *
|
|
30459
|
+
data_ptr_t row_ptr = source_ptr + (count - 1) * row_width;
|
|
30431
30460
|
for (idx_t i = 0; i < count; i++) {
|
|
30432
30461
|
idx_t &radix_offset = --counts[*(row_ptr + offset)];
|
|
30433
|
-
memcpy(target_ptr + radix_offset *
|
|
30434
|
-
row_ptr -=
|
|
30462
|
+
memcpy(target_ptr + radix_offset * row_width, row_ptr, row_width);
|
|
30463
|
+
row_ptr -= row_width;
|
|
30435
30464
|
}
|
|
30436
30465
|
swap = !swap;
|
|
30437
30466
|
}
|
|
30438
30467
|
// Move data back to original buffer (if it was swapped)
|
|
30439
30468
|
if (swap) {
|
|
30440
|
-
memcpy(dataptr, temp_block->Ptr(), count *
|
|
30469
|
+
memcpy(dataptr, temp_block->Ptr(), count * row_width);
|
|
30470
|
+
}
|
|
30471
|
+
}
|
|
30472
|
+
|
|
30473
|
+
//! Insertion sort, used when count of values is low
|
|
30474
|
+
inline void InsertionSort(const data_ptr_t orig_ptr, const data_ptr_t temp_ptr, const idx_t &count,
|
|
30475
|
+
const idx_t &col_offset, const idx_t &row_width, const idx_t &total_comp_width,
|
|
30476
|
+
const idx_t &offset, bool swap) {
|
|
30477
|
+
const data_ptr_t source_ptr = swap ? temp_ptr : orig_ptr;
|
|
30478
|
+
const data_ptr_t target_ptr = swap ? orig_ptr : temp_ptr;
|
|
30479
|
+
if (count > 1) {
|
|
30480
|
+
const idx_t total_offset = col_offset + offset;
|
|
30481
|
+
auto temp_val = unique_ptr<data_t[]>(new data_t[row_width]);
|
|
30482
|
+
const data_ptr_t val = temp_val.get();
|
|
30483
|
+
const auto comp_width = total_comp_width - offset;
|
|
30484
|
+
for (idx_t i = 1; i < count; i++) {
|
|
30485
|
+
memcpy(val, source_ptr + i * row_width, row_width);
|
|
30486
|
+
idx_t j = i;
|
|
30487
|
+
while (j > 0 &&
|
|
30488
|
+
memcmp(source_ptr + (j - 1) * row_width + total_offset, val + total_offset, comp_width) > 0) {
|
|
30489
|
+
memcpy(source_ptr + j * row_width, source_ptr + (j - 1) * row_width, row_width);
|
|
30490
|
+
j--;
|
|
30491
|
+
}
|
|
30492
|
+
memcpy(source_ptr + j * row_width, val, row_width);
|
|
30493
|
+
}
|
|
30494
|
+
}
|
|
30495
|
+
if (swap) {
|
|
30496
|
+
memcpy(target_ptr, source_ptr, count * row_width);
|
|
30497
|
+
}
|
|
30498
|
+
}
|
|
30499
|
+
|
|
30500
|
+
//! MSD radix sort that switches to insertion sort with low bucket sizes
|
|
30501
|
+
void RadixSortMSD(const data_ptr_t orig_ptr, const data_ptr_t temp_ptr, const idx_t &count, const idx_t &col_offset,
|
|
30502
|
+
const idx_t &row_width, const idx_t &comp_width, const idx_t &offset, idx_t locations[], bool swap) {
|
|
30503
|
+
const data_ptr_t source_ptr = swap ? temp_ptr : orig_ptr;
|
|
30504
|
+
const data_ptr_t target_ptr = swap ? orig_ptr : temp_ptr;
|
|
30505
|
+
// Init counts to 0
|
|
30506
|
+
memset(locations, 0, SortConstants::MSD_RADIX_LOCATIONS * sizeof(idx_t));
|
|
30507
|
+
idx_t *counts = locations + 1;
|
|
30508
|
+
// Collect counts
|
|
30509
|
+
const idx_t total_offset = col_offset + offset;
|
|
30510
|
+
data_ptr_t offset_ptr = source_ptr + total_offset;
|
|
30511
|
+
for (idx_t i = 0; i < count; i++) {
|
|
30512
|
+
counts[*offset_ptr]++;
|
|
30513
|
+
offset_ptr += row_width;
|
|
30514
|
+
}
|
|
30515
|
+
// Compute locations from counts
|
|
30516
|
+
idx_t max_count = 0;
|
|
30517
|
+
for (idx_t radix = 0; radix < SortConstants::VALUES_PER_RADIX; radix++) {
|
|
30518
|
+
max_count = MaxValue<idx_t>(max_count, counts[radix]);
|
|
30519
|
+
counts[radix] += locations[radix];
|
|
30520
|
+
}
|
|
30521
|
+
if (max_count != count) {
|
|
30522
|
+
// Re-order the data in temporary array
|
|
30523
|
+
data_ptr_t row_ptr = source_ptr;
|
|
30524
|
+
for (idx_t i = 0; i < count; i++) {
|
|
30525
|
+
const idx_t &radix_offset = locations[*(row_ptr + total_offset)]++;
|
|
30526
|
+
memcpy(target_ptr + radix_offset * row_width, row_ptr, row_width);
|
|
30527
|
+
row_ptr += row_width;
|
|
30528
|
+
}
|
|
30529
|
+
swap = !swap;
|
|
30530
|
+
}
|
|
30531
|
+
// Check if done
|
|
30532
|
+
if (offset == comp_width - 1) {
|
|
30533
|
+
if (swap) {
|
|
30534
|
+
memcpy(orig_ptr, temp_ptr, count * row_width);
|
|
30535
|
+
}
|
|
30536
|
+
return;
|
|
30537
|
+
}
|
|
30538
|
+
if (max_count == count) {
|
|
30539
|
+
RadixSortMSD(orig_ptr, temp_ptr, count, col_offset, row_width, comp_width, offset + 1,
|
|
30540
|
+
locations + SortConstants::MSD_RADIX_LOCATIONS, swap);
|
|
30541
|
+
return;
|
|
30542
|
+
}
|
|
30543
|
+
// Recurse
|
|
30544
|
+
idx_t radix_count = locations[0];
|
|
30545
|
+
for (idx_t radix = 0; radix < SortConstants::VALUES_PER_RADIX; radix++) {
|
|
30546
|
+
const idx_t loc = (locations[radix] - radix_count) * row_width;
|
|
30547
|
+
if (radix_count > SortConstants::INSERTION_SORT_THRESHOLD) {
|
|
30548
|
+
RadixSortMSD(orig_ptr + loc, temp_ptr + loc, radix_count, col_offset, row_width, comp_width, offset + 1,
|
|
30549
|
+
locations + SortConstants::MSD_RADIX_LOCATIONS, swap);
|
|
30550
|
+
} else if (radix_count != 0) {
|
|
30551
|
+
InsertionSort(orig_ptr + loc, temp_ptr + loc, radix_count, col_offset, row_width, comp_width, offset + 1,
|
|
30552
|
+
swap);
|
|
30553
|
+
}
|
|
30554
|
+
radix_count = locations[radix + 1] - locations[radix];
|
|
30555
|
+
}
|
|
30556
|
+
}
|
|
30557
|
+
|
|
30558
|
+
//! Calls different sort functions, depending on the count and sorting sizes
|
|
30559
|
+
void RadixSort(BufferManager &buffer_manager, const data_ptr_t &dataptr, const idx_t &count, const idx_t &col_offset,
|
|
30560
|
+
const idx_t &sorting_size, const SortLayout &sort_layout) {
|
|
30561
|
+
if (count <= SortConstants::INSERTION_SORT_THRESHOLD) {
|
|
30562
|
+
InsertionSort(dataptr, nullptr, count, 0, sort_layout.entry_size, sort_layout.comparison_size, 0, false);
|
|
30563
|
+
} else if (sorting_size <= SortConstants::MSD_RADIX_SORT_SIZE_THRESHOLD) {
|
|
30564
|
+
RadixSortLSD(buffer_manager, dataptr, count, col_offset, sort_layout.entry_size, sorting_size);
|
|
30565
|
+
} else {
|
|
30566
|
+
auto temp_block = buffer_manager.Allocate(MaxValue(count * sort_layout.entry_size, (idx_t)Storage::BLOCK_SIZE));
|
|
30567
|
+
auto preallocated_array = unique_ptr<idx_t[]>(new idx_t[sorting_size * SortConstants::MSD_RADIX_LOCATIONS]);
|
|
30568
|
+
RadixSortMSD(dataptr, temp_block->Ptr(), count, col_offset, sort_layout.entry_size, sorting_size, 0,
|
|
30569
|
+
preallocated_array.get(), false);
|
|
30441
30570
|
}
|
|
30442
30571
|
}
|
|
30443
30572
|
|
|
@@ -30478,11 +30607,10 @@ void LocalSortState::SortInMemory() {
|
|
|
30478
30607
|
idx_t sorting_size = 0;
|
|
30479
30608
|
idx_t col_offset = 0;
|
|
30480
30609
|
unique_ptr<bool[]> ties_ptr;
|
|
30481
|
-
unique_ptr<BufferHandle> ties_handle;
|
|
30482
30610
|
bool *ties = nullptr;
|
|
30483
30611
|
for (idx_t i = 0; i < sort_layout->column_count; i++) {
|
|
30484
30612
|
sorting_size += sort_layout->column_sizes[i];
|
|
30485
|
-
if (sort_layout->constant_size[i] && i < sort_layout->column_count - 1
|
|
30613
|
+
if (sort_layout->constant_size[i] && i < sort_layout->column_count - 1) {
|
|
30486
30614
|
// Add columns to the sorting size until we reach a variable size column, or the last column
|
|
30487
30615
|
continue;
|
|
30488
30616
|
}
|
|
@@ -34222,13 +34350,14 @@ public:
|
|
|
34222
34350
|
|
|
34223
34351
|
namespace duckdb {
|
|
34224
34352
|
|
|
34225
|
-
DataChunk::DataChunk() : count(0) {
|
|
34353
|
+
DataChunk::DataChunk() : count(0), capacity(STANDARD_VECTOR_SIZE) {
|
|
34226
34354
|
}
|
|
34227
34355
|
|
|
34228
34356
|
DataChunk::~DataChunk() {
|
|
34229
34357
|
}
|
|
34230
34358
|
|
|
34231
34359
|
void DataChunk::InitializeEmpty(const vector<LogicalType> &types) {
|
|
34360
|
+
capacity = STANDARD_VECTOR_SIZE;
|
|
34232
34361
|
D_ASSERT(data.empty()); // can only be initialized once
|
|
34233
34362
|
D_ASSERT(!types.empty()); // empty chunk not allowed
|
|
34234
34363
|
for (idx_t i = 0; i < types.size(); i++) {
|
|
@@ -34239,6 +34368,7 @@ void DataChunk::InitializeEmpty(const vector<LogicalType> &types) {
|
|
|
34239
34368
|
void DataChunk::Initialize(const vector<LogicalType> &types) {
|
|
34240
34369
|
D_ASSERT(data.empty()); // can only be initialized once
|
|
34241
34370
|
D_ASSERT(!types.empty()); // empty chunk not allowed
|
|
34371
|
+
capacity = STANDARD_VECTOR_SIZE;
|
|
34242
34372
|
for (idx_t i = 0; i < types.size(); i++) {
|
|
34243
34373
|
VectorCache cache(types[i]);
|
|
34244
34374
|
data.emplace_back(cache);
|
|
@@ -34256,12 +34386,14 @@ void DataChunk::Reset() {
|
|
|
34256
34386
|
for (idx_t i = 0; i < ColumnCount(); i++) {
|
|
34257
34387
|
data[i].ResetFromCache(vector_caches[i]);
|
|
34258
34388
|
}
|
|
34389
|
+
capacity = STANDARD_VECTOR_SIZE;
|
|
34259
34390
|
SetCardinality(0);
|
|
34260
34391
|
}
|
|
34261
34392
|
|
|
34262
34393
|
void DataChunk::Destroy() {
|
|
34263
34394
|
data.clear();
|
|
34264
34395
|
vector_caches.clear();
|
|
34396
|
+
capacity = 0;
|
|
34265
34397
|
SetCardinality(0);
|
|
34266
34398
|
}
|
|
34267
34399
|
|
|
@@ -34277,6 +34409,7 @@ void DataChunk::SetValue(idx_t col_idx, idx_t index, const Value &val) {
|
|
|
34277
34409
|
void DataChunk::Reference(DataChunk &chunk) {
|
|
34278
34410
|
D_ASSERT(chunk.ColumnCount() <= ColumnCount());
|
|
34279
34411
|
SetCardinality(chunk);
|
|
34412
|
+
SetCapacity(chunk);
|
|
34280
34413
|
for (idx_t i = 0; i < chunk.ColumnCount(); i++) {
|
|
34281
34414
|
data[i].Reference(chunk.data[i]);
|
|
34282
34415
|
}
|
|
@@ -34284,6 +34417,7 @@ void DataChunk::Reference(DataChunk &chunk) {
|
|
|
34284
34417
|
|
|
34285
34418
|
void DataChunk::Move(DataChunk &chunk) {
|
|
34286
34419
|
SetCardinality(chunk);
|
|
34420
|
+
SetCapacity(chunk);
|
|
34287
34421
|
data = move(chunk.data);
|
|
34288
34422
|
vector_caches = move(chunk.vector_caches);
|
|
34289
34423
|
|
|
@@ -34329,32 +34463,33 @@ void DataChunk::Split(DataChunk &other, idx_t split_idx) {
|
|
|
34329
34463
|
other.SetCardinality(*this);
|
|
34330
34464
|
}
|
|
34331
34465
|
|
|
34332
|
-
void DataChunk::Append(const DataChunk &other) {
|
|
34466
|
+
void DataChunk::Append(const DataChunk &other, bool resize, SelectionVector *sel, idx_t sel_count) {
|
|
34467
|
+
idx_t new_size = sel ? size() + sel_count : size() + other.size();
|
|
34333
34468
|
if (other.size() == 0) {
|
|
34334
34469
|
return;
|
|
34335
34470
|
}
|
|
34336
34471
|
if (ColumnCount() != other.ColumnCount()) {
|
|
34337
34472
|
throw InternalException("Column counts of appending chunk doesn't match!");
|
|
34338
34473
|
}
|
|
34339
|
-
|
|
34340
|
-
|
|
34341
|
-
|
|
34342
|
-
|
|
34343
|
-
|
|
34344
|
-
|
|
34345
|
-
|
|
34346
|
-
|
|
34347
|
-
|
|
34348
|
-
return;
|
|
34349
|
-
}
|
|
34350
|
-
if (ColumnCount() != other.ColumnCount()) {
|
|
34351
|
-
throw InternalException("Column counts of appending chunk doesn't match!");
|
|
34474
|
+
if (new_size > capacity) {
|
|
34475
|
+
if (resize) {
|
|
34476
|
+
for (idx_t i = 0; i < ColumnCount(); i++) {
|
|
34477
|
+
data[i].Resize(size(), new_size);
|
|
34478
|
+
}
|
|
34479
|
+
capacity = new_size;
|
|
34480
|
+
} else {
|
|
34481
|
+
throw InternalException("Can't append chunk to other chunk without resizing");
|
|
34482
|
+
}
|
|
34352
34483
|
}
|
|
34353
34484
|
for (idx_t i = 0; i < ColumnCount(); i++) {
|
|
34354
34485
|
D_ASSERT(data[i].GetVectorType() == VectorType::FLAT_VECTOR);
|
|
34355
|
-
|
|
34486
|
+
if (sel) {
|
|
34487
|
+
VectorOperations::Copy(other.data[i], data[i], *sel, sel_count, 0, size());
|
|
34488
|
+
} else {
|
|
34489
|
+
VectorOperations::Copy(other.data[i], data[i], other.size(), 0, size());
|
|
34490
|
+
}
|
|
34356
34491
|
}
|
|
34357
|
-
SetCardinality(
|
|
34492
|
+
SetCardinality(new_size);
|
|
34358
34493
|
}
|
|
34359
34494
|
|
|
34360
34495
|
void DataChunk::Normalify() {
|
|
@@ -34451,7 +34586,7 @@ void DataChunk::Hash(Vector &result) {
|
|
|
34451
34586
|
|
|
34452
34587
|
void DataChunk::Verify() {
|
|
34453
34588
|
#ifdef DEBUG
|
|
34454
|
-
D_ASSERT(size() <=
|
|
34589
|
+
D_ASSERT(size() <= capacity);
|
|
34455
34590
|
// verify that all vectors in this chunk have the chunk selection vector
|
|
34456
34591
|
for (idx_t i = 0; i < ColumnCount(); i++) {
|
|
34457
34592
|
data[i].Verify(size());
|
|
@@ -54676,8 +54811,8 @@ static void SortCollectionForPartition(WindowOperatorState &state, BoundWindowEx
|
|
|
54676
54811
|
|
|
54677
54812
|
// Copy the data for each collection.
|
|
54678
54813
|
if (bin_size) {
|
|
54679
|
-
over_partition.Append(over_chunk, sel, bin_size);
|
|
54680
|
-
payload_partition.Append(payload_chunk, sel, bin_size);
|
|
54814
|
+
over_partition.Append(over_chunk, false, &sel, bin_size);
|
|
54815
|
+
payload_partition.Append(payload_chunk, false, &sel, bin_size);
|
|
54681
54816
|
}
|
|
54682
54817
|
} else {
|
|
54683
54818
|
local_sort_state.SinkChunk(over_chunk, payload_chunk);
|
|
@@ -76623,9 +76758,16 @@ struct MapFun {
|
|
|
76623
76758
|
struct MapExtractFun {
|
|
76624
76759
|
static void RegisterFunction(BuiltinFunctions &set);
|
|
76625
76760
|
};
|
|
76761
|
+
|
|
76626
76762
|
struct ListExtractFun {
|
|
76627
76763
|
static void RegisterFunction(BuiltinFunctions &set);
|
|
76628
76764
|
};
|
|
76765
|
+
|
|
76766
|
+
struct ListConcatFun {
|
|
76767
|
+
static ScalarFunction GetFunction();
|
|
76768
|
+
static void RegisterFunction(BuiltinFunctions &set);
|
|
76769
|
+
};
|
|
76770
|
+
|
|
76629
76771
|
struct CardinalityFun {
|
|
76630
76772
|
static void RegisterFunction(BuiltinFunctions &set);
|
|
76631
76773
|
};
|
|
@@ -83601,11 +83743,6 @@ void ArraySliceFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
83601
83743
|
|
|
83602
83744
|
|
|
83603
83745
|
|
|
83604
|
-
|
|
83605
|
-
|
|
83606
|
-
|
|
83607
|
-
|
|
83608
|
-
|
|
83609
83746
|
//===----------------------------------------------------------------------===//
|
|
83610
83747
|
// DuckDB
|
|
83611
83748
|
//
|
|
@@ -83645,6 +83782,147 @@ public:
|
|
|
83645
83782
|
|
|
83646
83783
|
|
|
83647
83784
|
|
|
83785
|
+
namespace duckdb {
|
|
83786
|
+
|
|
83787
|
+
static void ListConcatFunction(DataChunk &args, ExpressionState &state, Vector &result) {
|
|
83788
|
+
D_ASSERT(args.ColumnCount() == 2);
|
|
83789
|
+
auto count = args.size();
|
|
83790
|
+
|
|
83791
|
+
Vector &lhs = args.data[0];
|
|
83792
|
+
Vector &rhs = args.data[1];
|
|
83793
|
+
if (lhs.GetType().id() == LogicalTypeId::SQLNULL) {
|
|
83794
|
+
result.Reference(rhs);
|
|
83795
|
+
return;
|
|
83796
|
+
}
|
|
83797
|
+
if (rhs.GetType().id() == LogicalTypeId::SQLNULL) {
|
|
83798
|
+
result.Reference(lhs);
|
|
83799
|
+
return;
|
|
83800
|
+
}
|
|
83801
|
+
|
|
83802
|
+
VectorData lhs_data;
|
|
83803
|
+
VectorData rhs_data;
|
|
83804
|
+
lhs.Orrify(count, lhs_data);
|
|
83805
|
+
rhs.Orrify(count, rhs_data);
|
|
83806
|
+
auto lhs_entries = (list_entry_t *)lhs_data.data;
|
|
83807
|
+
auto rhs_entries = (list_entry_t *)rhs_data.data;
|
|
83808
|
+
|
|
83809
|
+
auto lhs_list_size = ListVector::GetListSize(lhs);
|
|
83810
|
+
auto rhs_list_size = ListVector::GetListSize(rhs);
|
|
83811
|
+
auto &lhs_child = ListVector::GetEntry(lhs);
|
|
83812
|
+
auto &rhs_child = ListVector::GetEntry(rhs);
|
|
83813
|
+
VectorData lhs_child_data;
|
|
83814
|
+
VectorData rhs_child_data;
|
|
83815
|
+
lhs_child.Orrify(lhs_list_size, lhs_child_data);
|
|
83816
|
+
rhs_child.Orrify(rhs_list_size, rhs_child_data);
|
|
83817
|
+
|
|
83818
|
+
result.SetVectorType(VectorType::FLAT_VECTOR);
|
|
83819
|
+
auto result_entries = FlatVector::GetData<list_entry_t>(result);
|
|
83820
|
+
auto &result_validity = FlatVector::Validity(result);
|
|
83821
|
+
|
|
83822
|
+
idx_t offset = 0;
|
|
83823
|
+
for (idx_t i = 0; i < count; i++) {
|
|
83824
|
+
auto lhs_list_index = lhs_data.sel->get_index(i);
|
|
83825
|
+
auto rhs_list_index = rhs_data.sel->get_index(i);
|
|
83826
|
+
if (!lhs_data.validity.RowIsValid(lhs_list_index) && !rhs_data.validity.RowIsValid(rhs_list_index)) {
|
|
83827
|
+
result_validity.SetInvalid(i);
|
|
83828
|
+
continue;
|
|
83829
|
+
}
|
|
83830
|
+
result_entries[i].offset = offset;
|
|
83831
|
+
result_entries[i].length = 0;
|
|
83832
|
+
if (lhs_data.validity.RowIsValid(lhs_list_index)) {
|
|
83833
|
+
const auto &lhs_entry = lhs_entries[lhs_list_index];
|
|
83834
|
+
result_entries[i].length += lhs_entry.length;
|
|
83835
|
+
ListVector::Append(result, lhs_child, *lhs_child_data.sel, lhs_entry.offset + lhs_entry.length,
|
|
83836
|
+
lhs_entry.offset);
|
|
83837
|
+
}
|
|
83838
|
+
if (rhs_data.validity.RowIsValid(rhs_list_index)) {
|
|
83839
|
+
const auto &rhs_entry = rhs_entries[rhs_list_index];
|
|
83840
|
+
result_entries[i].length += rhs_entry.length;
|
|
83841
|
+
ListVector::Append(result, rhs_child, *rhs_child_data.sel, rhs_entry.offset + rhs_entry.length,
|
|
83842
|
+
rhs_entry.offset);
|
|
83843
|
+
}
|
|
83844
|
+
offset += result_entries[i].length;
|
|
83845
|
+
}
|
|
83846
|
+
D_ASSERT(ListVector::GetListSize(result) == offset);
|
|
83847
|
+
|
|
83848
|
+
if (lhs.GetVectorType() == VectorType::CONSTANT_VECTOR && rhs.GetVectorType() == VectorType::CONSTANT_VECTOR) {
|
|
83849
|
+
result.SetVectorType(VectorType::CONSTANT_VECTOR);
|
|
83850
|
+
}
|
|
83851
|
+
}
|
|
83852
|
+
|
|
83853
|
+
static unique_ptr<FunctionData> ListConcatBind(ClientContext &context, ScalarFunction &bound_function,
|
|
83854
|
+
vector<unique_ptr<Expression>> &arguments) {
|
|
83855
|
+
D_ASSERT(bound_function.arguments.size() == 2);
|
|
83856
|
+
|
|
83857
|
+
auto &lhs = arguments[0]->return_type;
|
|
83858
|
+
auto &rhs = arguments[1]->return_type;
|
|
83859
|
+
if (lhs.id() == LogicalTypeId::SQLNULL && rhs.id() == LogicalTypeId::SQLNULL) {
|
|
83860
|
+
bound_function.return_type = LogicalType::SQLNULL;
|
|
83861
|
+
} else if (lhs.id() == LogicalTypeId::SQLNULL || rhs.id() == LogicalTypeId::SQLNULL) {
|
|
83862
|
+
// we mimic postgres behaviour: list_concat(NULL, my_list) = my_list
|
|
83863
|
+
bound_function.arguments[0] = lhs;
|
|
83864
|
+
bound_function.arguments[1] = rhs;
|
|
83865
|
+
bound_function.return_type = rhs.id() == LogicalTypeId::SQLNULL ? lhs : rhs;
|
|
83866
|
+
} else {
|
|
83867
|
+
D_ASSERT(lhs.id() == LogicalTypeId::LIST);
|
|
83868
|
+
D_ASSERT(rhs.id() == LogicalTypeId::LIST);
|
|
83869
|
+
|
|
83870
|
+
// Resolve list type
|
|
83871
|
+
auto child_type = LogicalType::SQLNULL;
|
|
83872
|
+
for (const auto &argument : arguments) {
|
|
83873
|
+
child_type = LogicalType::MaxLogicalType(child_type, ListType::GetChildType(argument->return_type));
|
|
83874
|
+
}
|
|
83875
|
+
ExpressionBinder::ResolveParameterType(child_type);
|
|
83876
|
+
auto list_type = LogicalType::LIST(move(child_type));
|
|
83877
|
+
|
|
83878
|
+
bound_function.arguments[0] = list_type;
|
|
83879
|
+
bound_function.arguments[1] = list_type;
|
|
83880
|
+
bound_function.return_type = list_type;
|
|
83881
|
+
}
|
|
83882
|
+
return make_unique<VariableReturnBindData>(bound_function.return_type);
|
|
83883
|
+
}
|
|
83884
|
+
|
|
83885
|
+
static unique_ptr<BaseStatistics> ListConcatStats(ClientContext &context, BoundFunctionExpression &expr,
|
|
83886
|
+
FunctionData *bind_data,
|
|
83887
|
+
vector<unique_ptr<BaseStatistics>> &child_stats) {
|
|
83888
|
+
D_ASSERT(child_stats.size() == 2);
|
|
83889
|
+
if (!child_stats[0] || !child_stats[1]) {
|
|
83890
|
+
return nullptr;
|
|
83891
|
+
}
|
|
83892
|
+
|
|
83893
|
+
auto &left_stats = (ListStatistics &)*child_stats[0];
|
|
83894
|
+
auto &right_stats = (ListStatistics &)*child_stats[1];
|
|
83895
|
+
|
|
83896
|
+
auto stats = left_stats.Copy();
|
|
83897
|
+
stats->Merge(right_stats);
|
|
83898
|
+
|
|
83899
|
+
return stats;
|
|
83900
|
+
}
|
|
83901
|
+
|
|
83902
|
+
ScalarFunction ListConcatFun::GetFunction() {
|
|
83903
|
+
// the arguments and return types are actually set in the binder function
|
|
83904
|
+
return ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::LIST(LogicalType::ANY)},
|
|
83905
|
+
LogicalType::LIST(LogicalType::ANY), ListConcatFunction, false, ListConcatBind, nullptr,
|
|
83906
|
+
ListConcatStats);
|
|
83907
|
+
}
|
|
83908
|
+
|
|
83909
|
+
void ListConcatFun::RegisterFunction(BuiltinFunctions &set) {
|
|
83910
|
+
set.AddFunction({"list_concat", "list_cat", "array_concat", "array_cat"}, GetFunction());
|
|
83911
|
+
}
|
|
83912
|
+
|
|
83913
|
+
} // namespace duckdb
|
|
83914
|
+
|
|
83915
|
+
|
|
83916
|
+
|
|
83917
|
+
|
|
83918
|
+
|
|
83919
|
+
|
|
83920
|
+
|
|
83921
|
+
|
|
83922
|
+
|
|
83923
|
+
|
|
83924
|
+
|
|
83925
|
+
|
|
83648
83926
|
namespace duckdb {
|
|
83649
83927
|
|
|
83650
83928
|
template <class T, bool HEAP_REF = false, bool VALIDITY_ONLY = false>
|
|
@@ -85613,6 +85891,7 @@ void BuiltinFunctions::RegisterNestedFunctions() {
|
|
|
85613
85891
|
Register<ArraySliceFun>();
|
|
85614
85892
|
Register<StructPackFun>();
|
|
85615
85893
|
Register<StructExtractFun>();
|
|
85894
|
+
Register<ListConcatFun>();
|
|
85616
85895
|
Register<ListValueFun>();
|
|
85617
85896
|
Register<ListExtractFun>();
|
|
85618
85897
|
Register<ListRangeFun>();
|
|
@@ -85959,6 +86238,7 @@ struct BitwiseNotFun {
|
|
|
85959
86238
|
|
|
85960
86239
|
|
|
85961
86240
|
|
|
86241
|
+
|
|
85962
86242
|
#include <limits>
|
|
85963
86243
|
|
|
85964
86244
|
namespace duckdb {
|
|
@@ -86274,6 +86554,8 @@ void AddFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
86274
86554
|
|
|
86275
86555
|
functions.AddFunction(GetFunction(LogicalType::TIMESTAMP, LogicalType::INTERVAL));
|
|
86276
86556
|
functions.AddFunction(GetFunction(LogicalType::INTERVAL, LogicalType::TIMESTAMP));
|
|
86557
|
+
// we can add lists together
|
|
86558
|
+
functions.AddFunction(ListConcatFun::GetFunction());
|
|
86277
86559
|
|
|
86278
86560
|
set.AddFunction(functions);
|
|
86279
86561
|
}
|
|
@@ -87856,6 +88138,7 @@ void CHR::RegisterFunction(BuiltinFunctions &set) {
|
|
|
87856
88138
|
|
|
87857
88139
|
|
|
87858
88140
|
|
|
88141
|
+
|
|
87859
88142
|
#include <string.h>
|
|
87860
88143
|
|
|
87861
88144
|
namespace duckdb {
|
|
@@ -88101,6 +88384,7 @@ void ConcatFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
88101
88384
|
concat_op.AddFunction(
|
|
88102
88385
|
ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::VARCHAR, ConcatOperator));
|
|
88103
88386
|
concat_op.AddFunction(ScalarFunction({LogicalType::BLOB, LogicalType::BLOB}, LogicalType::BLOB, ConcatOperator));
|
|
88387
|
+
concat_op.AddFunction(ListConcatFun::GetFunction());
|
|
88104
88388
|
set.AddFunction(concat_op);
|
|
88105
88389
|
|
|
88106
88390
|
ScalarFunction concat_ws = ScalarFunction("concat_ws", {LogicalType::VARCHAR, LogicalType::VARCHAR},
|
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.1-
|
|
13
|
+
#define DUCKDB_SOURCE_ID "b36732a57"
|
|
14
|
+
#define DUCKDB_VERSION "0.3.1-dev532"
|
|
15
15
|
//===----------------------------------------------------------------------===//
|
|
16
16
|
// DuckDB
|
|
17
17
|
//
|
|
@@ -3660,12 +3660,15 @@ public:
|
|
|
3660
3660
|
return data.size();
|
|
3661
3661
|
}
|
|
3662
3662
|
void SetCardinality(idx_t count_p) {
|
|
3663
|
-
D_ASSERT(
|
|
3663
|
+
D_ASSERT(count_p <= capacity);
|
|
3664
3664
|
this->count = count_p;
|
|
3665
3665
|
}
|
|
3666
3666
|
void SetCardinality(const DataChunk &other) {
|
|
3667
3667
|
this->count = other.size();
|
|
3668
3668
|
}
|
|
3669
|
+
void SetCapacity(const DataChunk &other) {
|
|
3670
|
+
this->capacity = other.capacity;
|
|
3671
|
+
}
|
|
3669
3672
|
|
|
3670
3673
|
DUCKDB_API Value GetValue(idx_t col_idx, idx_t index) const;
|
|
3671
3674
|
DUCKDB_API void SetValue(idx_t col_idx, idx_t index, const Value &val);
|
|
@@ -3684,10 +3687,10 @@ public:
|
|
|
3684
3687
|
void InitializeEmpty(const vector<LogicalType> &types);
|
|
3685
3688
|
//! Append the other DataChunk to this one. The column count and types of
|
|
3686
3689
|
//! the two DataChunks have to match exactly. Throws an exception if there
|
|
3687
|
-
//! is not enough space in the chunk.
|
|
3688
|
-
DUCKDB_API void Append(const DataChunk &other
|
|
3689
|
-
|
|
3690
|
-
|
|
3690
|
+
//! is not enough space in the chunk and resize is not allowed.
|
|
3691
|
+
DUCKDB_API void Append(const DataChunk &other, bool resize = false, SelectionVector *sel = nullptr,
|
|
3692
|
+
idx_t count = 0);
|
|
3693
|
+
|
|
3691
3694
|
//! Destroy all data and columns owned by this DataChunk
|
|
3692
3695
|
DUCKDB_API void Destroy();
|
|
3693
3696
|
|
|
@@ -3739,6 +3742,8 @@ public:
|
|
|
3739
3742
|
private:
|
|
3740
3743
|
//! The amount of tuples stored in the data chunk
|
|
3741
3744
|
idx_t count;
|
|
3745
|
+
//! The amount of tuples that can be stored in the data chunk
|
|
3746
|
+
idx_t capacity;
|
|
3742
3747
|
//! Vector caches, used to store data when ::Initialize is called
|
|
3743
3748
|
vector<VectorCache> vector_caches;
|
|
3744
3749
|
};
|