duckdb 0.3.1-dev501.0 → 0.3.1-dev517.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 +418 -117
- package/src/duckdb.hpp +6 -2
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++) {
|
|
@@ -35946,20 +35950,30 @@ bool Hugeint::TryCast(hugeint_t input, float &result) {
|
|
|
35946
35950
|
return true;
|
|
35947
35951
|
}
|
|
35948
35952
|
|
|
35949
|
-
template
|
|
35950
|
-
bool
|
|
35953
|
+
template <class REAL_T>
|
|
35954
|
+
bool CastBigintToFloating(hugeint_t input, REAL_T &result) {
|
|
35951
35955
|
switch (input.upper) {
|
|
35952
35956
|
case -1:
|
|
35953
35957
|
// special case for upper = -1 to avoid rounding issues in small negative numbers
|
|
35954
|
-
result = -
|
|
35958
|
+
result = -REAL_T(NumericLimits<uint64_t>::Maximum() - input.lower) - 1;
|
|
35955
35959
|
break;
|
|
35956
35960
|
default:
|
|
35957
|
-
result =
|
|
35961
|
+
result = REAL_T(input.lower) + REAL_T(input.upper) * REAL_T(NumericLimits<uint64_t>::Maximum());
|
|
35958
35962
|
break;
|
|
35959
35963
|
}
|
|
35960
35964
|
return true;
|
|
35961
35965
|
}
|
|
35962
35966
|
|
|
35967
|
+
template <>
|
|
35968
|
+
bool Hugeint::TryCast(hugeint_t input, double &result) {
|
|
35969
|
+
return CastBigintToFloating<double>(input, result);
|
|
35970
|
+
}
|
|
35971
|
+
|
|
35972
|
+
template <>
|
|
35973
|
+
bool Hugeint::TryCast(hugeint_t input, long double &result) {
|
|
35974
|
+
return CastBigintToFloating<long double>(input, result);
|
|
35975
|
+
}
|
|
35976
|
+
|
|
35963
35977
|
template <class DST>
|
|
35964
35978
|
hugeint_t HugeintConvertInteger(DST input) {
|
|
35965
35979
|
hugeint_t result;
|
|
@@ -36017,8 +36031,8 @@ bool Hugeint::TryConvert(float value, hugeint_t &result) {
|
|
|
36017
36031
|
return Hugeint::TryConvert(double(value), result);
|
|
36018
36032
|
}
|
|
36019
36033
|
|
|
36020
|
-
template
|
|
36021
|
-
bool
|
|
36034
|
+
template <class REAL_T>
|
|
36035
|
+
bool ConvertFloatingToBigint(REAL_T value, hugeint_t &result) {
|
|
36022
36036
|
if (value <= -170141183460469231731687303715884105728.0 || value >= 170141183460469231731687303715884105727.0) {
|
|
36023
36037
|
return false;
|
|
36024
36038
|
}
|
|
@@ -36026,14 +36040,24 @@ bool Hugeint::TryConvert(double value, hugeint_t &result) {
|
|
|
36026
36040
|
if (negative) {
|
|
36027
36041
|
value = -value;
|
|
36028
36042
|
}
|
|
36029
|
-
result.lower = (uint64_t)fmod(value,
|
|
36030
|
-
result.upper = (uint64_t)(value /
|
|
36043
|
+
result.lower = (uint64_t)fmod(value, REAL_T(NumericLimits<uint64_t>::Maximum()));
|
|
36044
|
+
result.upper = (uint64_t)(value / REAL_T(NumericLimits<uint64_t>::Maximum()));
|
|
36031
36045
|
if (negative) {
|
|
36032
|
-
NegateInPlace(result);
|
|
36046
|
+
Hugeint::NegateInPlace(result);
|
|
36033
36047
|
}
|
|
36034
36048
|
return true;
|
|
36035
36049
|
}
|
|
36036
36050
|
|
|
36051
|
+
template <>
|
|
36052
|
+
bool Hugeint::TryConvert(double value, hugeint_t &result) {
|
|
36053
|
+
return ConvertFloatingToBigint<double>(value, result);
|
|
36054
|
+
}
|
|
36055
|
+
|
|
36056
|
+
template <>
|
|
36057
|
+
bool Hugeint::TryConvert(long double value, hugeint_t &result) {
|
|
36058
|
+
return ConvertFloatingToBigint<long double>(value, result);
|
|
36059
|
+
}
|
|
36060
|
+
|
|
36037
36061
|
//===--------------------------------------------------------------------===//
|
|
36038
36062
|
// hugeint_t operators
|
|
36039
36063
|
//===--------------------------------------------------------------------===//
|
|
@@ -70552,6 +70576,45 @@ struct VarianceFun {
|
|
|
70552
70576
|
|
|
70553
70577
|
namespace duckdb {
|
|
70554
70578
|
|
|
70579
|
+
static inline void KahanAddInternal(double input, double &summed, double &err) {
|
|
70580
|
+
double diff = input - err;
|
|
70581
|
+
double newval = summed + diff;
|
|
70582
|
+
err = (newval - summed) - diff;
|
|
70583
|
+
summed = newval;
|
|
70584
|
+
}
|
|
70585
|
+
|
|
70586
|
+
template <class T>
|
|
70587
|
+
struct SumState {
|
|
70588
|
+
bool isset;
|
|
70589
|
+
T value;
|
|
70590
|
+
|
|
70591
|
+
void Initialize() {
|
|
70592
|
+
this->isset = false;
|
|
70593
|
+
}
|
|
70594
|
+
|
|
70595
|
+
void Combine(const SumState<T> &other) {
|
|
70596
|
+
this->isset = other.isset || this->isset;
|
|
70597
|
+
this->value += other.value;
|
|
70598
|
+
}
|
|
70599
|
+
};
|
|
70600
|
+
|
|
70601
|
+
struct KahanSumState {
|
|
70602
|
+
bool isset;
|
|
70603
|
+
double value;
|
|
70604
|
+
double err;
|
|
70605
|
+
|
|
70606
|
+
void Initialize() {
|
|
70607
|
+
this->isset = false;
|
|
70608
|
+
this->err = 0.0;
|
|
70609
|
+
}
|
|
70610
|
+
|
|
70611
|
+
void Combine(const KahanSumState &other) {
|
|
70612
|
+
this->isset = other.isset || this->isset;
|
|
70613
|
+
KahanAddInternal(other.value, this->value, this->err);
|
|
70614
|
+
KahanAddInternal(other.err, this->value, this->err);
|
|
70615
|
+
}
|
|
70616
|
+
};
|
|
70617
|
+
|
|
70555
70618
|
struct RegularAdd {
|
|
70556
70619
|
template <class STATE, class T>
|
|
70557
70620
|
static void AddNumber(STATE &state, T input) {
|
|
@@ -70564,6 +70627,18 @@ struct RegularAdd {
|
|
|
70564
70627
|
}
|
|
70565
70628
|
};
|
|
70566
70629
|
|
|
70630
|
+
struct KahanAdd {
|
|
70631
|
+
template <class STATE, class T>
|
|
70632
|
+
static void AddNumber(STATE &state, T input) {
|
|
70633
|
+
KahanAddInternal(input, state.value, state.err);
|
|
70634
|
+
}
|
|
70635
|
+
|
|
70636
|
+
template <class STATE, class T>
|
|
70637
|
+
static void AddConstant(STATE &state, T input, idx_t count) {
|
|
70638
|
+
KahanAddInternal(input * count, state.value, state.err);
|
|
70639
|
+
}
|
|
70640
|
+
};
|
|
70641
|
+
|
|
70567
70642
|
struct HugeintAdd {
|
|
70568
70643
|
static void AddValue(hugeint_t &result, uint64_t value, int positive) {
|
|
70569
70644
|
// integer summation taken from Tim Gubner et al. - Efficient Query Processing
|
|
@@ -70659,8 +70734,34 @@ namespace duckdb {
|
|
|
70659
70734
|
|
|
70660
70735
|
template <class T>
|
|
70661
70736
|
struct AvgState {
|
|
70737
|
+
uint64_t count;
|
|
70662
70738
|
T value;
|
|
70739
|
+
|
|
70740
|
+
void Initialize() {
|
|
70741
|
+
this->count = 0;
|
|
70742
|
+
}
|
|
70743
|
+
|
|
70744
|
+
void Combine(const AvgState<T> &other) {
|
|
70745
|
+
this->count += other.count;
|
|
70746
|
+
this->value += other.value;
|
|
70747
|
+
}
|
|
70748
|
+
};
|
|
70749
|
+
|
|
70750
|
+
struct KahanAvgState {
|
|
70663
70751
|
uint64_t count;
|
|
70752
|
+
double value;
|
|
70753
|
+
double err;
|
|
70754
|
+
|
|
70755
|
+
void Initialize() {
|
|
70756
|
+
this->count = 0;
|
|
70757
|
+
this->err = 0.0;
|
|
70758
|
+
}
|
|
70759
|
+
|
|
70760
|
+
void Combine(const KahanAvgState &other) {
|
|
70761
|
+
this->count += other.count;
|
|
70762
|
+
KahanAddInternal(other.value, this->value, this->err);
|
|
70763
|
+
KahanAddInternal(other.err, this->value, this->err);
|
|
70764
|
+
}
|
|
70664
70765
|
};
|
|
70665
70766
|
|
|
70666
70767
|
struct AverageDecimalBindData : public FunctionData {
|
|
@@ -70678,12 +70779,11 @@ public:
|
|
|
70678
70779
|
struct AverageSetOperation {
|
|
70679
70780
|
template <class STATE>
|
|
70680
70781
|
static void Initialize(STATE *state) {
|
|
70681
|
-
state->
|
|
70782
|
+
state->Initialize();
|
|
70682
70783
|
}
|
|
70683
70784
|
template <class STATE>
|
|
70684
70785
|
static void Combine(const STATE &source, STATE *target) {
|
|
70685
|
-
target->
|
|
70686
|
-
target->value += source.value;
|
|
70786
|
+
target->Combine(source);
|
|
70687
70787
|
}
|
|
70688
70788
|
template <class STATE>
|
|
70689
70789
|
static void AddValues(STATE *state, idx_t count) {
|
|
@@ -70691,8 +70791,9 @@ struct AverageSetOperation {
|
|
|
70691
70791
|
}
|
|
70692
70792
|
};
|
|
70693
70793
|
|
|
70694
|
-
|
|
70695
|
-
|
|
70794
|
+
template <class T>
|
|
70795
|
+
static T GetAverageDivident(uint64_t count, FunctionData *bind_data) {
|
|
70796
|
+
T divident = T(count);
|
|
70696
70797
|
if (bind_data) {
|
|
70697
70798
|
auto &avg_bind_data = (AverageDecimalBindData &)*bind_data;
|
|
70698
70799
|
divident *= avg_bind_data.scale;
|
|
@@ -70707,7 +70808,7 @@ struct IntegerAverageOperation : public BaseSumOperation<AverageSetOperation, Re
|
|
|
70707
70808
|
if (state->count == 0) {
|
|
70708
70809
|
mask.SetInvalid(idx);
|
|
70709
70810
|
} else {
|
|
70710
|
-
double divident = GetAverageDivident(state->count, bind_data);
|
|
70811
|
+
double divident = GetAverageDivident<double>(state->count, bind_data);
|
|
70711
70812
|
target[idx] = double(state->value) / divident;
|
|
70712
70813
|
}
|
|
70713
70814
|
}
|
|
@@ -70720,8 +70821,8 @@ struct IntegerAverageOperationHugeint : public BaseSumOperation<AverageSetOperat
|
|
|
70720
70821
|
if (state->count == 0) {
|
|
70721
70822
|
mask.SetInvalid(idx);
|
|
70722
70823
|
} else {
|
|
70723
|
-
double divident = GetAverageDivident(state->count, bind_data);
|
|
70724
|
-
target[idx] = Hugeint::Cast<double>(state->value) / divident;
|
|
70824
|
+
long double divident = GetAverageDivident<long double>(state->count, bind_data);
|
|
70825
|
+
target[idx] = Hugeint::Cast<long double>(state->value) / divident;
|
|
70725
70826
|
}
|
|
70726
70827
|
}
|
|
70727
70828
|
};
|
|
@@ -70733,8 +70834,8 @@ struct HugeintAverageOperation : public BaseSumOperation<AverageSetOperation, Re
|
|
|
70733
70834
|
if (state->count == 0) {
|
|
70734
70835
|
mask.SetInvalid(idx);
|
|
70735
70836
|
} else {
|
|
70736
|
-
double divident = GetAverageDivident(state->count, bind_data);
|
|
70737
|
-
target[idx] = Hugeint::Cast<double>(state->value) / divident;
|
|
70837
|
+
long double divident = GetAverageDivident<long double>(state->count, bind_data);
|
|
70838
|
+
target[idx] = Hugeint::Cast<long double>(state->value) / divident;
|
|
70738
70839
|
}
|
|
70739
70840
|
}
|
|
70740
70841
|
};
|
|
@@ -70748,7 +70849,21 @@ struct NumericAverageOperation : public BaseSumOperation<AverageSetOperation, Re
|
|
|
70748
70849
|
if (!Value::DoubleIsValid(state->value)) {
|
|
70749
70850
|
throw OutOfRangeException("AVG is out of range!");
|
|
70750
70851
|
}
|
|
70751
|
-
target[idx] = state->value / state->count;
|
|
70852
|
+
target[idx] = (state->value / state->count);
|
|
70853
|
+
}
|
|
70854
|
+
}
|
|
70855
|
+
};
|
|
70856
|
+
|
|
70857
|
+
struct KahanAverageOperation : public BaseSumOperation<AverageSetOperation, KahanAdd> {
|
|
70858
|
+
template <class T, class STATE>
|
|
70859
|
+
static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) {
|
|
70860
|
+
if (state->count == 0) {
|
|
70861
|
+
mask.SetInvalid(idx);
|
|
70862
|
+
} else {
|
|
70863
|
+
if (!Value::DoubleIsValid(state->value)) {
|
|
70864
|
+
throw OutOfRangeException("AVG is out of range!");
|
|
70865
|
+
}
|
|
70866
|
+
target[idx] = (state->value / state->count) + (state->err / state->count);
|
|
70752
70867
|
}
|
|
70753
70868
|
}
|
|
70754
70869
|
};
|
|
@@ -70800,6 +70915,11 @@ void AvgFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
70800
70915
|
avg.AddFunction(AggregateFunction::UnaryAggregate<AvgState<double>, double, double, NumericAverageOperation>(
|
|
70801
70916
|
LogicalType::DOUBLE, LogicalType::DOUBLE));
|
|
70802
70917
|
set.AddFunction(avg);
|
|
70918
|
+
|
|
70919
|
+
AggregateFunctionSet favg("favg");
|
|
70920
|
+
favg.AddFunction(AggregateFunction::UnaryAggregate<KahanAvgState, double, double, KahanAverageOperation>(
|
|
70921
|
+
LogicalType::DOUBLE, LogicalType::DOUBLE));
|
|
70922
|
+
set.AddFunction(favg);
|
|
70803
70923
|
}
|
|
70804
70924
|
|
|
70805
70925
|
} // namespace duckdb
|
|
@@ -73480,21 +73600,14 @@ void StringAggFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
73480
73600
|
|
|
73481
73601
|
namespace duckdb {
|
|
73482
73602
|
|
|
73483
|
-
template <class T>
|
|
73484
|
-
struct SumState {
|
|
73485
|
-
T value;
|
|
73486
|
-
bool isset;
|
|
73487
|
-
};
|
|
73488
|
-
|
|
73489
73603
|
struct SumSetOperation {
|
|
73490
73604
|
template <class STATE>
|
|
73491
73605
|
static void Initialize(STATE *state) {
|
|
73492
|
-
state->
|
|
73606
|
+
state->Initialize();
|
|
73493
73607
|
}
|
|
73494
73608
|
template <class STATE>
|
|
73495
73609
|
static void Combine(const STATE &source, STATE *target) {
|
|
73496
|
-
target->
|
|
73497
|
-
target->value += source.value;
|
|
73610
|
+
target->Combine(source);
|
|
73498
73611
|
}
|
|
73499
73612
|
template <class STATE>
|
|
73500
73613
|
static void AddValues(STATE *state, idx_t count) {
|
|
@@ -73524,7 +73637,8 @@ struct SumToHugeintOperation : public BaseSumOperation<SumSetOperation, HugeintA
|
|
|
73524
73637
|
}
|
|
73525
73638
|
};
|
|
73526
73639
|
|
|
73527
|
-
|
|
73640
|
+
template <class ADD_OPERATOR>
|
|
73641
|
+
struct DoubleSumOperation : public BaseSumOperation<SumSetOperation, ADD_OPERATOR> {
|
|
73528
73642
|
template <class T, class STATE>
|
|
73529
73643
|
static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) {
|
|
73530
73644
|
if (!state->isset) {
|
|
@@ -73538,6 +73652,9 @@ struct NumericSumOperation : public BaseSumOperation<SumSetOperation, RegularAdd
|
|
|
73538
73652
|
}
|
|
73539
73653
|
};
|
|
73540
73654
|
|
|
73655
|
+
using NumericSumOperation = DoubleSumOperation<RegularAdd>;
|
|
73656
|
+
using KahanSumOperation = DoubleSumOperation<KahanAdd>;
|
|
73657
|
+
|
|
73541
73658
|
struct HugeintSumOperation : public BaseSumOperation<SumSetOperation, RegularAdd> {
|
|
73542
73659
|
template <class T, class STATE>
|
|
73543
73660
|
static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) {
|
|
@@ -73646,12 +73763,23 @@ void SumFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
73646
73763
|
sum.AddFunction(GetSumAggregate(PhysicalType::INT32));
|
|
73647
73764
|
sum.AddFunction(GetSumAggregate(PhysicalType::INT64));
|
|
73648
73765
|
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
73766
|
sum.AddFunction(AggregateFunction::UnaryAggregate<SumState<double>, double, double, NumericSumOperation>(
|
|
73652
73767
|
LogicalType::DOUBLE, LogicalType::DOUBLE));
|
|
73653
73768
|
|
|
73654
73769
|
set.AddFunction(sum);
|
|
73770
|
+
|
|
73771
|
+
// fsum
|
|
73772
|
+
AggregateFunctionSet fsum("fsum");
|
|
73773
|
+
fsum.AddFunction(AggregateFunction::UnaryAggregate<KahanSumState, double, double, KahanSumOperation>(
|
|
73774
|
+
LogicalType::DOUBLE, LogicalType::DOUBLE));
|
|
73775
|
+
|
|
73776
|
+
set.AddFunction(fsum);
|
|
73777
|
+
|
|
73778
|
+
fsum.name = "kahan_sum";
|
|
73779
|
+
set.AddFunction(fsum);
|
|
73780
|
+
|
|
73781
|
+
fsum.name = "sumKahan";
|
|
73782
|
+
set.AddFunction(fsum);
|
|
73655
73783
|
}
|
|
73656
73784
|
|
|
73657
73785
|
} // namespace duckdb
|
|
@@ -74963,14 +75091,12 @@ struct QuantileState {
|
|
|
74963
75091
|
// Regular aggregation
|
|
74964
75092
|
std::vector<SaveType> v;
|
|
74965
75093
|
|
|
74966
|
-
// Windowed
|
|
75094
|
+
// Windowed Quantile indirection
|
|
74967
75095
|
std::vector<idx_t> w;
|
|
74968
75096
|
idx_t pos;
|
|
74969
75097
|
|
|
74970
|
-
//
|
|
74971
|
-
std::vector<idx_t>
|
|
74972
|
-
std::vector<idx_t> lower;
|
|
74973
|
-
std::vector<idx_t> upper;
|
|
75098
|
+
// Windowed MAD indirection
|
|
75099
|
+
std::vector<idx_t> m;
|
|
74974
75100
|
|
|
74975
75101
|
QuantileState() : pos(0) {
|
|
74976
75102
|
}
|
|
@@ -75052,33 +75178,28 @@ static idx_t ReplaceIndex(idx_t *index, const FrameBounds &frame, const FrameBou
|
|
|
75052
75178
|
}
|
|
75053
75179
|
|
|
75054
75180
|
template <class INPUT_TYPE>
|
|
75055
|
-
static inline
|
|
75056
|
-
|
|
75057
|
-
auto replace = false;
|
|
75058
|
-
|
|
75181
|
+
static inline int CanReplace(const idx_t *index, const INPUT_TYPE *fdata, const idx_t j, const idx_t k0, const idx_t k1,
|
|
75182
|
+
const QuantileNotNull &validity) {
|
|
75059
75183
|
D_ASSERT(index);
|
|
75060
75184
|
|
|
75061
|
-
// NULLs
|
|
75062
|
-
//
|
|
75185
|
+
// NULLs sort to the end, so if we have inserted a NULL,
|
|
75186
|
+
// it must be past the end of the quantile to be replaceable.
|
|
75187
|
+
// Note that the quantile values are never NULL.
|
|
75063
75188
|
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;
|
|
75189
|
+
if (!validity(ij)) {
|
|
75190
|
+
return k1 < j ? 1 : 0;
|
|
75070
75191
|
}
|
|
75071
75192
|
|
|
75072
75193
|
auto curr = fdata[ij];
|
|
75073
75194
|
if (k1 < j) {
|
|
75074
|
-
auto hi = fdata[
|
|
75075
|
-
|
|
75195
|
+
auto hi = fdata[index[k0]];
|
|
75196
|
+
return hi < curr ? 1 : 0;
|
|
75076
75197
|
} else if (j < k0) {
|
|
75077
|
-
auto lo = fdata[
|
|
75078
|
-
|
|
75198
|
+
auto lo = fdata[index[k1]];
|
|
75199
|
+
return curr < lo ? -1 : 0;
|
|
75079
75200
|
}
|
|
75080
75201
|
|
|
75081
|
-
return
|
|
75202
|
+
return 0;
|
|
75082
75203
|
}
|
|
75083
75204
|
|
|
75084
75205
|
template <class INPUT_TYPE>
|
|
@@ -75195,7 +75316,8 @@ struct QuantileLess {
|
|
|
75195
75316
|
// Continuous interpolation
|
|
75196
75317
|
template <bool DISCRETE>
|
|
75197
75318
|
struct Interpolator {
|
|
75198
|
-
Interpolator(const double q, const idx_t n_p)
|
|
75319
|
+
Interpolator(const double q, const idx_t n_p)
|
|
75320
|
+
: n(n_p), RN((double)(n_p - 1) * q), FRN(floor(RN)), CRN(ceil(RN)), begin(0), end(n_p) {
|
|
75199
75321
|
}
|
|
75200
75322
|
|
|
75201
75323
|
template <class INPUT_TYPE, class TARGET_TYPE, typename ACCESSOR = QuantileDirect<INPUT_TYPE>>
|
|
@@ -75203,11 +75325,11 @@ struct Interpolator {
|
|
|
75203
75325
|
using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE;
|
|
75204
75326
|
QuantileLess<ACCESSOR> comp(accessor);
|
|
75205
75327
|
if (CRN == FRN) {
|
|
75206
|
-
std::nth_element(v_t, v_t + FRN, v_t +
|
|
75328
|
+
std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp);
|
|
75207
75329
|
return CastInterpolation::Cast<ACCESS_TYPE, TARGET_TYPE>(accessor(v_t[FRN]), result);
|
|
75208
75330
|
} else {
|
|
75209
|
-
std::nth_element(v_t, v_t + FRN, v_t +
|
|
75210
|
-
std::nth_element(v_t + FRN, v_t + CRN, v_t +
|
|
75331
|
+
std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp);
|
|
75332
|
+
std::nth_element(v_t + FRN, v_t + CRN, v_t + end, comp);
|
|
75211
75333
|
auto lo = CastInterpolation::Cast<ACCESS_TYPE, TARGET_TYPE>(accessor(v_t[FRN]), result);
|
|
75212
75334
|
auto hi = CastInterpolation::Cast<ACCESS_TYPE, TARGET_TYPE>(accessor(v_t[CRN]), result);
|
|
75213
75335
|
return CastInterpolation::Interpolate<TARGET_TYPE>(lo, RN - FRN, hi);
|
|
@@ -75230,19 +75352,23 @@ struct Interpolator {
|
|
|
75230
75352
|
const double RN;
|
|
75231
75353
|
const idx_t FRN;
|
|
75232
75354
|
const idx_t CRN;
|
|
75355
|
+
|
|
75356
|
+
idx_t begin;
|
|
75357
|
+
idx_t end;
|
|
75233
75358
|
};
|
|
75234
75359
|
|
|
75235
75360
|
// Discrete "interpolation"
|
|
75236
75361
|
template <>
|
|
75237
75362
|
struct Interpolator<true> {
|
|
75238
|
-
Interpolator(const double q, const idx_t n_p)
|
|
75363
|
+
Interpolator(const double q, const idx_t n_p)
|
|
75364
|
+
: n(n_p), RN((double)(n_p - 1) * q), FRN(floor(RN)), CRN(FRN), begin(0), end(n_p) {
|
|
75239
75365
|
}
|
|
75240
75366
|
|
|
75241
75367
|
template <class INPUT_TYPE, class TARGET_TYPE, typename ACCESSOR = QuantileDirect<INPUT_TYPE>>
|
|
75242
75368
|
TARGET_TYPE Operation(INPUT_TYPE *v_t, Vector &result, const ACCESSOR &accessor = ACCESSOR()) const {
|
|
75243
75369
|
using ACCESS_TYPE = typename ACCESSOR::RESULT_TYPE;
|
|
75244
75370
|
QuantileLess<ACCESSOR> comp(accessor);
|
|
75245
|
-
std::nth_element(v_t, v_t + FRN, v_t +
|
|
75371
|
+
std::nth_element(v_t + begin, v_t + FRN, v_t + end, comp);
|
|
75246
75372
|
return CastInterpolation::Cast<ACCESS_TYPE, TARGET_TYPE>(accessor(v_t[FRN]), result);
|
|
75247
75373
|
}
|
|
75248
75374
|
|
|
@@ -75256,6 +75382,9 @@ struct Interpolator<true> {
|
|
|
75256
75382
|
const double RN;
|
|
75257
75383
|
const idx_t FRN;
|
|
75258
75384
|
const idx_t CRN;
|
|
75385
|
+
|
|
75386
|
+
idx_t begin;
|
|
75387
|
+
idx_t end;
|
|
75259
75388
|
};
|
|
75260
75389
|
|
|
75261
75390
|
struct QuantileBindData : public FunctionData {
|
|
@@ -75328,7 +75457,9 @@ static void ExecuteListFinalize(Vector &states, FunctionData *bind_data_p, Vecto
|
|
|
75328
75457
|
|
|
75329
75458
|
D_ASSERT(bind_data_p);
|
|
75330
75459
|
auto bind_data = (QuantileBindData *)bind_data_p;
|
|
75331
|
-
|
|
75460
|
+
if (offset == 0) {
|
|
75461
|
+
ListVector::SetListSize(result, 0);
|
|
75462
|
+
}
|
|
75332
75463
|
|
|
75333
75464
|
if (states.GetVectorType() == VectorType::CONSTANT_VECTOR) {
|
|
75334
75465
|
result.SetVectorType(VectorType::CONSTANT_VECTOR);
|
|
@@ -75406,7 +75537,7 @@ struct QuantileScalarOperation : public QuantileOperation {
|
|
|
75406
75537
|
if (frame.first == prev.first + 1 && frame.second == prev.second + 1) {
|
|
75407
75538
|
// Fixed frame size
|
|
75408
75539
|
const auto j = ReplaceIndex(index, frame, prev);
|
|
75409
|
-
// We can only replace if the number of
|
|
75540
|
+
// We can only replace if the number of NULLs has not changed
|
|
75410
75541
|
if (dmask.AllValid() || not_null(prev.first) == not_null(prev.second)) {
|
|
75411
75542
|
Interpolator<DISCRETE> interp(q, prev_pos);
|
|
75412
75543
|
replace = CanReplace(index, data, j, interp.FRN, interp.CRN, not_null);
|
|
@@ -75515,15 +75646,19 @@ struct QuantileListOperation : public QuantileOperation {
|
|
|
75515
75646
|
auto v_t = state->v.data();
|
|
75516
75647
|
D_ASSERT(v_t);
|
|
75517
75648
|
|
|
75518
|
-
target[idx]
|
|
75519
|
-
|
|
75649
|
+
auto &entry = target[idx];
|
|
75650
|
+
entry.offset = ridx;
|
|
75651
|
+
idx_t lower = 0;
|
|
75652
|
+
for (const auto &q : bind_data->order) {
|
|
75653
|
+
const auto &quantile = bind_data->quantiles[q];
|
|
75520
75654
|
Interpolator<DISCRETE> interp(quantile, state->v.size());
|
|
75521
|
-
|
|
75522
|
-
|
|
75655
|
+
interp.begin = lower;
|
|
75656
|
+
rdata[ridx + q] = interp.template Operation<typename STATE::SaveType, CHILD_TYPE>(v_t, result);
|
|
75657
|
+
lower = interp.FRN;
|
|
75523
75658
|
}
|
|
75524
|
-
|
|
75659
|
+
entry.length = bind_data->quantiles.size();
|
|
75525
75660
|
|
|
75526
|
-
ListVector::SetListSize(result_list,
|
|
75661
|
+
ListVector::SetListSize(result_list, entry.offset + entry.length);
|
|
75527
75662
|
}
|
|
75528
75663
|
|
|
75529
75664
|
template <class STATE, class INPUT_TYPE, class RESULT_TYPE>
|
|
@@ -75547,57 +75682,75 @@ struct QuantileListOperation : public QuantileOperation {
|
|
|
75547
75682
|
auto rdata = FlatVector::GetData<CHILD_TYPE>(result);
|
|
75548
75683
|
|
|
75549
75684
|
// Lazily initialise frame state
|
|
75550
|
-
|
|
75685
|
+
auto prev_pos = state->pos;
|
|
75551
75686
|
state->SetPos(frame.second - frame.first);
|
|
75552
75687
|
|
|
75553
75688
|
auto index = state->w.data();
|
|
75554
75689
|
|
|
75555
|
-
|
|
75556
|
-
|
|
75557
|
-
|
|
75690
|
+
// We can generalise replacement for quantile lists by observing that when a replacement is
|
|
75691
|
+
// valid for a single quantile, it is valid for all quantiles greater/less than that quantile
|
|
75692
|
+
// based on whether the insertion is below/above the quantile location.
|
|
75693
|
+
// So if a replaced index in an IQR is located between Q25 and Q50, but has a value below Q25,
|
|
75694
|
+
// then Q25 must be recomputed, but Q50 and Q75 are unaffected.
|
|
75695
|
+
// For a single element list, this reduces to the scalar case.
|
|
75696
|
+
std::pair<idx_t, idx_t> replaceable {state->pos, 0};
|
|
75697
|
+
if (frame.first == prev.first + 1 && frame.second == prev.second + 1) {
|
|
75558
75698
|
// Fixed frame size
|
|
75559
|
-
j = ReplaceIndex(index, frame, prev);
|
|
75560
|
-
|
|
75699
|
+
const auto j = ReplaceIndex(index, frame, prev);
|
|
75700
|
+
// We can only replace if the number of NULLs has not changed
|
|
75701
|
+
if (dmask.AllValid() || not_null(prev.first) == not_null(prev.second)) {
|
|
75702
|
+
for (const auto &q : bind_data->order) {
|
|
75703
|
+
const auto &quantile = bind_data->quantiles[q];
|
|
75704
|
+
Interpolator<DISCRETE> interp(quantile, prev_pos);
|
|
75705
|
+
const auto replace = CanReplace(index, data, j, interp.FRN, interp.CRN, not_null);
|
|
75706
|
+
if (replace < 0) {
|
|
75707
|
+
// Replacement is before this quantile, so the rest will be replaceable too.
|
|
75708
|
+
replaceable.first = MinValue(replaceable.first, interp.FRN);
|
|
75709
|
+
replaceable.second = prev_pos;
|
|
75710
|
+
break;
|
|
75711
|
+
} else if (replace > 0) {
|
|
75712
|
+
// Replacement is after this quantile, so everything before it is replaceable too.
|
|
75713
|
+
replaceable.first = 0;
|
|
75714
|
+
replaceable.second = MaxValue(replaceable.second, interp.CRN);
|
|
75715
|
+
}
|
|
75716
|
+
}
|
|
75717
|
+
if (replaceable.first < replaceable.second) {
|
|
75718
|
+
state->pos = prev_pos;
|
|
75719
|
+
}
|
|
75720
|
+
}
|
|
75561
75721
|
} else {
|
|
75562
75722
|
ReuseIndexes(index, frame, prev);
|
|
75563
|
-
if (!dmask.AllValid()) {
|
|
75564
|
-
state->pos = std::partition(index, index + state->pos, not_null) - index;
|
|
75565
|
-
}
|
|
75566
75723
|
}
|
|
75567
75724
|
|
|
75568
|
-
if (!
|
|
75569
|
-
|
|
75570
|
-
|
|
75725
|
+
if (replaceable.first >= replaceable.second && !dmask.AllValid()) {
|
|
75726
|
+
// Remove the NULLs
|
|
75727
|
+
state->pos = std::partition(index, index + state->pos, not_null) - index;
|
|
75571
75728
|
}
|
|
75572
75729
|
|
|
75573
|
-
|
|
75574
|
-
|
|
75575
|
-
|
|
75576
|
-
|
|
75577
|
-
|
|
75578
|
-
|
|
75579
|
-
|
|
75580
|
-
|
|
75581
|
-
|
|
75582
|
-
|
|
75583
|
-
|
|
75584
|
-
|
|
75585
|
-
|
|
75586
|
-
|
|
75587
|
-
|
|
75588
|
-
|
|
75589
|
-
|
|
75730
|
+
if (state->pos) {
|
|
75731
|
+
using ID = QuantileIndirect<INPUT_TYPE>;
|
|
75732
|
+
ID indirect(data);
|
|
75733
|
+
for (const auto &q : bind_data->order) {
|
|
75734
|
+
const auto &quantile = bind_data->quantiles[q];
|
|
75735
|
+
Interpolator<DISCRETE> interp(quantile, state->pos);
|
|
75736
|
+
if (replaceable.first <= interp.FRN && interp.CRN <= replaceable.second) {
|
|
75737
|
+
rdata[lentry.offset + q] = interp.template Replace<idx_t, CHILD_TYPE, ID>(index, result, indirect);
|
|
75738
|
+
} else {
|
|
75739
|
+
// Make sure we don't disturb any replacements
|
|
75740
|
+
if (replaceable.first < replaceable.second) {
|
|
75741
|
+
if (interp.FRN < replaceable.first) {
|
|
75742
|
+
interp.end = replaceable.first;
|
|
75743
|
+
}
|
|
75744
|
+
if (replaceable.second < interp.CRN) {
|
|
75745
|
+
interp.begin = replaceable.second;
|
|
75746
|
+
}
|
|
75747
|
+
}
|
|
75748
|
+
rdata[lentry.offset + q] =
|
|
75749
|
+
interp.template Operation<idx_t, CHILD_TYPE, ID>(index, result, indirect);
|
|
75750
|
+
}
|
|
75590
75751
|
}
|
|
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);
|
|
75752
|
+
} else {
|
|
75753
|
+
lmask.Set(lidx, false);
|
|
75601
75754
|
}
|
|
75602
75755
|
}
|
|
75603
75756
|
};
|
|
@@ -75877,12 +76030,11 @@ struct MedianAbsoluteDeviationOperation : public QuantileOperation {
|
|
|
75877
76030
|
D_ASSERT(index);
|
|
75878
76031
|
|
|
75879
76032
|
// We need a second index for the second pass.
|
|
75880
|
-
|
|
75881
|
-
|
|
75882
|
-
state->disturbed.resize(state->pos);
|
|
76033
|
+
if (state->pos > state->m.size()) {
|
|
76034
|
+
state->m.resize(state->pos);
|
|
75883
76035
|
}
|
|
75884
76036
|
|
|
75885
|
-
auto index2 = state->
|
|
76037
|
+
auto index2 = state->m.data();
|
|
75886
76038
|
D_ASSERT(index2);
|
|
75887
76039
|
|
|
75888
76040
|
// The replacement trick does not work on the second index because if
|
|
@@ -76475,9 +76627,16 @@ struct MapFun {
|
|
|
76475
76627
|
struct MapExtractFun {
|
|
76476
76628
|
static void RegisterFunction(BuiltinFunctions &set);
|
|
76477
76629
|
};
|
|
76630
|
+
|
|
76478
76631
|
struct ListExtractFun {
|
|
76479
76632
|
static void RegisterFunction(BuiltinFunctions &set);
|
|
76480
76633
|
};
|
|
76634
|
+
|
|
76635
|
+
struct ListConcatFun {
|
|
76636
|
+
static ScalarFunction GetFunction();
|
|
76637
|
+
static void RegisterFunction(BuiltinFunctions &set);
|
|
76638
|
+
};
|
|
76639
|
+
|
|
76481
76640
|
struct CardinalityFun {
|
|
76482
76641
|
static void RegisterFunction(BuiltinFunctions &set);
|
|
76483
76642
|
};
|
|
@@ -83453,11 +83612,6 @@ void ArraySliceFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
83453
83612
|
|
|
83454
83613
|
|
|
83455
83614
|
|
|
83456
|
-
|
|
83457
|
-
|
|
83458
|
-
|
|
83459
|
-
|
|
83460
|
-
|
|
83461
83615
|
//===----------------------------------------------------------------------===//
|
|
83462
83616
|
// DuckDB
|
|
83463
83617
|
//
|
|
@@ -83497,6 +83651,147 @@ public:
|
|
|
83497
83651
|
|
|
83498
83652
|
|
|
83499
83653
|
|
|
83654
|
+
namespace duckdb {
|
|
83655
|
+
|
|
83656
|
+
static void ListConcatFunction(DataChunk &args, ExpressionState &state, Vector &result) {
|
|
83657
|
+
D_ASSERT(args.ColumnCount() == 2);
|
|
83658
|
+
auto count = args.size();
|
|
83659
|
+
|
|
83660
|
+
Vector &lhs = args.data[0];
|
|
83661
|
+
Vector &rhs = args.data[1];
|
|
83662
|
+
if (lhs.GetType().id() == LogicalTypeId::SQLNULL) {
|
|
83663
|
+
result.Reference(rhs);
|
|
83664
|
+
return;
|
|
83665
|
+
}
|
|
83666
|
+
if (rhs.GetType().id() == LogicalTypeId::SQLNULL) {
|
|
83667
|
+
result.Reference(lhs);
|
|
83668
|
+
return;
|
|
83669
|
+
}
|
|
83670
|
+
|
|
83671
|
+
VectorData lhs_data;
|
|
83672
|
+
VectorData rhs_data;
|
|
83673
|
+
lhs.Orrify(count, lhs_data);
|
|
83674
|
+
rhs.Orrify(count, rhs_data);
|
|
83675
|
+
auto lhs_entries = (list_entry_t *)lhs_data.data;
|
|
83676
|
+
auto rhs_entries = (list_entry_t *)rhs_data.data;
|
|
83677
|
+
|
|
83678
|
+
auto lhs_list_size = ListVector::GetListSize(lhs);
|
|
83679
|
+
auto rhs_list_size = ListVector::GetListSize(rhs);
|
|
83680
|
+
auto &lhs_child = ListVector::GetEntry(lhs);
|
|
83681
|
+
auto &rhs_child = ListVector::GetEntry(rhs);
|
|
83682
|
+
VectorData lhs_child_data;
|
|
83683
|
+
VectorData rhs_child_data;
|
|
83684
|
+
lhs_child.Orrify(lhs_list_size, lhs_child_data);
|
|
83685
|
+
rhs_child.Orrify(rhs_list_size, rhs_child_data);
|
|
83686
|
+
|
|
83687
|
+
result.SetVectorType(VectorType::FLAT_VECTOR);
|
|
83688
|
+
auto result_entries = FlatVector::GetData<list_entry_t>(result);
|
|
83689
|
+
auto &result_validity = FlatVector::Validity(result);
|
|
83690
|
+
|
|
83691
|
+
idx_t offset = 0;
|
|
83692
|
+
for (idx_t i = 0; i < count; i++) {
|
|
83693
|
+
auto lhs_list_index = lhs_data.sel->get_index(i);
|
|
83694
|
+
auto rhs_list_index = rhs_data.sel->get_index(i);
|
|
83695
|
+
if (!lhs_data.validity.RowIsValid(lhs_list_index) && !rhs_data.validity.RowIsValid(rhs_list_index)) {
|
|
83696
|
+
result_validity.SetInvalid(i);
|
|
83697
|
+
continue;
|
|
83698
|
+
}
|
|
83699
|
+
result_entries[i].offset = offset;
|
|
83700
|
+
result_entries[i].length = 0;
|
|
83701
|
+
if (lhs_data.validity.RowIsValid(lhs_list_index)) {
|
|
83702
|
+
const auto &lhs_entry = lhs_entries[lhs_list_index];
|
|
83703
|
+
result_entries[i].length += lhs_entry.length;
|
|
83704
|
+
ListVector::Append(result, lhs_child, *lhs_child_data.sel, lhs_entry.offset + lhs_entry.length,
|
|
83705
|
+
lhs_entry.offset);
|
|
83706
|
+
}
|
|
83707
|
+
if (rhs_data.validity.RowIsValid(rhs_list_index)) {
|
|
83708
|
+
const auto &rhs_entry = rhs_entries[rhs_list_index];
|
|
83709
|
+
result_entries[i].length += rhs_entry.length;
|
|
83710
|
+
ListVector::Append(result, rhs_child, *rhs_child_data.sel, rhs_entry.offset + rhs_entry.length,
|
|
83711
|
+
rhs_entry.offset);
|
|
83712
|
+
}
|
|
83713
|
+
offset += result_entries[i].length;
|
|
83714
|
+
}
|
|
83715
|
+
D_ASSERT(ListVector::GetListSize(result) == offset);
|
|
83716
|
+
|
|
83717
|
+
if (lhs.GetVectorType() == VectorType::CONSTANT_VECTOR && rhs.GetVectorType() == VectorType::CONSTANT_VECTOR) {
|
|
83718
|
+
result.SetVectorType(VectorType::CONSTANT_VECTOR);
|
|
83719
|
+
}
|
|
83720
|
+
}
|
|
83721
|
+
|
|
83722
|
+
static unique_ptr<FunctionData> ListConcatBind(ClientContext &context, ScalarFunction &bound_function,
|
|
83723
|
+
vector<unique_ptr<Expression>> &arguments) {
|
|
83724
|
+
D_ASSERT(bound_function.arguments.size() == 2);
|
|
83725
|
+
|
|
83726
|
+
auto &lhs = arguments[0]->return_type;
|
|
83727
|
+
auto &rhs = arguments[1]->return_type;
|
|
83728
|
+
if (lhs.id() == LogicalTypeId::SQLNULL && rhs.id() == LogicalTypeId::SQLNULL) {
|
|
83729
|
+
bound_function.return_type = LogicalType::SQLNULL;
|
|
83730
|
+
} else if (lhs.id() == LogicalTypeId::SQLNULL || rhs.id() == LogicalTypeId::SQLNULL) {
|
|
83731
|
+
// we mimic postgres behaviour: list_concat(NULL, my_list) = my_list
|
|
83732
|
+
bound_function.arguments[0] = lhs;
|
|
83733
|
+
bound_function.arguments[1] = rhs;
|
|
83734
|
+
bound_function.return_type = rhs.id() == LogicalTypeId::SQLNULL ? lhs : rhs;
|
|
83735
|
+
} else {
|
|
83736
|
+
D_ASSERT(lhs.id() == LogicalTypeId::LIST);
|
|
83737
|
+
D_ASSERT(rhs.id() == LogicalTypeId::LIST);
|
|
83738
|
+
|
|
83739
|
+
// Resolve list type
|
|
83740
|
+
auto child_type = LogicalType::SQLNULL;
|
|
83741
|
+
for (const auto &argument : arguments) {
|
|
83742
|
+
child_type = LogicalType::MaxLogicalType(child_type, ListType::GetChildType(argument->return_type));
|
|
83743
|
+
}
|
|
83744
|
+
ExpressionBinder::ResolveParameterType(child_type);
|
|
83745
|
+
auto list_type = LogicalType::LIST(move(child_type));
|
|
83746
|
+
|
|
83747
|
+
bound_function.arguments[0] = list_type;
|
|
83748
|
+
bound_function.arguments[1] = list_type;
|
|
83749
|
+
bound_function.return_type = list_type;
|
|
83750
|
+
}
|
|
83751
|
+
return make_unique<VariableReturnBindData>(bound_function.return_type);
|
|
83752
|
+
}
|
|
83753
|
+
|
|
83754
|
+
static unique_ptr<BaseStatistics> ListConcatStats(ClientContext &context, BoundFunctionExpression &expr,
|
|
83755
|
+
FunctionData *bind_data,
|
|
83756
|
+
vector<unique_ptr<BaseStatistics>> &child_stats) {
|
|
83757
|
+
D_ASSERT(child_stats.size() == 2);
|
|
83758
|
+
if (!child_stats[0] || !child_stats[1]) {
|
|
83759
|
+
return nullptr;
|
|
83760
|
+
}
|
|
83761
|
+
|
|
83762
|
+
auto &left_stats = (ListStatistics &)*child_stats[0];
|
|
83763
|
+
auto &right_stats = (ListStatistics &)*child_stats[1];
|
|
83764
|
+
|
|
83765
|
+
auto stats = left_stats.Copy();
|
|
83766
|
+
stats->Merge(right_stats);
|
|
83767
|
+
|
|
83768
|
+
return stats;
|
|
83769
|
+
}
|
|
83770
|
+
|
|
83771
|
+
ScalarFunction ListConcatFun::GetFunction() {
|
|
83772
|
+
// the arguments and return types are actually set in the binder function
|
|
83773
|
+
return ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::LIST(LogicalType::ANY)},
|
|
83774
|
+
LogicalType::LIST(LogicalType::ANY), ListConcatFunction, false, ListConcatBind, nullptr,
|
|
83775
|
+
ListConcatStats);
|
|
83776
|
+
}
|
|
83777
|
+
|
|
83778
|
+
void ListConcatFun::RegisterFunction(BuiltinFunctions &set) {
|
|
83779
|
+
set.AddFunction({"list_concat", "list_cat", "array_concat", "array_cat"}, GetFunction());
|
|
83780
|
+
}
|
|
83781
|
+
|
|
83782
|
+
} // namespace duckdb
|
|
83783
|
+
|
|
83784
|
+
|
|
83785
|
+
|
|
83786
|
+
|
|
83787
|
+
|
|
83788
|
+
|
|
83789
|
+
|
|
83790
|
+
|
|
83791
|
+
|
|
83792
|
+
|
|
83793
|
+
|
|
83794
|
+
|
|
83500
83795
|
namespace duckdb {
|
|
83501
83796
|
|
|
83502
83797
|
template <class T, bool HEAP_REF = false, bool VALIDITY_ONLY = false>
|
|
@@ -85465,6 +85760,7 @@ void BuiltinFunctions::RegisterNestedFunctions() {
|
|
|
85465
85760
|
Register<ArraySliceFun>();
|
|
85466
85761
|
Register<StructPackFun>();
|
|
85467
85762
|
Register<StructExtractFun>();
|
|
85763
|
+
Register<ListConcatFun>();
|
|
85468
85764
|
Register<ListValueFun>();
|
|
85469
85765
|
Register<ListExtractFun>();
|
|
85470
85766
|
Register<ListRangeFun>();
|
|
@@ -85811,6 +86107,7 @@ struct BitwiseNotFun {
|
|
|
85811
86107
|
|
|
85812
86108
|
|
|
85813
86109
|
|
|
86110
|
+
|
|
85814
86111
|
#include <limits>
|
|
85815
86112
|
|
|
85816
86113
|
namespace duckdb {
|
|
@@ -86126,6 +86423,8 @@ void AddFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
86126
86423
|
|
|
86127
86424
|
functions.AddFunction(GetFunction(LogicalType::TIMESTAMP, LogicalType::INTERVAL));
|
|
86128
86425
|
functions.AddFunction(GetFunction(LogicalType::INTERVAL, LogicalType::TIMESTAMP));
|
|
86426
|
+
// we can add lists together
|
|
86427
|
+
functions.AddFunction(ListConcatFun::GetFunction());
|
|
86129
86428
|
|
|
86130
86429
|
set.AddFunction(functions);
|
|
86131
86430
|
}
|
|
@@ -87708,6 +88007,7 @@ void CHR::RegisterFunction(BuiltinFunctions &set) {
|
|
|
87708
88007
|
|
|
87709
88008
|
|
|
87710
88009
|
|
|
88010
|
+
|
|
87711
88011
|
#include <string.h>
|
|
87712
88012
|
|
|
87713
88013
|
namespace duckdb {
|
|
@@ -87953,6 +88253,7 @@ void ConcatFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
87953
88253
|
concat_op.AddFunction(
|
|
87954
88254
|
ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::VARCHAR, ConcatOperator));
|
|
87955
88255
|
concat_op.AddFunction(ScalarFunction({LogicalType::BLOB, LogicalType::BLOB}, LogicalType::BLOB, ConcatOperator));
|
|
88256
|
+
concat_op.AddFunction(ListConcatFun::GetFunction());
|
|
87956
88257
|
set.AddFunction(concat_op);
|
|
87957
88258
|
|
|
87958
88259
|
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 "9fd34ad70"
|
|
14
|
+
#define DUCKDB_VERSION "0.3.1-dev517"
|
|
15
15
|
//===----------------------------------------------------------------------===//
|
|
16
16
|
// DuckDB
|
|
17
17
|
//
|
|
@@ -5957,6 +5957,8 @@ template <>
|
|
|
5957
5957
|
bool Hugeint::TryCast(hugeint_t input, float &result);
|
|
5958
5958
|
template <>
|
|
5959
5959
|
bool Hugeint::TryCast(hugeint_t input, double &result);
|
|
5960
|
+
template <>
|
|
5961
|
+
bool Hugeint::TryCast(hugeint_t input, long double &result);
|
|
5960
5962
|
|
|
5961
5963
|
template <>
|
|
5962
5964
|
bool Hugeint::TryConvert(int8_t value, hugeint_t &result);
|
|
@@ -5978,6 +5980,8 @@ template <>
|
|
|
5978
5980
|
bool Hugeint::TryConvert(float value, hugeint_t &result);
|
|
5979
5981
|
template <>
|
|
5980
5982
|
bool Hugeint::TryConvert(double value, hugeint_t &result);
|
|
5983
|
+
template <>
|
|
5984
|
+
bool Hugeint::TryConvert(long double value, hugeint_t &result);
|
|
5981
5985
|
|
|
5982
5986
|
} // namespace duckdb
|
|
5983
5987
|
|