duckdb 0.3.3-dev1226.0 → 0.3.3-dev1229.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.3-dev1226.0",
4
+ "version": "0.3.3-dev1229.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -26367,17 +26367,20 @@ template <class OP, bool NO_MATCH_SEL>
26367
26367
  static void TemplatedMatchNested(Vector &col, Vector &rows, const idx_t vcount, SelectionVector &sel, idx_t &count,
26368
26368
  const idx_t col_offset, const idx_t col_no, SelectionVector *no_match,
26369
26369
  idx_t &no_match_count) {
26370
- // Gather a scattered Vector containing the column values being matched
26370
+ // Gather a dense Vector containing the column values being matched
26371
26371
  Vector key(col.GetType());
26372
- RowOperations::Gather(rows, sel, key, sel, count, col_offset, col_no);
26372
+ RowOperations::Gather(rows, sel, key, *FlatVector::IncrementalSelectionVector(), count, col_offset, col_no);
26373
+
26374
+ // Densify the input column
26375
+ Vector sliced(col, sel, count);
26373
26376
 
26374
26377
  if (NO_MATCH_SEL) {
26375
26378
  SelectionVector no_match_sel_offset(no_match->data() + no_match_count);
26376
- auto match_count = SelectComparison<OP>(col, key, vcount, sel, count, &sel, &no_match_sel_offset);
26379
+ auto match_count = SelectComparison<OP>(sliced, key, count, sel, count, &sel, &no_match_sel_offset);
26377
26380
  no_match_count += count - match_count;
26378
26381
  count = match_count;
26379
26382
  } else {
26380
- count = SelectComparison<OP>(col, key, vcount, sel, count, &sel, nullptr);
26383
+ count = SelectComparison<OP>(sliced, key, count, sel, count, &sel, nullptr);
26381
26384
  }
26382
26385
  }
26383
26386
 
@@ -43436,9 +43439,13 @@ static idx_t DistinctSelect(Vector &left, Vector &right, idx_t vcount, const Sel
43436
43439
  }
43437
43440
 
43438
43441
  template <class OP>
