duckdb 0.3.1-dev501.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 +588 -156
- package/src/duckdb.hpp +16 -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());
|
|
@@ -35946,20 +36081,30 @@ bool Hugeint::TryCast(hugeint_t input, float &result) {
|
|
|
35946
36081
|
return true;
|
|
35947
36082
|
}
|
|
35948
36083
|
|
|
35949
|
-
template
|
|
35950
|
-
bool
|
|
36084
|
+
template <class REAL_T>
|
|
36085
|
+
bool CastBigintToFloating(hugeint_t input, REAL_T &result) {
|
|
35951
36086
|
switch (input.upper) {
|
|
35952
36087
|
case -1:
|
|
35953
36088
|
// special case for upper = -1 to avoid rounding issues in small negative numbers
|
|
35954
|
-
result = -
|
|
36089
|
+
result = -REAL_T(NumericLimits<uint64_t>::Maximum() - input.lower) - 1;
|
|
35955
36090
|
break;
|
|
35956
36091
|
default:
|
|
35957
|
-
result =
|
|
36092
|
+
result = REAL_T(input.lower) + REAL_T(input.upper) * REAL_T(NumericLimits<uint64_t>::Maximum());
|
|
35958
36093
|
break;
|
|
35959
36094
|
}
|
|
35960
36095
|
return true;
|
|
35961
36096
|
}
|
|
35962
36097
|
|
|
36098
|
+
template <>
|
|
36099
|
+
bool Hugeint::TryCast(hugeint_t input, double &result) {
|
|
36100
|
+
return CastBigintToFloating<double>(input, result);
|
|
36101
|
+
}
|
|
36102
|
+
|
|
36103
|
+
template <>
|
|
36104
|
+
bool Hugeint::TryCast(hugeint_t input, long double &result) {
|
|
36105
|
+
return CastBigintToFloating<long double>(input, result);
|
|
36106
|
+
}
|
|
36107
|
+
|
|
35963
36108
|
template <class DST>
|
|
35964
36109
|
hugeint_t HugeintConvertInteger(DST input) {
|
|
35965
36110
|
hugeint_t result;
|
|
@@ -36017,8 +36162,8 @@ bool Hugeint::TryConvert(float value, hugeint_t &result) {
|
|
|
36017
36162
|
return Hugeint::TryConvert(double(value), result);
|
|
36018
36163
|
}
|
|
36019
36164
|
|
|
36020
|
-
template
|
|
36021
|
-
bool
|
|
36165
|
+
template <class REAL_T>
|
|
36166
|
+
bool ConvertFloatingToBigint(REAL_T value, hugeint_t &result) {
|
|
36022
36167
|
if (value <= -170141183460469231731687303715884105728.0 || value >= 170141183460469231731687303715884105727.0) {
|
|
36023
36168
|
return false;
|
|
36024
36169
|
}
|
|
@@ -36026,14 +36171,24 @@ bool Hugeint::TryConvert(double value, hugeint_t &result) {
|
|
|
36026
36171
|
if (negative) {
|
|
36027
36172
|
value = -value;
|
|
36028
36173
|
}
|
|
36029
|
-
result.lower = (uint64_t)fmod(value,
|
|
36030
|
-
result.upper = (uint64_t)(value /
|
|
36174
|
+
result.lower = (uint64_t)fmod(value, REAL_T(NumericLimits<uint64_t>::Maximum()));
|
|
36175
|
+
result.upper = (uint64_t)(value / REAL_T(NumericLimits<uint64_t>::Maximum()));
|
|
36031
36176
|
if (negative) {
|
|
36032
|
-
NegateInPlace(result);
|
|
36177
|
+
Hugeint::NegateInPlace(result);
|
|
36033
36178
|
}
|
|
36034
36179
|
return true;
|
|
36035
36180
|
}
|
|
36036
36181
|
|
|
36182
|
+
template <>
|
|
36183
|
+
bool Hugeint::TryConvert(double value, hugeint_t &result) {
|
|
36184
|
+
return ConvertFloatingToBigint<double>(value, result);
|
|
36185
|
+
}
|
|
36186
|
+
|
|
36187
|
+
template <>
|
|
36188
|
+
bool Hugeint::TryConvert(long double value, hugeint_t &result) {
|
|
36189
|
+
return ConvertFloatingToBigint<long double>(value, result);
|
|
36190
|
+
}
|
|
36191
|
+
|
|
36037
36192
|
//===--------------------------------------------------------------------===//
|
|
36038
36193
|
// hugeint_t operators
|
|
36039
36194
|
//===--------------------------------------------------------------------===//
|
|
@@ -54656,8 +54811,8 @@ static void SortCollectionForPartition(WindowOperatorState &state, BoundWindowEx
|
|
|
54656
54811
|
|
|
54657
54812
|
// Copy the data for each collection.
|
|
54658
54813
|
if (bin_size) {
|
|
54659
|
-
over_partition.Append(over_chunk, sel, bin_size);
|
|
54660
|
-
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);
|
|
54661
54816
|
}
|
|
54662
54817
|
} else {
|
|
54663
54818
|
local_sort_state.SinkChunk(over_chunk, payload_chunk);
|
|
@@ -70552,6 +70707,45 @@ struct VarianceFun {
|
|
|
70552
70707
|
|
|
70553
70708
|
namespace duckdb {
|
|
70554
70709
|
|
|
70710
|
+
static inline void KahanAddInternal(double input, double &summed, double &err) {
|
|
70711
|
+
double diff = input - err;
|
|
70712
|
+
double newval = summed + diff;
|
|
70713
|
+
err = (newval - summed) - diff;
|
|
70714
|
+
summed = newval;
|
|
70715
|
+
}
|
|
70716
|
+
|
|
70717
|
+
template <class T>
|
|
70718
|
+
struct SumState {
|
|
70719
|
+
bool isset;
|
|
70720
|
+
T value;
|
|
70721
|
+
|
|
70722
|
+
void Initialize() {
|
|
70723
|
+
this->isset = false;
|
|
70724
|
+
}
|
|
70725
|
+
|
|
70726
|
+
void Combine(const SumState<T> &other) {
|
|
70727
|
+
this->isset = other.isset || this->isset;
|
|
70728
|
+
this->value += other.value;
|
|
70729
|
+
}
|
|
70730
|
+
};
|
|
70731
|
+
|
|
70732
|
+
struct KahanSumState {
|
|
70733
|
+
bool isset;
|
|
70734
|
+
double value;
|
|
70735
|
+
double err;
|
|
70736
|
+
|
|
70737
|
+
void Initialize() {
|
|
70738
|
+
this->isset = false;
|
|
70739
|
+
this->err = 0.0;
|
|
70740
|
+
}
|
|
70741
|
+
|
|
70742
|
+
void Combine(const KahanSumState &other) {
|
|
70743
|
+
this->isset = other.isset || this->isset;
|
|
70744
|
+
KahanAddInternal(other.value, this->value, this->err);
|
|
70745
|
+
KahanAddInternal(other.err, this->value, this->err);
|
|
70746
|
+
}
|
|
70747
|
+
};
|
|
70748
|
+
|
|
70555
70749
|
struct RegularAdd {
|
|
70556
70750
|
template <class STATE, class T>
|
|
70557
70751
|
static void AddNumber(STATE &state, T input) {
|
|
@@ -70564,6 +70758,18 @@ struct RegularAdd {
|
|
|
70564
70758
|
}
|
|
70565
70759
|
};
|
|
70566
70760
|
|
|
70761
|
+
struct KahanAdd {
|
|
70762
|
+
template <class STATE, class T>
|
|
70763
|
+
static void AddNumber(STATE &state, T input) {
|
|
70764
|
+
KahanAddInternal(input, state.value, state.err);
|
|
70765
|
+
}
|
|
70766
|
+
|
|
70767
|
+
template <class STATE, class T>
|
|
70768
|
+
static void AddConstant(STATE &state, T input, idx_t count) {
|
|
70769
|
+
KahanAddInternal(input * count, state.value, state.err);
|
|
70770
|
+
}
|
|
70771
|
+
};
|
|
70772
|
+
|
|
70567
70773
|
struct HugeintAdd {
|
|
70568
70774
|
static void AddValue(hugeint_t &result, uint64_t value, int positive) {
|
|
70569
70775
|
// integer summation taken from Tim Gubner et al. - Efficient Query Processing
|
|
@@ -70659,8 +70865,34 @@ namespace duckdb {
|
|
|
70659
70865
|
|
|
70660
70866
|
template <class T>
|
|
70661
70867
|
struct AvgState {
|
|
70868
|
+
uint64_t count;
|
|
70662
70869
|
T value;
|
|
70870
|
+
|
|
70871
|
+
void Initialize() {
|
|
70872
|
+
this->count = 0;
|
|
70873
|
+
}
|
|
70874
|
+
|
|
70875
|
+
void Combine(const AvgState<T> &other) {
|
|
70876
|
+
this->count += other.count;
|
|
70877
|
+
this->value += other.value;
|
|
70878
|
+
}
|
|
70879
|
+
};
|
|
70880
|
+
|
|
70881
|
+
struct KahanAvgState {
|
|
70663
70882
|
uint64_t count;
|
|
70883
|
+
double value;
|
|
70884
|
+
double err;
|
|
70885
|
+
|
|
70886
|
+
void Initialize() {
|
|
70887
|
+
this->count = 0;
|
|
70888
|
+
this->err = 0.0;
|
|
70889
|
+
}
|
|
70890
|
+
|
|
70891
|
+
void Combine(const KahanAvgState &other) {
|
|
70892
|
+
this->count += other.count;
|
|
70893
|
+
KahanAddInternal(other.value, this->value, this->err);
|
|
70894
|
+
KahanAddInternal(other.err, this->value, this->err);
|
|
70895
|
+
}
|
|
70664
70896
|
};
|
|
70665
70897
|
|
|
70666
70898
|
struct AverageDecimalBindData : public FunctionData {
|
|
@@ -70678,12 +70910,11 @@ public:
|
|
|
70678
70910
|
struct AverageSetOperation {
|
|
70679
70911
|
template <class STATE>
|
|
70680
70912
|
static void Initialize(STATE *state) {
|
|
70681
|
-
state->
|
|
70913
|
+
state->Initialize();
|
|
70682
70914
|
}
|
|
70683
70915
|
template <class STATE>
|
|
70684
70916
|
static void Combine(const STATE &source, STATE *target) {
|
|
70685
|
-
target->
|
|
70686
|
-
target->value += source.value;
|
|
70917
|
+
target->Combine(source);
|
|
70687
70918
|
}
|
|
70688
70919
|
template <class STATE>
|
|
70689
70920
|
static void AddValues(STATE *state, idx_t count) {
|
|
@@ -70691,8 +70922,9 @@ struct AverageSetOperation {
|
|
|
70691
70922
|
}
|
|
70692
70923
|
};
|
|
70693
70924
|
|
|
70694
|
-
|
|
70695
|
-
|
|
70925
|
+
template <class T>
|
|
70926
|
+
static T GetAverageDivident(uint64_t count, FunctionData *bind_data) {
|
|
70927
|
+
T divident = T(count);
|
|
70696
70928
|
if (bind_data) {
|
|
70697
70929
|
auto &avg_bind_data = (AverageDecimalBindData &)*bind_data;
|
|
70698
70930
|
divident *= avg_bind_data.scale;
|
|
@@ -70707,7 +70939,7 @@ struct IntegerAverageOperation : public BaseSumOperation<AverageSetOperation, Re
|
|
|
70707
70939
|
if (state->count == 0) {
|
|
70708
70940
|
mask.SetInvalid(idx);
|
|
70709
70941
|
} else {
|
|
70710
|
-
double divident = GetAverageDivident(state->count, bind_data);
|
|
70942
|
+
double divident = GetAverageDivident<double>(state->count, bind_data);
|
|
70711
70943
|
target[idx] = double(state->value) / divident;
|
|
70712
70944
|
}
|
|
70713
70945
|
}
|
|
@@ -70720,8 +70952,8 @@ struct IntegerAverageOperationHugeint : public BaseSumOperation<AverageSetOperat
|
|
|
70720
70952
|
if (state->count == 0) {
|
|
70721
70953
|
mask.SetInvalid(idx);
|
|
70722
70954
|
} else {
|
|
70723
|
-
double divident = GetAverageDivident(state->count, bind_data);
|
|
70724
|
-
target[idx] = Hugeint::Cast<double>(state->value) / divident;
|
|
70955
|
+
long double divident = GetAverageDivident<long double>(state->count, bind_data);
|
|
70956
|
+
target[idx] = Hugeint::Cast<long double>(state->value) / divident;
|
|
70725
70957
|
}
|
|
70726
70958
|
}
|
|
70727
70959
|
};
|
|
@@ -70733,8 +70965,8 @@ struct HugeintAverageOperation : public BaseSumOperation<AverageSetOperation, Re
|
|
|
70733
70965
|
if (state->count == 0) {
|
|
70734
70966
|
mask.SetInvalid(idx);
|
|
70735
70967
|
} else {
|
|
70736
|
-
double divident = GetAverageDivident(state->count, bind_data);
|
|
70737
|
-
target[idx] = Hugeint::Cast<double>(state->value) / divident;
|
|
70968
|
+
long double divident = GetAverageDivident<long double>(state->count, bind_data);
|
|
70969
|
+
target[idx] = Hugeint::Cast<long double>(state->value) / divident;
|
|
70738
70970
|
}
|
|
70739
70971
|
}
|
|
70740
70972
|
};
|
|
@@ -70748,7 +70980,21 @@ struct NumericAverageOperation : public BaseSumOperation<AverageSetOperation, Re
|
|
|
70748
70980
|
if (!Value::DoubleIsValid(state->value)) {
|
|
70749
70981
|
throw OutOfRangeException("AVG is out of range!");
|
|
70750
70982
|
}
|
|
70751
|
-
target[idx] = state->value / state->count;
|
|
70983
|
+
target[idx] = (state->value / state->count);
|
|
70984
|
+
}
|
|
70985
|
+
}
|
|
70986
|
+
};
|
|
70987
|
+
|
|
70988
|
+
struct KahanAverageOperation : public BaseSumOperation<AverageSetOperation, KahanAdd> {
|
|
70989
|
+
template <class T, class STATE>
|
|
70990
|
+
static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) {
|
|
70991
|
+
if (state->count == 0) {
|
|
70992
|
+
mask.SetInvalid(idx);
|
|
70993
|
+
} else {
|
|
70994
|
+
if (!Value::DoubleIsValid(state->value)) {
|
|
70995
|
+
throw OutOfRangeException("AVG is out of range!");
|
|
70996
|
+
}
|
|
70997
|
+
target[idx] = (state->value / state->count) + (state->err / state->count);
|
|
70752
70998
|
}
|
|
70753
70999
|
}
|
|
70754
71000
|
};
|
|
@@ -70800,6 +71046,11 @@ void AvgFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
70800
71046
|
avg.AddFunction(AggregateFunction::UnaryAggregate<AvgState<double>, double, double, NumericAverageOperation>(
|
|
70801
71047
|
LogicalType::DOUBLE, LogicalType::DOUBLE));
|
|
70802
71048
|
set.AddFunction(avg);
|
|
71049
|
+
|
|
71050
|
+
AggregateFunctionSet favg("favg");
|
|
71051
|
+
favg.AddFunction(AggregateFunction::UnaryAggregate<KahanAvgState, double, double, KahanAverageOperation>(
|
|
71052
|
+
LogicalType::DOUBLE, LogicalType::DOUBLE));
|
|
71053
|
+
set.AddFunction(favg);
|
|
70803
71054
|
}
|
|
70804
71055
|
|
|
70805
71056
|
} // namespace duckdb
|
|
@@ -73480,21 +73731,14 @@ void StringAggFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
73480
73731
|
|
|
73481
73732
|
namespace duckdb {
|
|
73482
73733
|
|
|
73483
|
-
template <class T>
|
|
73484
|
-
struct SumState {
|
|
73485
|
-
T value;
|
|
73486
|
-
bool isset;
|
|
73487
|
-
};
|
|
73488
|
-
|
|
73489
73734
|
struct SumSetOperation {
|
|
73490
73735
|
template <class STATE>
|
|
73491
73736
|
static void Initialize(STATE *state) {
|
|
73492
|
-
state->
|
|
73737
|
+
state->Initialize();
|
|
73493
73738
|
}
|
|
73494
73739
|
template <class STATE>
|
|
73495
73740
|
static void Combine(const STATE &source, STATE *target) {
|
|
73496
|
-
target->
|
|
73497
|
-
target->value += source.value;
|
|
73741
|
+
target->Combine(source);
|
|
73498
73742
|
}
|
|
73499
73743
|
template <class STATE>
|
|
73500
73744
|
static void AddValues(STATE *state, idx_t count) {
|
|
@@ -73524,7 +73768,8 @@ struct SumToHugeintOperation : public BaseSumOperation<SumSetOperation, HugeintA
|
|
|
73524
73768
|
}
|
|
73525
73769
|
};
|
|
73526
73770
|
|
|
73527
|
-
|
|
73771
|
+
template <class ADD_OPERATOR>
|
|
73772
|
+
struct DoubleSumOperation : public BaseSumOperation<SumSetOperation, ADD_OPERATOR> {
|
|
73528
73773
|
template <class T, class STATE>
|
|
73529
73774
|
static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) {
|
|
73530
73775
|
if (!state->isset) {
|
|
@@ -73538,6 +73783,9 @@ struct NumericSumOperation : public BaseSumOperation<SumSetOperation, RegularAdd
|
|
|
73538
73783
|
}
|
|
73539
73784
|
};
|
|
73540
73785
|
|
|
73786
|
+
using NumericSumOperation = DoubleSumOperation<RegularAdd>;
|
|
73787
|
+
using KahanSumOperation = DoubleSumOperation<KahanAdd>;
|
|
73788
|
+
|
|
73541
73789
|
struct HugeintSumOperation : public BaseSumOperation<SumSetOperation, RegularAdd> {
|
|
73542
73790
|
template <class T, class STATE>
|
|
73543
73791
|
static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) {
|
|
@@ -73646,12 +73894,23 @@ void SumFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
73646
73894
|
sum.AddFunction(GetSumAggregate(PhysicalType::INT32));
|
|
73647
73895
|
sum.AddFunction(GetSumAggregate(PhysicalType::INT64));
|
|
73648
73896
|
sum.AddFunction(GetSumAggregate(PhysicalType::INT128));
|
|
73649
|
-
// float sums to float
|
|
73650
|
-
// FIXME: implement http://ic.ese.upenn.edu/pdf/parallel_fpaccum_tc2016.pdf for parallel FP sums
|
|
73651
73897
|
sum.AddFunction(AggregateFunction::UnaryAggregate<SumState<double>, double, double, NumericSumOperation>(
|
|
73652
73898
|
LogicalType::DOUBLE, LogicalType::DOUBLE));
|
|
73653
73899
|
|
|
73654
73900
|
set.AddFunction(sum);
|
|
73901
|
+
|
|
73902
|
+
// fsum
|
|
73903
|
+
AggregateFunctionSet fsum("fsum");
|
|
73904
|
+
fsum.AddFunction(AggregateFunction::UnaryAggregate<KahanSumState, double, double, KahanSumOperation>(
|
|
73905
|
+
LogicalType::DOUBLE, LogicalType::DOUBLE));
|
|
73906
|
+
|
|
73907
|
+
set.AddFunction(fsum);
|
|
73908
|
+
|
|
73909
|
+
fsum.name = "kahan_sum";
|
|
73910
|
+
set.AddFunction(fsum);
|
|
73911
|
+
|
|
73912
|
+
fsum.name = "sumKahan";
|
|
73913
|
+
set.AddFunction(fsum);
|
|
73655
73914
|
}
|
|
73656
73915
|
|
|
73657
73916
|
} // namespace duckdb
|
|
@@ -74963,14 +75222,12 @@ struct QuantileState {
|
|
|
74963
75222
|
// Regular aggregation
|
|
74964
75223
|
std::vector<SaveType> v;
|
|
74965
75224
|
|
|
74966
|
-
// Windowed
|
|
75225
|
+
// Windowed Quantile indirection
|
|
74967
75226
|
std::vector<idx_t> w;
|
|
74968
75227
|
idx_t pos;
|
|
74969
75228
|
|
|
74970
|
-
//
|
|
74971
|
-
std::vector<idx_t>
|
|
74972
|
-
std::vector<idx_t> lower;
|
|
74973
|
-
std::vector<idx_t> upper;
|
|
75229
|
+
// Windowed MAD indirection
|
|
75230
|
+
std::vector<idx_t> m;
|
|
74974
75231
|
|
|
74975
75232
|
QuantileState() : pos(0) {
|
|
74976
75233
|
}
|
|
@@ -75052,33 +75309,28 @@ static idx_t ReplaceIndex(idx_t *index, const FrameBounds &frame, const FrameBou
|
|
|
75052
75309
|
}
|
|
75053
75310
|
|
|
75054
75311
|
template <class INPUT_TYPE>
|
|
75055
|
-
static inline
|
|
75056
|
-
|
|
75057
|
-
auto replace = false;
|
|
75058
|
-
|
|
75312
|
+
static inline int CanReplace(const idx_t *index, const INPUT_TYPE *fdata, const idx_t j, const idx_t k0, const idx_t k1,
|
|
75313
|
+
const QuantileNotNull &validity) {
|
|
75059
75314
|
D_ASSERT(index);
|
|
75060
75315
|
|
|
75061
|
-
// NULLs
|
|
75062
|
-
//
|
|
75316
|
+
// NULLs sort to the end, so if we have inserted a NULL,
|
|
75317
|
+
// it must be past the end of the quantile to be replaceable.
|
|
75318
|
+
// Note that the quantile values are never NULL.
|
|
75063
75319
|
const auto ij = index[j];
|
|
75064
|
-
|
|
75065
|
-
|
|
75066
|
-
const auto nullj = !validity(ij);
|
|
75067
|
-
const auto nullk0 = !validity(ik0);
|
|
75068
|
-
if (nullj || nullk0) {
|
|
75069
|
-
return nullj == nullk0;
|
|
75320
|
+
if (!validity(ij)) {
|
|
75321
|
+
return k1 < j ? 1 : 0;
|
|
75070
75322
|
}
|
|
75071
75323
|
|
|
75072
75324
|
auto curr = fdata[ij];
|
|
75073
75325
|
if (k1 < j) {
|
|
75074
|
-
auto hi = fdata[
|
|
75075
|
-
|
|
75326
|
+
auto hi = fdata[index[k0]];
|
|
75327
|
+
return hi < curr ? 1 : 0;
|
|
75076
75328
|
} else if (j < k0) {
|
|
75077
|
-
auto lo = fdata[
|
|
75078
|
-
|
|
75329
|
+
auto lo = fdata[index[k1]];
|
|
75330
|
+
return curr < lo ? -1 : 0;
|
|
75079
75331
|
}
|
|
75080
75332
|
|
|
75081
|
-
return
|
|
75333
|
+
return 0;
|
|
75082
75334
|
}
|
|
75083
75335
|
|
|
75084
75336
|
template <class INPUT_TYPE>
|
|
@@ -75195,7 +75447,8 @@ struct QuantileLess {
|
|
|
75195
75447
|
// Continuous interpolation
|
|
75196
75448
|
template <bool DISCRETE>
|
|
75197
75449
|
struct Interpolator {
|
|
75198
|
-
Interpolator(const double q, const idx_t n_p)
|
|
75450
|
+
Interpolator(const double q, const idx_t n_p)
|
|
75451
|
+
: n(n_p), RN((double)(n_p - 1) * q), FRN(floor(RN)), CRN(ceil(RN)), begin(0), end(n_p) {
|
|
75199
75452
|
}
|
|
75200
75453
|
|
|
75201
75454
|
template <class INPUT_TYPE, class TARGET_TYPE, typename ACCESSOR = QuantileDirect<INPUT_TYPE>>
|
|
@@ -75203,11 +75456,11 @@ struct Interpolator {
|
|
|
75203
75456
|
using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE;
|
|
75204
75457
|
QuantileLess<ACCESSOR> comp(accessor);
|
|
75205
75458
|
if (CRN == FRN) {
|
|
75206
|
-
std::nth_element(v_t, v_t + FRN, v_t +
|
|
75459
|
+
std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp);
|
|
75207
75460
|
return CastInterpolation::Cast<ACCESS_TYPE, TARGET_TYPE>(accessor(v_t[FRN]), result);
|
|
75208
75461
|
} else {
|
|
75209
|
-
std::nth_element(v_t, v_t + FRN, v_t +
|
|
75210
|
-
std::nth_element(v_t + FRN, v_t + CRN, v_t +
|
|
75462
|
+
std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp);
|
|
75463
|
+
std::nth_element(v_t + FRN, v_t + CRN, v_t + end, comp);
|
|
75211
75464
|
auto lo = CastInterpolation::Cast<ACCESS_TYPE, TARGET_TYPE>(accessor(v_t[FRN]), result);
|
|
75212
75465
|
auto hi = CastInterpolation::Cast<ACCESS_TYPE, TARGET_TYPE>(accessor(v_t[CRN]), result);
|
|
75213
75466
|
return CastInterpolation::Interpolate<TARGET_TYPE>(lo, RN - FRN, hi);
|
|
@@ -75230,19 +75483,23 @@ struct Interpolator {
|
|
|
75230
75483
|
const double RN;
|
|
75231
75484
|
const idx_t FRN;
|
|
75232
75485
|
const idx_t CRN;
|
|
75486
|
+
|
|
75487
|
+
idx_t begin;
|
|
75488
|
+
idx_t end;
|
|
75233
75489
|
};
|
|
75234
75490
|
|
|
75235
75491
|
// Discrete "interpolation"
|
|
75236
75492
|
template <>
|
|
75237
75493
|
struct Interpolator<true> {
|
|
75238
|
-
Interpolator(const double q, const idx_t n_p)
|
|
75494
|
+
Interpolator(const double q, const idx_t n_p)
|
|
75495
|
+
: n(n_p), RN((double)(n_p - 1) * q), FRN(floor(RN)), CRN(FRN), begin(0), end(n_p) {
|
|
75239
75496
|
}
|
|
75240
75497
|
|
|
75241
75498
|
template <class INPUT_TYPE, class TARGET_TYPE, typename ACCESSOR = QuantileDirect<INPUT_TYPE>>
|
|
75242
75499
|
TARGET_TYPE Operation(INPUT_TYPE *v_t, Vector &result, const ACCESSOR &accessor = ACCESSOR()) const {
|
|
75243
75500
|
using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE;
|
|
75244
75501
|
QuantileLess<ACCESSOR> comp(accessor);
|
|
75245
|
-
std::nth_element(v_t, v_t + FRN, v_t +
|
|
75502
|
+
std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp);
|
|
75246
75503
|
return CastInterpolation::Cast<ACCESS_TYPE, TARGET_TYPE>(accessor(v_t[FRN]), result);
|
|
75247
75504
|
}
|
|
75248
75505
|
|
|
@@ -75256,6 +75513,9 @@ struct Interpolator<true> {
|
|
|
75256
75513
|
const double RN;
|
|
75257
75514
|
const idx_t FRN;
|
|
75258
75515
|
const idx_t CRN;
|
|
75516
|
+
|
|
75517
|
+
idx_t begin;
|
|
75518
|
+
idx_t end;
|
|
75259
75519
|
};
|
|
75260
75520
|
|
|
75261
75521
|
struct QuantileBindData : public FunctionData {
|
|
@@ -75328,7 +75588,9 @@ static void ExecuteListFinalize(Vector &states, FunctionData *bind_data_p, Vecto
|
|
|
75328
75588
|
|
|
75329
75589
|
D_ASSERT(bind_data_p);
|
|
75330
75590
|
auto bind_data = (QuantileBindData *)bind_data_p;
|
|
75331
|
-
|
|
75591
|
+
if (offset == 0) {
|
|
75592
|
+
ListVector::SetListSize(result, 0);
|
|
75593
|
+
}
|
|
75332
75594
|
|
|
75333
75595
|
if (states.GetVectorType() == VectorType::CONSTANT_VECTOR) {
|
|
75334
75596
|
result.SetVectorType(VectorType::CONSTANT_VECTOR);
|
|
@@ -75406,7 +75668,7 @@ struct QuantileScalarOperation : public QuantileOperation {
|
|
|
75406
75668
|
if (frame.first == prev.first + 1 && frame.second == prev.second + 1) {
|
|
75407
75669
|
// Fixed frame size
|
|
75408
75670
|
const auto j = ReplaceIndex(index, frame, prev);
|
|
75409
|
-
// We can only replace if the number of
|
|
75671
|
+
// We can only replace if the number of NULLs has not changed
|
|
75410
75672
|
if (dmask.AllValid() || not_null(prev.first) == not_null(prev.second)) {
|
|
75411
75673
|
Interpolator<DISCRETE> interp(q, prev_pos);
|
|
75412
75674
|
replace = CanReplace(index, data, j, interp.FRN, interp.CRN, not_null);
|
|
@@ -75515,15 +75777,19 @@ struct QuantileListOperation : public QuantileOperation {
|
|
|
75515
75777
|
auto v_t = state->v.data();
|
|
75516
75778
|
D_ASSERT(v_t);
|
|
75517
75779
|
|
|
75518
|
-
target[idx]
|
|
75519
|
-
|
|
75780
|
+
auto &entry = target[idx];
|
|
75781
|
+
entry.offset = ridx;
|
|
75782
|
+
idx_t lower = 0;
|
|
75783
|
+
for (const auto &q : bind_data->order) {
|
|
75784
|
+
const auto &quantile = bind_data->quantiles[q];
|
|
75520
75785
|
Interpolator<DISCRETE> interp(quantile, state->v.size());
|
|
75521
|
-
|
|
75522
|
-
|
|
75786
|
+
interp.begin = lower;
|
|
75787
|
+
rdata[ridx + q] = interp.template Operation<typename STATE::SaveType, CHILD_TYPE>(v_t, result);
|
|
75788
|
+
lower = interp.FRN;
|
|
75523
75789
|
}
|
|
75524
|
-
|
|
75790
|
+
entry.length = bind_data->quantiles.size();
|
|
75525
75791
|
|
|
75526
|
-
ListVector::SetListSize(result_list,
|
|
75792
|
+
ListVector::SetListSize(result_list, entry.offset + entry.length);
|
|
75527
75793
|
}
|
|
75528
75794
|
|
|
75529
75795
|
template <class STATE, class INPUT_TYPE, class RESULT_TYPE>
|
|
@@ -75547,57 +75813,75 @@ struct QuantileListOperation : public QuantileOperation {
|
|
|
75547
75813
|
auto rdata = FlatVector::GetData<CHILD_TYPE>(result);
|
|
75548
75814
|
|
|
75549
75815
|
// Lazily initialise frame state
|
|
75550
|
-
|
|
75816
|
+
auto prev_pos = state->pos;
|
|
75551
75817
|
state->SetPos(frame.second - frame.first);
|
|
75552
75818
|
|
|
75553
75819
|
auto index = state->w.data();
|
|
75554
75820
|
|
|
75555
|
-
|
|
75556
|
-
|
|
75557
|
-
|
|
75821
|
+
// We can generalise replacement for quantile lists by observing that when a replacement is
|
|
75822
|
+
// valid for a single quantile, it is valid for all quantiles greater/less than that quantile
|
|
75823
|
+
// based on whether the insertion is below/above the quantile location.
|
|
75824
|
+
// So if a replaced index in an IQR is located between Q25 and Q50, but has a value below Q25,
|
|
75825
|
+
// then Q25 must be recomputed, but Q50 and Q75 are unaffected.
|
|
75826
|
+
// For a single element list, this reduces to the scalar case.
|
|
75827
|
+
std::pair<idx_t, idx_t> replaceable {state->pos, 0};
|
|
75828
|
+
if (frame.first == prev.first + 1 && frame.second == prev.second + 1) {
|
|
75558
75829
|
// Fixed frame size
|
|
75559
|
-
j = ReplaceIndex(index, frame, prev);
|
|
75560
|
-
|
|
75830
|
+
const auto j = ReplaceIndex(index, frame, prev);
|
|
75831
|
+
// We can only replace if the number of NULLs has not changed
|
|
75832
|
+
if (dmask.AllValid() || not_null(prev.first) == not_null(prev.second)) {
|
|
75833
|
+
for (const auto &q : bind_data->order) {
|
|
75834
|
+
const auto &quantile = bind_data->quantiles[q];
|
|
75835
|
+
Interpolator<DISCRETE> interp(quantile, prev_pos);
|
|
75836
|
+
const auto replace = CanReplace(index, data, j, interp.FRN, interp.CRN, not_null);
|
|
75837
|
+
if (replace < 0) {
|
|
75838
|
+
// Replacement is before this quantile, so the rest will be replaceable too.
|
|
75839
|
+
replaceable.first = MinValue(replaceable.first, interp.FRN);
|
|
75840
|
+
replaceable.second = prev_pos;
|
|
75841
|
+
break;
|
|
75842
|
+
} else if (replace > 0) {
|
|
75843
|
+
// Replacement is after this quantile, so everything before it is replaceable too.
|
|
75844
|
+
replaceable.first = 0;
|
|
75845
|
+
replaceable.second = MaxValue(replaceable.second, interp.CRN);
|
|
75846
|
+
}
|
|
75847
|
+
}
|
|
75848
|
+
if (replaceable.first < replaceable.second) {
|
|
75849
|
+
state->pos = prev_pos;
|
|
75850
|
+
}
|
|
75851
|
+
}
|
|
75561
75852
|
} else {
|
|
75562
75853
|
ReuseIndexes(index, frame, prev);
|
|
75563
|
-
if (!dmask.AllValid()) {
|
|
75564
|
-
state->pos = std::partition(index, index + state->pos, not_null) - index;
|
|
75565
|
-
}
|
|
75566
75854
|
}
|
|
75567
75855
|
|
|
75568
|
-
if (!
|
|
75569
|
-
|
|
75570
|
-
|
|
75856
|
+
if (replaceable.first >= replaceable.second && !dmask.AllValid()) {
|
|
75857
|
+
// Remove the NULLs
|
|
75858
|
+
state->pos = std::partition(index, index + state->pos, not_null) - index;
|
|
75571
75859
|
}
|
|
75572
75860
|
|
|
75573
|
-
|
|
75574
|
-
|
|
75575
|
-
|
|
75576
|
-
|
|
75577
|
-
|
|
75578
|
-
|
|
75579
|
-
|
|
75580
|
-
|
|
75581
|
-
|
|
75582
|
-
|
|
75583
|
-
|
|
75584
|
-
|
|
75585
|
-
|
|
75586
|
-
|
|
75587
|
-
|
|
75588
|
-
|
|
75589
|
-
|
|
75861
|
+
if (state->pos) {
|
|
75862
|
+
using ID = QuantileIndirect<INPUT_TYPE>;
|
|
75863
|
+
ID indirect(data);
|
|
75864
|
+
for (const auto &q : bind_data->order) {
|
|
75865
|
+
const auto &quantile = bind_data->quantiles[q];
|
|
75866
|
+
Interpolator<DISCRETE> interp(quantile, state->pos);
|
|
75867
|
+
if (replaceable.first <= interp.FRN && interp.CRN <= replaceable.second) {
|
|
75868
|
+
rdata[lentry.offset + q] = interp.template Replace<idx_t, CHILD_TYPE, ID>(index, result, indirect);
|
|
75869
|
+
} else {
|
|
75870
|
+
// Make sure we don't disturb any replacements
|
|
75871
|
+
if (replaceable.first < replaceable.second) {
|
|
75872
|
+
if (interp.FRN < replaceable.first) {
|
|
75873
|
+
interp.end = replaceable.first;
|
|
75874
|
+
}
|
|
75875
|
+
if (replaceable.second < interp.CRN) {
|
|
75876
|
+
interp.begin = replaceable.second;
|
|
75877
|
+
}
|
|
75878
|
+
}
|
|
75879
|
+
rdata[lentry.offset + q] =
|
|
75880
|
+
interp.template Operation<idx_t, CHILD_TYPE, ID>(index, result, indirect);
|
|
75881
|
+
}
|
|
75590
75882
|
}
|
|
75591
|
-
|
|
75592
|
-
|
|
75593
|
-
state->upper.resize(state->lower.size(), state->pos);
|
|
75594
|
-
|
|
75595
|
-
// Second pass: select the disturbed values
|
|
75596
|
-
for (idx_t i = 0; i < state->disturbed.size(); ++i) {
|
|
75597
|
-
const auto &q = state->disturbed[i];
|
|
75598
|
-
const auto &quantile = bind_data->quantiles[q];
|
|
75599
|
-
Interpolator<DISCRETE> interp(quantile, state->pos);
|
|
75600
|
-
rdata[lentry.offset + q] = interp.template Operation<idx_t, CHILD_TYPE>(index, result, indirect);
|
|
75883
|
+
} else {
|
|
75884
|
+
lmask.Set(lidx, false);
|
|
75601
75885
|
}
|
|
75602
75886
|
}
|
|
75603
75887
|
};
|
|
@@ -75877,12 +76161,11 @@ struct MedianAbsoluteDeviationOperation : public QuantileOperation {
|
|
|
75877
76161
|
D_ASSERT(index);
|
|
75878
76162
|
|
|
75879
76163
|
// We need a second index for the second pass.
|
|
75880
|
-
|
|
75881
|
-
|
|
75882
|
-
state->disturbed.resize(state->pos);
|
|
76164
|
+
if (state->pos > state->m.size()) {
|
|
76165
|
+
state->m.resize(state->pos);
|
|
75883
76166
|
}
|
|
75884
76167
|
|
|
75885
|
-
auto index2 = state->
|
|
76168
|
+
auto index2 = state->m.data();
|
|
75886
76169
|
D_ASSERT(index2);
|
|
75887
76170
|
|
|
75888
76171
|
// The replacement trick does not work on the second index because if
|
|
@@ -76475,9 +76758,16 @@ struct MapFun {
|
|
|
76475
76758
|
struct MapExtractFun {
|
|
76476
76759
|
static void RegisterFunction(BuiltinFunctions &set);
|
|
76477
76760
|
};
|
|
76761
|
+
|
|
76478
76762
|
struct ListExtractFun {
|
|
76479
76763
|
static void RegisterFunction(BuiltinFunctions &set);
|
|
76480
76764
|
};
|
|
76765
|
+
|
|
76766
|
+
struct ListConcatFun {
|
|
76767
|
+
static ScalarFunction GetFunction();
|
|
76768
|
+
static void RegisterFunction(BuiltinFunctions &set);
|
|
76769
|
+
};
|
|
76770
|
+
|
|
76481
76771
|
struct CardinalityFun {
|
|
76482
76772
|
static void RegisterFunction(BuiltinFunctions &set);
|
|
76483
76773
|
};
|
|
@@ -83453,11 +83743,6 @@ void ArraySliceFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
83453
83743
|
|
|
83454
83744
|
|
|
83455
83745
|
|
|
83456
|
-
|
|
83457
|
-
|
|
83458
|
-
|
|
83459
|
-
|
|
83460
|
-
|
|
83461
83746
|
//===----------------------------------------------------------------------===//
|
|
83462
83747
|
// DuckDB
|
|
83463
83748
|
//
|
|
@@ -83497,6 +83782,147 @@ public:
|
|
|
83497
83782
|
|
|
83498
83783
|
|
|
83499
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
|
+
|
|
83500
83926
|
namespace duckdb {
|
|
83501
83927
|
|
|
83502
83928
|
template <class T, bool HEAP_REF = false, bool VALIDITY_ONLY = false>
|
|
@@ -85465,6 +85891,7 @@ void BuiltinFunctions::RegisterNestedFunctions() {
|
|
|
85465
85891
|
Register<ArraySliceFun>();
|
|
85466
85892
|
Register<StructPackFun>();
|
|
85467
85893
|
Register<StructExtractFun>();
|
|
85894
|
+
Register<ListConcatFun>();
|
|
85468
85895
|
Register<ListValueFun>();
|
|
85469
85896
|
Register<ListExtractFun>();
|
|
85470
85897
|
Register<ListRangeFun>();
|
|
@@ -85811,6 +86238,7 @@ struct BitwiseNotFun {
|
|
|
85811
86238
|
|
|
85812
86239
|
|
|
85813
86240
|
|
|
86241
|
+
|
|
85814
86242
|
#include <limits>
|
|
85815
86243
|
|
|
85816
86244
|
namespace duckdb {
|
|
@@ -86126,6 +86554,8 @@ void AddFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
86126
86554
|
|
|
86127
86555
|
functions.AddFunction(GetFunction(LogicalType::TIMESTAMP, LogicalType::INTERVAL));
|
|
86128
86556
|
functions.AddFunction(GetFunction(LogicalType::INTERVAL, LogicalType::TIMESTAMP));
|
|
86557
|
+
// we can add lists together
|
|
86558
|
+
functions.AddFunction(ListConcatFun::GetFunction());
|
|
86129
86559
|
|
|
86130
86560
|
set.AddFunction(functions);
|
|
86131
86561
|
}
|
|
@@ -87708,6 +88138,7 @@ void CHR::RegisterFunction(BuiltinFunctions &set) {
|
|
|
87708
88138
|
|
|
87709
88139
|
|
|
87710
88140
|
|
|
88141
|
+
|
|
87711
88142
|
#include <string.h>
|
|
87712
88143
|
|
|
87713
88144
|
namespace duckdb {
|
|
@@ -87953,6 +88384,7 @@ void ConcatFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
87953
88384
|
concat_op.AddFunction(
|
|
87954
88385
|
ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::VARCHAR, ConcatOperator));
|
|
87955
88386
|
concat_op.AddFunction(ScalarFunction({LogicalType::BLOB, LogicalType::BLOB}, LogicalType::BLOB, ConcatOperator));
|
|
88387
|
+
concat_op.AddFunction(ListConcatFun::GetFunction());
|
|
87956
88388
|
set.AddFunction(concat_op);
|
|
87957
88389
|
|
|
87958
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
|
};
|
|
@@ -5957,6 +5962,8 @@ template <>
|
|
|
5957
5962
|
bool Hugeint::TryCast(hugeint_t input, float &result);
|
|
5958
5963
|
template <>
|
|
5959
5964
|
bool Hugeint::TryCast(hugeint_t input, double &result);
|
|
5965
|
+
template <>
|
|
5966
|
+
bool Hugeint::TryCast(hugeint_t input, long double &result);
|
|
5960
5967
|
|
|
5961
5968
|
template <>
|
|
5962
5969
|
bool Hugeint::TryConvert(int8_t value, hugeint_t &result);
|
|
@@ -5978,6 +5985,8 @@ template <>
|
|
|
5978
5985
|
bool Hugeint::TryConvert(float value, hugeint_t &result);
|
|
5979
5986
|
template <>
|
|
5980
5987
|
bool Hugeint::TryConvert(double value, hugeint_t &result);
|
|
5988
|
+
template <>
|
|
5989
|
+
bool Hugeint::TryConvert(long double value, hugeint_t &result);
|
|
5981
5990
|
|
|
5982
5991
|
} // namespace duckdb
|
|
5983
5992
|
|