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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
- "version": "0.3.1-dev501.0",
4
+ "version": "0.3.1-dev517.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
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
- {nullptr, nullptr, {nullptr}, nullptr}};
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 Hugeint::TryCast(hugeint_t input, double &result) {
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 = -double(NumericLimits<uint64_t>::Maximum() - input.lower) - 1;
35958
+ result = -REAL_T(NumericLimits<uint64_t>::Maximum() - input.lower) - 1;
35955
35959
  break;
35956
35960
  default:
35957
- result = double(input.lower) + double(input.upper) * double(NumericLimits<uint64_t>::Maximum());
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 Hugeint::TryConvert(double value, hugeint_t &result) {
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, double(NumericLimits<uint64_t>::Maximum()));
36030
- result.upper = (uint64_t)(value / double(NumericLimits<uint64_t>::Maximum()));
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->count = 0;
70782
+ state->Initialize();
70682
70783
  }
70683
70784
  template <class STATE>
70684
70785
  static void Combine(const STATE &source, STATE *target) {
70685
- target->count += source.count;
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
- static double GetAverageDivident(uint64_t count, FunctionData *bind_data) {
70695
- double divident = double(count);
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->isset = false;
73606
+ state->Initialize();
73493
73607
  }
73494
73608
  template <class STATE>
73495
73609
  static void Combine(const STATE &source, STATE *target) {
73496
- target->isset = source.isset || target->isset;
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
- struct NumericSumOperation : public BaseSumOperation<SumSetOperation, RegularAdd> {
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 Aggregation
75094
+ // Windowed Quantile indirection
74967
75095
  std::vector<idx_t> w;
74968
75096
  idx_t pos;
74969
75097
 
74970
- // List temporaries
74971
- std::vector<idx_t> disturbed;
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 bool CanReplace(const idx_t *index, const INPUT_TYPE *fdata, const idx_t j, const idx_t k0,
75056
- const idx_t k1, const QuantileNotNull &validity) {
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 can replace NULLs
75062
- // and NULLs are at the end, so we only have to check the first one
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
- const auto ik0 = index[k0];
75065
- const auto ik1 = index[k1];
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[ik0];
75075
- replace = hi < curr;
75195
+ auto hi = fdata[index[k0]];
75196
+ return hi < curr ? 1 : 0;
75076
75197
  } else if (j < k0) {
75077
- auto lo = fdata[ik1];
75078
- replace = curr < lo;
75198
+ auto lo = fdata[index[k1]];
75199
+ return curr < lo ? -1 : 0;
75079
75200
  }
75080
75201
 
75081
- return replace;
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) : n(n_p), RN((double)(n_p - 1) * q), FRN(floor(RN)), CRN(ceil(RN)) {
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 + n, comp);
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 + n, comp);
75210
- std::nth_element(v_t + FRN, v_t + CRN, v_t + n, comp);
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) : n(n_p), RN((double)(n_p - 1) * q), FRN(floor(RN)), CRN(FRN) {
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 + n, comp);
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
- ListVector::SetListSize(result, 0);
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 NULls has not changed
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].offset = ridx;
75519
- for (const auto &quantile : bind_data->quantiles) {
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
- rdata[ridx] = interp.template Operation<typename STATE::SaveType, CHILD_TYPE>(v_t, result);
75522
- ++ridx;
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
- target[idx].length = bind_data->quantiles.size();
75659
+ entry.length = bind_data->quantiles.size();
75525
75660
 
75526
- ListVector::SetListSize(result_list, ridx);
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
- const auto prev_valid = state->w.size() == (prev.second - prev.first);
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
- bool fixed = false;
75556
- auto j = state->pos;
75557
- if (prev_valid && dmask.AllValid() && frame.first == prev.first + 1 && frame.second == prev.second + 1) {
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
- fixed = true;
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 (!state->pos) {
75569
- lmask.Set(lidx, false);
75570
- return;
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
- // First pass: Fill in the undisturbed values and find the islands of stability.
75574
- QuantileIndirect<INPUT_TYPE> indirect(data);
75575
- state->disturbed.clear();
75576
- state->lower.clear();
75577
- state->upper.clear();
75578
- idx_t lb = 0;
75579
- for (idx_t i = 0; i < bind_data->order.size(); ++i) {
75580
- const auto q = bind_data->order[i];
75581
- const auto &quantile = bind_data->quantiles[q];
75582
- Interpolator<DISCRETE> interp(quantile, state->pos);
75583
-
75584
- if (fixed && CanReplace(index, data, j, interp.FRN, interp.CRN, not_null)) {
75585
- rdata[lentry.offset + q] = interp.template Replace<idx_t, CHILD_TYPE>(index, result, indirect);
75586
- state->upper.resize(state->lower.size(), interp.FRN);
75587
- } else {
75588
- state->disturbed.push_back(q);
75589
- state->lower.push_back(MinValue(lb, interp.FRN));
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
- lb = interp.CRN + 1;
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
- // so repurpose disturbed as the second index.
75881
- if (state->pos > state->disturbed.size()) {
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->disturbed.data();
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 "fbeb407d4"
14
- #define DUCKDB_VERSION "0.3.1-dev501"
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