43439
- static idx_t DistinctSelectNotNull(VectorData &lvdata, VectorData &rvdata, const idx_t count, idx_t &true_count,
43440
- const SelectionVector &sel, SelectionVector &maybe_vec, OptionalSelection &true_vec,
43441
- OptionalSelection &false_vec) {
43442
+ static idx_t DistinctSelectNotNull(Vector &left, Vector &right, const idx_t count, idx_t &true_count,
43443
+ const SelectionVector &sel, SelectionVector &maybe_vec, OptionalSelection &true_opt,
43444
+ OptionalSelection &false_opt) {
43445
+ VectorData lvdata, rvdata;
43446
+ left.Orrify(count, lvdata);
43447
+ right.Orrify(count, rvdata);
43448
+
43442
43449
  auto &lmask = lvdata.validity;
43443
43450
  auto &rmask = rvdata.validity;
43444
43451
 
@@ -43452,39 +43459,39 @@ static idx_t DistinctSelectNotNull(VectorData &lvdata, VectorData &rvdata, const
43452
43459
  return remaining;
43453
43460
  }
43454
43461
 
43462
+ // Slice the Vectors down to the rows that are not determined (i.e., neither is NULL)
43463
+ SelectionVector slicer(count);
43464
+ true_count = 0;
43455
43465
  idx_t false_count = 0;
43456
43466
  for (idx_t i = 0; i < count; ++i) {
43457
- const auto idx = sel.get_index(i);
43458
- const auto lidx = lvdata.sel->get_index(idx);
43459
- const auto ridx = rvdata.sel->get_index(idx);
43467
+ const auto result_idx = sel.get_index(i);
43468
+ const auto lidx = lvdata.sel->get_index(i);
43469
+ const auto ridx = rvdata.sel->get_index(i);
43460
43470
  const auto lnull = !lmask.RowIsValid(lidx);
43461
43471
  const auto rnull = !rmask.RowIsValid(ridx);
43462
43472
  if (lnull || rnull) {
43463
43473
  // If either is NULL then we can major distinguish them
43464
43474
  if (!OP::Operation(false, false, lnull, rnull)) {
43465
- false_vec.Append(false_count, idx);
43475
+ false_opt.Append(false_count, result_idx);
43466
43476
  } else {
43467
- true_vec.Append(true_count, idx);
43477
+ true_opt.Append(true_count, result_idx);
43468
43478
  }
43469
43479
  } else {
43470
43480
  // Neither is NULL, distinguish values.
43471
- maybe_vec.set_index(remaining++, idx);
43481
+ slicer.set_index(remaining, i);
43482
+ maybe_vec.set_index(remaining++, result_idx);
43472
43483
  }
43473
43484
  }
43474
- true_vec.Advance(true_count);
43475
- false_vec.Advance(false_count);
43476
43485
 
43477
- return remaining;
43478
- }
43486
+ true_opt.Advance(true_count);
43487
+ false_opt.Advance(false_count);
43479
43488
 
43480
- template <bool DENSE>
43481
- static inline void ScatterSelection(SelectionVector *target, const idx_t count, const SelectionVector &sel,
43482
- const SelectionVector &dense_vec) {
43483
- if (DENSE && target) {
43484
- for (idx_t i = 0; i < count; ++i) {
43485
- target->set_index(i, sel.get_index(dense_vec.get_index(i)));
43486
- }
43489
+ if (remaining && remaining < count) {
43490
+ left.Slice(slicer, remaining);
43491
+ right.Slice(slicer, remaining);
43487
43492
  }
43493
+
43494
+ return remaining;
43488
43495
  }
43489
43496
 
43490
43497
  struct PositionComparator {
@@ -43616,26 +43623,70 @@ static StructEntries &StructVectorGetSlicedEntries(Vector &parent, StructEntries
43616
43623
  return children;
43617
43624
  }
43618
43625
 
43626
+ static void ExtractNestedSelection(const SelectionVector &slice_sel, const idx_t count, const SelectionVector &sel,
43627
+ OptionalSelection &opt) {
43628
+
43629
+ for (idx_t i = 0; i < count;) {
43630
+ const auto slice_idx = slice_sel.get_index(i);
43631
+ const auto result_idx = sel.get_index(slice_idx);
43632
+ opt.Append(i, result_idx);
43633
+ }
43634
+ opt.Advance(count);
43635
+ }
43636
+
43637
+ static void DensifyNestedSelection(const SelectionVector &dense_sel, const idx_t count, SelectionVector &slice_sel) {
43638
+ for (idx_t i = 0; i < count; ++i) {
43639
+ slice_sel.set_index(i, dense_sel.get_index(i));
43640
+ }
43641
+ }
43642
+
43619
43643
  template <class OP>
43620
- static idx_t DistinctSelectStruct(Vector &left, Vector &right, idx_t vcount, VectorData &lvdata, VectorData &rvdata,
43621
- idx_t count, SelectionVector &maybe_vec, OptionalSelection &true_opt,
43622
- OptionalSelection &false_opt) {
43644
+ static idx_t DistinctSelectStruct(Vector &left, Vector &right, idx_t count, const SelectionVector &sel,
43645
+ OptionalSelection &true_opt, OptionalSelection &false_opt) {
43646
+ if (count == 0) {
43647
+ return 0;
43648
+ }
43649
+
43623
43650
  // Avoid allocating in the 99% of the cases where we don't need to.
43624
43651
  StructEntries lsliced, rsliced;
43625
- auto &lchildren = StructVectorGetSlicedEntries(left, lsliced, vcount);
43626
- auto &rchildren = StructVectorGetSlicedEntries(right, rsliced, vcount);
43652
+ auto &lchildren = StructVectorGetSlicedEntries(left, lsliced, count);
43653
+ auto &rchildren = StructVectorGetSlicedEntries(right, rsliced, count);
43627
43654
  D_ASSERT(lchildren.size() == rchildren.size());
43628
43655
 
43656
+ // In order to reuse the comparators, we have to track what passed and failed internally.
43657
+ // To do that, we need local SVs that we then merge back into the real ones after every pass.
43658
+ const auto vcount = count;
43659
+ SelectionVector slice_sel(count);
43660
+ for (idx_t i = 0; i < count; ++i) {
43661
+ slice_sel.set_index(i, i);
43662
+ }
43663
+
43664
+ SelectionVector true_sel(count);
43665
+ SelectionVector false_sel(count);
43666
+
43629
43667
  idx_t match_count = 0;
43630
43668
  for (idx_t col_no = 0; col_no < lchildren.size(); ++col_no) {
43631
- auto &lchild = *lchildren[col_no];
43632
- auto &rchild = *rchildren[col_no];
43669
+ // Slice the children to maintain density
43670
+ Vector lchild(*lchildren[col_no]);
43671
+ lchild.Normalify(vcount);
43672
+ lchild.Slice(slice_sel, count);
43673
+
43674
+ Vector rchild(*rchildren[col_no]);
43675
+ rchild.Normalify(vcount);
43676
+ rchild.Slice(slice_sel, count);
43633
43677
 
43634
43678
  // Find everything that definitely matches
43635
43679
  auto true_count =
43636
- PositionComparator::Definite<OP>(lchild, rchild, vcount, maybe_vec, count, true_opt, maybe_vec);
43680
+ PositionComparator::Definite<OP>(lchild, rchild, count, slice_sel, count, &true_sel, false_sel);
43637
43681
  if (true_count > 0) {
43638
- true_opt.Advance(true_count);
43682
+ auto false_count = count - true_count;
43683
+
43684
+ // Extract the definite matches into the true result
43685
+ ExtractNestedSelection(false_count ? true_sel : slice_sel, true_count, sel, true_opt);
43686
+
43687
+ // Remove the definite matches from the slicing vector
43688
+ DensifyNestedSelection(false_sel, false_count, slice_sel);
43689
+
43639
43690
  match_count += true_count;
43640
43691
  count -= true_count;
43641
43692
  }
@@ -43643,12 +43694,28 @@ static idx_t DistinctSelectStruct(Vector &left, Vector &right, idx_t vcount, Vec
43643
43694
  if (col_no != lchildren.size() - 1) {
43644
43695
  // Find what might match on the next position
43645
43696
  true_count =
43646
- PositionComparator::Possible<OP>(lchild, rchild, vcount, maybe_vec, count, maybe_vec, false_opt);
43697
+ PositionComparator::Possible<OP>(lchild, rchild, count, slice_sel, count, true_sel, &false_sel);
43647
43698
  auto false_count = count - true_count;
43648
- false_opt.Advance(false_count);
43699
+
43700
+ // Extract the definite failures into the false result
43701
+ ExtractNestedSelection(true_count ? false_sel : slice_sel, false_count, sel, false_opt);
43702
+
43703
+ // Remove any definite failures from the slicing vector
43704
+ if (false_count) {
43705
+ DensifyNestedSelection(true_sel, true_count, slice_sel);
43706
+ }
43707
+
43649
43708
  count = true_count;
43650
43709
  } else {
43651
- true_count = PositionComparator::Final<OP>(lchild, rchild, vcount, maybe_vec, count, true_opt, false_opt);
43710
+ true_count = PositionComparator::Final<OP>(lchild, rchild, count, slice_sel, count, &true_sel, &false_sel);
43711
+ auto false_count = count - true_count;
43712
+
43713
+ // Extract the definite matches into the true result
43714
+ ExtractNestedSelection(false_count ? true_sel : slice_sel, true_count, sel, true_opt);
43715
+
43716
+ // Extract the definite failures into the false result
43717
+ ExtractNestedSelection(true_count ? false_sel : slice_sel, false_count, sel, false_opt);
43718
+
43652
43719
  match_count += true_count;
43653
43720
  }
43654
43721
  }
@@ -43657,28 +43724,27 @@ static idx_t DistinctSelectStruct(Vector &left, Vector &right, idx_t vcount, Vec
43657
43724
  }
43658
43725
 
43659
43726
  static void PositionListCursor(SelectionVector &cursor, VectorData &vdata, const idx_t pos,
43660
- const SelectionVector &maybe_vec, const idx_t count) {
43727
+ const SelectionVector &slice_sel, const idx_t count) {
43661
43728
  const auto data = (const list_entry_t *)vdata.data;
43662
43729
  for (idx_t i = 0; i < count; ++i) {
43663
- const auto idx = maybe_vec.get_index(i);
43730
+ const auto slice_idx = slice_sel.get_index(i);
43664
43731
 
43665
- const auto lidx = vdata.sel->get_index(idx);
43732
+ const auto lidx = vdata.sel->get_index(slice_idx);
43666
43733
  const auto &entry = data[lidx];
43667
- cursor.set_index(idx, entry.offset + pos);
43734
+ cursor.set_index(i, entry.offset + pos);
43668
43735
  }
43669
43736
  }
43670
43737
 
43671
43738
  template <class OP>
43672
- static idx_t DistinctSelectList(Vector &left, Vector &right, idx_t vcount, VectorData &lvdata, VectorData &rvdata,
43673
- idx_t count, SelectionVector &maybe_vec, OptionalSelection &true_opt,
43674
- OptionalSelection &false_opt) {
43739
+ static idx_t DistinctSelectList(Vector &left, Vector &right, idx_t count, const SelectionVector &sel,
43740
+ OptionalSelection &true_opt, OptionalSelection &false_opt) {
43675
43741
  if (count == 0) {
43676
43742
  return count;
43677
43743
  }
43678
43744
 
43679
- // We use them to create dictionary views of the children so we can vectorise the positional comparisons.
43680
- SelectionVector lcursor(vcount);
43681
- SelectionVector rcursor(vcount);
43745
+ // Create dictionary views of the children so we can vectorise the positional comparisons.
43746
+ SelectionVector lcursor(count);
43747
+ SelectionVector rcursor(count);
43682
43748
 
43683
43749
  Vector lchild(ListVector::GetEntry(left), lcursor, count);
43684
43750
  Vector rchild(ListVector::GetEntry(right), rcursor, count);
@@ -43696,105 +43762,137 @@ static idx_t DistinctSelectList(Vector &left, Vector &right, idx_t vcount, Vecto
43696
43762
  // ++left, ++right;
43697
43763
  // }
43698
43764
  // }
43765
+
43766
+ // Get pointers to the list entries
43767
+ VectorData lvdata;
43768
+ left.Orrify(count, lvdata);
43699
43769
  const auto ldata = (const list_entry_t *)lvdata.data;
43770
+
43771
+ VectorData rvdata;
43772
+ right.Orrify(count, rvdata);
43700
43773
  const auto rdata = (const list_entry_t *)rvdata.data;
43701
43774
 
43775
+ // In order to reuse the comparators, we have to track what passed and failed internally.
43776
+ // To do that, we need local SVs that we then merge back into the real ones after every pass.
43777
+ SelectionVector slice_sel(count);
43778
+ for (idx_t i = 0; i < count; ++i) {
43779
+ slice_sel.set_index(i, i);
43780
+ }
43781
+
43782
+ SelectionVector true_sel(count);
43783
+ SelectionVector false_sel(count);
43784
+
43702
43785
  idx_t match_count = 0;
43703
43786
  for (idx_t pos = 0; count > 0; ++pos) {
43704
43787
  // Set up the cursors for the current position
43705
- PositionListCursor(lcursor, lvdata, pos, maybe_vec, count);
43706
- PositionListCursor(rcursor, rvdata, pos, maybe_vec, count);
43788
+ PositionListCursor(lcursor, lvdata, pos, slice_sel, count);
43789
+ PositionListCursor(rcursor, rvdata, pos, slice_sel, count);
43707
43790
 
43708
43791
  // Tie-break the pairs where one of the LISTs is exhausted.
43709
43792
  idx_t true_count = 0;
43710
43793
  idx_t false_count = 0;
43711
43794
  idx_t maybe_count = 0;
43712
43795
  for (idx_t i = 0; i < count; ++i) {
43713
- const auto idx = maybe_vec.get_index(i);
43714
- const auto lidx = lvdata.sel->get_index(idx);
43796
+ const auto slice_idx = slice_sel.get_index(i);
43797
+ const auto lidx = lvdata.sel->get_index(slice_idx);
43715
43798
  const auto &lentry = ldata[lidx];
43716
- const auto ridx = rvdata.sel->get_index(idx);
43799
+ const auto ridx = rvdata.sel->get_index(slice_idx);
43717
43800
  const auto &rentry = rdata[ridx];
43718
43801
  if (lentry.length == pos || rentry.length == pos) {
43802
+ const auto idx = sel.get_index(slice_idx);
43719
43803
  if (PositionComparator::TieBreak<OP>(lentry.length, rentry.length)) {
43720
43804
  true_opt.Append(true_count, idx);
43721
43805
  } else {
43722
43806
  false_opt.Append(false_count, idx);
43723
43807
  }
43724
43808
  } else {
43725
- maybe_vec.set_index(maybe_count++, idx);
43809
+ true_sel.set_index(maybe_count++, slice_idx);
43726
43810
  }
43727
43811
  }
43728
43812
  true_opt.Advance(true_count);
43729
43813
  false_opt.Advance(false_count);
43730
- count = maybe_count;
43731
43814
  match_count += true_count;
43732
43815
 
43816
+ // Redensify the list cursors
43817
+ if (maybe_count < count) {
43818
+ count = maybe_count;
43819
+ DensifyNestedSelection(true_sel, count, slice_sel);
43820
+ PositionListCursor(lcursor, lvdata, pos, slice_sel, count);
43821
+ PositionListCursor(rcursor, rvdata, pos, slice_sel, count);
43822
+ }
43823
+
43733
43824
  // Find everything that definitely matches
43734
- true_count = PositionComparator::Definite<OP>(lchild, rchild, vcount, maybe_vec, count, true_opt, maybe_vec);
43735
- true_opt.Advance(true_count);
43736
- match_count += true_count;
43737
- count -= true_count;
43825
+ true_count = PositionComparator::Definite<OP>(lchild, rchild, count, slice_sel, count, &true_sel, false_sel);
43826
+ if (true_count) {
43827
+ false_count = count - true_count;
43828
+ ExtractNestedSelection(false_count ? true_sel : slice_sel, true_count, sel, true_opt);
43829
+ match_count += true_count;
43830
+
43831
+ // Redensify the list cursors
43832
+ count -= true_count;
43833
+ DensifyNestedSelection(false_sel, count, slice_sel);
43834
+ PositionListCursor(lcursor, lvdata, pos, slice_sel, count);
43835
+ PositionListCursor(rcursor, rvdata, pos, slice_sel, count);
43836
+ }
43738
43837
 
43739
43838
  // Find what might match on the next position
43740
- maybe_count = PositionComparator::Possible<OP>(lchild, rchild, vcount, maybe_vec, count, maybe_vec, false_opt);
43741
- false_count = count - maybe_count;
43742
- false_opt.Advance(false_count);
43743
- count = maybe_count;
43839
+ true_count = PositionComparator::Possible<OP>(lchild, rchild, count, slice_sel, count, true_sel, &false_sel);
43840
+ false_count = count - true_count;
43841
+ ExtractNestedSelection(true_count ? false_sel : slice_sel, false_count, sel, false_opt);
43842
+
43843
+ if (false_count) {
43844
+ DensifyNestedSelection(true_sel, true_count, slice_sel);
43845
+ }
43846
+ count = true_count;
43744
43847
  }
43745
43848
 
43746
43849
  return match_count;
43747
43850
  }
43748
43851
 
43749
- template <class OP, bool DENSE, class OPNESTED>
43750
- static idx_t DistinctSelectNested(Vector &left, Vector &right, idx_t vcount, const SelectionVector *sel, idx_t count,
43852
+ template <class OP, class OPNESTED>
43853
+ static idx_t DistinctSelectNested(Vector &left, Vector &right, const SelectionVector *sel, const idx_t count,
43751
43854
  SelectionVector *true_sel, SelectionVector *false_sel) {
43752
- // We need multiple, real selections
43855
+ // The Select operations all use a dense pair of input vectors to partition
43856
+ // a selection vector in a single pass. But to implement progressive comparisons,
43857
+ // we have to make multiple passes, so we need to keep track of the original input positions
43858
+ // and then scatter the output selections when we are done.
43753
43859
  SelectionVector owned_sel;
43754
43860
  if (!sel) {
43755
43861
  sel = FlatVector::IncrementalSelectionVector(count, owned_sel);
43756
43862
  }
43757
43863
 
43758
- SelectionVector true_vec;
43759
- SelectionVector false_vec;
43760
- if (DENSE) {
43761
- true_vec.Initialize(vcount);
43762
- false_vec.Initialize(vcount);
43763
- }
43864
+ // Make buffered selections for progressive comparisons
43865
+ // TODO: Remove unnecessary allocations
43866
+ SelectionVector true_vec(count);
43867
+ OptionalSelection true_opt(&true_vec);
43764
43868
 
43765
- OptionalSelection true_opt(DENSE ? &true_vec : true_sel);
43766
- OptionalSelection false_opt(DENSE ? &false_vec : false_sel);
43869
+ SelectionVector false_vec(count);
43870
+ OptionalSelection false_opt(&false_vec);
43767
43871
 
43768
- // Handle NULL STRUCTs
43769
- VectorData lvdata, rvdata;
43770
- left.Orrify(vcount, lvdata);
43771
- right.Orrify(vcount, rvdata);
43872
+ SelectionVector maybe_vec(count);
43873
+
43874
+ // Handle NULL nested values
43875
+ Vector l_not_null(left);
43876
+ Vector r_not_null(right);
43772
43877
 
43773
- sel_t maybe_one;
43774
- SelectionVector maybe_vec(&maybe_one);
43775
- if (count > 1) {
43776
- maybe_vec.Initialize(count);
43777
- }
43778
43878
  idx_t match_count = 0;
43779
- idx_t no_match_count = count;
43780
- count = DistinctSelectNotNull<OP>(lvdata, rvdata, count, match_count, *sel, maybe_vec, true_opt, false_opt);
43781
- no_match_count -= (count + match_count);
43879
+ auto unknown =
43880
+ DistinctSelectNotNull<OP>(l_not_null, r_not_null, count, match_count, *sel, maybe_vec, true_opt, false_opt);
43782
43881
 
43783
- idx_t true_count = 0;
43784
43882
  if (PhysicalType::LIST == left.GetType().InternalType()) {
43785
- true_count =
43786
- DistinctSelectList<OPNESTED>(left, right, vcount, lvdata, rvdata, count, maybe_vec, true_opt, false_opt);
43883
+ match_count += DistinctSelectList<OPNESTED>(l_not_null, r_not_null, unknown, maybe_vec, true_opt, false_opt);
43787
43884
  } else {
43788
- true_count =
43789
- DistinctSelectStruct<OPNESTED>(left, right, vcount, lvdata, rvdata, count, maybe_vec, true_opt, false_opt);
43885
+ match_count += DistinctSelectStruct<OPNESTED>(l_not_null, r_not_null, unknown, maybe_vec, true_opt, false_opt);
43790
43886
  }
43791
43887
 
43792
- auto false_count = count - true_count;
43793
- match_count += true_count;
43794
- no_match_count += false_count;
43888
+ // Copy the buffered selections to the output selections
43889
+ if (true_sel) {
43890
+ DensifyNestedSelection(true_vec, match_count, *true_sel);
43891
+ }
43795
43892
 
43796
- ScatterSelection<DENSE>(true_sel, match_count, *sel, true_vec);
43797
- ScatterSelection<DENSE>(false_sel, no_match_count, *sel, false_vec);
43893
+ if (false_sel) {
43894
+ DensifyNestedSelection(false_vec, count - match_count, *false_sel);
43895
+ }
43798
43896
 
43799
43897
  return match_count;
43800
43898
  }
@@ -43896,7 +43994,7 @@ static idx_t TemplatedDistinctSelectOperation(Vector &left, Vector &right, idx_t
43896
43994
  case PhysicalType::MAP:
43897
43995
  case PhysicalType::STRUCT:
43898
43996
  case PhysicalType::LIST:
43899
- return DistinctSelectNested<OP, DENSE, OPNESTED>(left, right, vcount, sel, count, true_sel, false_sel);
43997
+ return DistinctSelectNested<OP, OPNESTED>(left, right, sel, count, true_sel, false_sel);
43900
43998
  default:
43901
43999
  throw InternalException("Invalid type for distinct selection");
43902
44000
  }
@@ -44004,38 +44102,38 @@ idx_t VectorOperations::DistinctLessThanEquals(Vector &left, Vector &right, cons
44004
44102
  // true := A != B with nulls being equal, inputs selected
44005
44103
  idx_t VectorOperations::NestedNotEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
44006
44104
  idx_t count, SelectionVector *true_sel, SelectionVector *false_sel) {
44007
- return TemplatedDistinctSelectOperation<duckdb::DistinctFrom, false>(left, right, vcount, &sel, count, true_sel,
44008
- false_sel);
44105
+ return TemplatedDistinctSelectOperation<duckdb::DistinctFrom, true>(left, right, vcount, &sel, count, true_sel,
44106
+ false_sel);
44009
44107
  }
44010
44108
  // true := A == B with nulls being equal, inputs selected
44011
44109
  idx_t VectorOperations::NestedEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel, idx_t count,
44012
44110
  SelectionVector *true_sel, SelectionVector *false_sel) {
44013
- return TemplatedDistinctSelectOperation<duckdb::NotDistinctFrom, false>(left, right, vcount, &sel, count, true_sel,
44014
- false_sel);
44111
+ return TemplatedDistinctSelectOperation<duckdb::NotDistinctFrom, true>(left, right, vcount, &sel, count, true_sel,
44112
+ false_sel);
44015
44113
  }
44016
44114
  // true := A > B with nulls being maximal, inputs selected
44017
44115
  idx_t VectorOperations::NestedGreaterThan(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
44018
44116
  idx_t count, SelectionVector *true_sel, SelectionVector *false_sel) {
44019
- return TemplatedDistinctSelectOperation<duckdb::DistinctGreaterThan, false>(left, right, vcount, &sel, count,
44020
- true_sel, false_sel);
44117
+ return TemplatedDistinctSelectOperation<duckdb::DistinctGreaterThan, true>(left, right, vcount, &sel, count,
44118
+ true_sel, false_sel);
44021
44119
  }
44022
44120
  // true := A >= B with nulls being maximal, inputs selected
44023
44121
  idx_t VectorOperations::NestedGreaterThanEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
44024
44122
  idx_t count, SelectionVector *true_sel, SelectionVector *false_sel) {
44025
- return TemplatedDistinctSelectOperation<duckdb::DistinctGreaterThanEquals, false>(left, right, vcount, &sel, count,
44026
- true_sel, false_sel);
44123
+ return TemplatedDistinctSelectOperation<duckdb::DistinctGreaterThanEquals, true>(left, right, vcount, &sel, count,
44124
+ true_sel, false_sel);
44027
44125
  }
44028
44126
  // true := A < B with nulls being maximal, inputs selected
44029
44127
  idx_t VectorOperations::NestedLessThan(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
44030
44128
  idx_t count, SelectionVector *true_sel, SelectionVector *false_sel) {
44031
- return TemplatedDistinctSelectOperation<duckdb::DistinctLessThan, false>(left, right, vcount, &sel, count, true_sel,
44032
- false_sel);
44129
+ return TemplatedDistinctSelectOperation<duckdb::DistinctLessThan, true>(left, right, vcount, &sel, count, true_sel,
44130
+ false_sel);
44033
44131
  }
44034
44132
  // true := A <= B with nulls being maximal, inputs selected
44035
44133
  idx_t VectorOperations::NestedLessThanEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
44036
44134
  idx_t count, SelectionVector *true_sel, SelectionVector *false_sel) {
44037
- return TemplatedDistinctSelectOperation<duckdb::DistinctLessThanEquals, false>(left, right, vcount, &sel, count,
44038
- true_sel, false_sel);
44135
+ return TemplatedDistinctSelectOperation<duckdb::DistinctLessThanEquals, true>(left, right, vcount, &sel, count,
44136
+ true_sel, false_sel);
44039
44137
  }
44040
44138
 
44041
44139
  } // namespace duckdb
@@ -48171,45 +48269,63 @@ idx_t NestedSelector::Select<duckdb::GreaterThanEquals>(Vector &left, Vector &ri
48171
48269
  return VectorOperations::NestedGreaterThanEquals(left, right, vcount, sel, count, true_sel, false_sel);
48172
48270
  }
48173
48271
 
48174
- static inline idx_t SelectNotNull(VectorData &lvdata, VectorData &rvdata, const idx_t count,
48175
- OptionalSelection &false_vec, SelectionVector &maybe_vec) {
48272
+ static inline idx_t SelectNotNull(Vector &left, Vector &right, const idx_t count, const SelectionVector &sel,
48273
+ SelectionVector &maybe_vec, OptionalSelection &false_opt) {
48274
+
48275
+ VectorData lvdata, rvdata;
48276
+ left.Orrify(count, lvdata);
48277
+ right.Orrify(count, rvdata);
48278
+
48279
+ auto &lmask = lvdata.validity;
48280
+ auto &rmask = rvdata.validity;
48176
48281
 
48177
48282
  // For top-level comparisons, NULL semantics are in effect,
48178
48283
  // so filter out any NULLs
48179
- if (!lvdata.validity.AllValid() || !rvdata.validity.AllValid()) {
48180
- idx_t true_count = 0;
48181
- idx_t false_count = 0;
48284
+ idx_t remaining = 0;
48285
+ if (lmask.AllValid() && rmask.AllValid()) {
48286
+ // None are NULL, distinguish values.
48182
48287
  for (idx_t i = 0; i < count; ++i) {
48183
- const auto lidx = lvdata.sel->get_index(i);
48184
- const auto ridx = rvdata.sel->get_index(i);
48185
- if (!lvdata.validity.RowIsValid(lidx) || !rvdata.validity.RowIsValid(ridx)) {
48186
- false_vec.Append(false_count, i);
48187
- } else {
48188
- maybe_vec.set_index(true_count++, i);
48189
- }
48288
+ const auto idx = sel.get_index(i);
48289
+ maybe_vec.set_index(remaining++, idx);
48190
48290
  }
48191
- false_vec.Advance(false_count);
48291
+ return remaining;
48292
+ }
48192
48293
 
48193
- return true_count;
48194
- } else {
48195
- for (idx_t i = 0; i < count; ++i) {
48196
- maybe_vec.set_index(i, i);
48294
+ // Slice the Vectors down to the rows that are not determined (i.e., neither is NULL)
48295
+ SelectionVector slicer(count);
48296
+ idx_t false_count = 0;
48297
+ for (idx_t i = 0; i < count; ++i) {
48298
+ const auto result_idx = sel.get_index(i);
48299
+ const auto lidx = lvdata.sel->get_index(i);
48300
+ const auto ridx = rvdata.sel->get_index(i);
48301
+ if (!lmask.RowIsValid(lidx) || !rmask.RowIsValid(ridx)) {
48302
+ false_opt.Append(false_count, result_idx);
48303
+ } else {
48304
+ // Neither is NULL, distinguish values.
48305
+ slicer.set_index(remaining, i);
48306
+ maybe_vec.set_index(remaining++, result_idx);
48197
48307
  }
48198
- return count;
48199
48308
  }
48309
+ false_opt.Advance(false_count);
48310
+
48311
+ if (remaining && remaining < count) {
48312
+ left.Slice(slicer, remaining);
48313
+ right.Slice(slicer, remaining);
48314
+ }
48315
+
48316
+ return remaining;
48200
48317
  }
48201
48318
 
48202
- static void ScatterSelection(SelectionVector *target, const idx_t count, const SelectionVector *sel,
48203
- const SelectionVector &dense_vec) {
48319
+ static void ScatterSelection(SelectionVector *target, const idx_t count, const SelectionVector &dense_vec) {
48204
48320
  if (target) {
48205
48321
  for (idx_t i = 0; i < count; ++i) {
48206
- target->set_index(i, sel->get_index(dense_vec.get_index(i)));
48322
+ target->set_index(i, dense_vec.get_index(i));
48207
48323
  }
48208
48324
  }
48209
48325
  }
48210
48326
 
48211
48327
  template <typename OP>
48212
- static idx_t NestedSelectOperation(Vector &left, Vector &right, const SelectionVector *sel, idx_t vcount,
48328
+ static idx_t NestedSelectOperation(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
48213
48329
  SelectionVector *true_sel, SelectionVector *false_sel) {
48214
48330
  // The Select operations all use a dense pair of input vectors to partition
48215
48331
  // a selection vector in a single pass. But to implement progressive comparisons,
@@ -48217,47 +48333,34 @@ static idx_t NestedSelectOperation(Vector &left, Vector &right, const SelectionV
48217
48333
  // and then scatter the output selections when we are done.
48218
48334
  SelectionVector owned_sel;
48219
48335
  if (!sel) {
48220
- sel = FlatVector::IncrementalSelectionVector(vcount, owned_sel);
48336
+ sel = FlatVector::IncrementalSelectionVector(count, owned_sel);
48221
48337
  }
48222
48338
 
48223
- VectorData lvdata, rvdata;
48224
- left.Orrify(vcount, lvdata);
48225
- right.Orrify(vcount, rvdata);
48226
-
48227
- // Make real selections for progressive comparisons
48228
- SelectionVector true_vec(vcount);
48339
+ // Make buffered selections for progressive comparisons
48340
+ // TODO: Remove unnecessary allocations
48341
+ SelectionVector true_vec(count);
48229
48342
  OptionalSelection true_opt(&true_vec);
48230
48343
 
48231
- SelectionVector false_vec(vcount);
48344
+ SelectionVector false_vec(count);
48232
48345
  OptionalSelection false_opt(&false_vec);
48233
48346
 
48234
- SelectionVector maybe_vec(vcount);
48235
- auto count = SelectNotNull(lvdata, rvdata, vcount, false_opt, maybe_vec);
48236
- auto no_match_count = vcount - count;
48347
+ SelectionVector maybe_vec(count);
48237
48348
 
48238
- // If everything was NULL, fill in false_sel with sel
48239
- if (count == 0) {
48240
- SelectionVector owned_flat_sel;
48241
- auto flat_sel = FlatVector::IncrementalSelectionVector(vcount, owned_sel);
48242
- ScatterSelection(false_sel, no_match_count, sel, *flat_sel);
48243
- return count;
48244
- }
48349
+ // Handle NULL nested values
48350
+ Vector l_not_null(left);
48351
+ Vector r_not_null(right);
48352
+
48353
+ auto match_count = SelectNotNull(l_not_null, r_not_null, count, *sel, maybe_vec, false_opt);
48354
+ auto no_match_count = count - match_count;
48355
+ count = match_count;
48245
48356
 
48246
48357
  // Now that we have handled the NULLs, we can use the recursive nested comparator for the rest.
48247
- auto match_count = NestedSelector::Select<OP>(left, right, vcount, maybe_vec, count, true_opt, false_opt);
48358
+ match_count = NestedSelector::Select<OP>(l_not_null, r_not_null, count, maybe_vec, count, true_opt, false_opt);
48248
48359
  no_match_count += (count - match_count);
48249
48360
 
48250
- // Sort the optional selections if we would overwrite.
48251
- if (true_sel == sel) {
48252
- std::sort(true_vec.data(), true_vec.data() + match_count);
48253
- }
48254
- if (false_sel == sel) {
48255
- std::sort(false_vec.data(), false_vec.data() + no_match_count);
48256
- }
48257
-
48258
- // Scatter the original selection to the output selections
48259
- ScatterSelection(true_sel, match_count, sel, true_vec);
48260
- ScatterSelection(false_sel, no_match_count, sel, false_vec);
48361
+ // Copy the buffered selections to the output selections
48362
+ ScatterSelection(true_sel, match_count, true_vec);
48363
+ ScatterSelection(false_sel, no_match_count, false_vec);
48261
48364
 
48262
48365
  return match_count;
48263
48366
  }