duckdb 0.3.3-dev1226.0 → 0.3.3-dev1251.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/src/duckdb.cpp CHANGED
@@ -5307,15 +5307,19 @@ int ResultArrowArrayStreamWrapper::MyStreamGetNext(struct ArrowArrayStream *stre
5307
5307
  out->release = nullptr;
5308
5308
  return 0;
5309
5309
  }
5310
- while (chunk_result->size() < my_stream->batch_size) {
5310
+ unique_ptr<DataChunk> agg_chunk_result = make_unique<DataChunk>();
5311
+ agg_chunk_result->Initialize(chunk_result->GetTypes());
5312
+ agg_chunk_result->Append(*chunk_result, true);
5313
+
5314
+ while (agg_chunk_result->size() < my_stream->batch_size) {
5311
5315
  auto new_chunk = result.Fetch();
5312
5316
  if (!new_chunk) {
5313
5317
  break;
5314
5318
  } else {
5315
- chunk_result->Append(*new_chunk, true);
5319
+ agg_chunk_result->Append(*new_chunk, true);
5316
5320
  }
5317
5321
  }
5318
- chunk_result->ToArrowArray(out);
5322
+ agg_chunk_result->ToArrowArray(out);
5319
5323
  return 0;
5320
5324
  }
5321
5325
 
@@ -26367,17 +26371,20 @@ template <class OP, bool NO_MATCH_SEL>
26367
26371
  static void TemplatedMatchNested(Vector &col, Vector &rows, const idx_t vcount, SelectionVector &sel, idx_t &count,
26368
26372
  const idx_t col_offset, const idx_t col_no, SelectionVector *no_match,
26369
26373
  idx_t &no_match_count) {
26370
- // Gather a scattered Vector containing the column values being matched
26374
+ // Gather a dense Vector containing the column values being matched
26371
26375
  Vector key(col.GetType());
26372
- RowOperations::Gather(rows, sel, key, sel, count, col_offset, col_no);
26376
+ RowOperations::Gather(rows, sel, key, *FlatVector::IncrementalSelectionVector(), count, col_offset, col_no);
26377
+
26378
+ // Densify the input column
26379
+ Vector sliced(col, sel, count);
26373
26380
 
26374
26381
  if (NO_MATCH_SEL) {
26375
26382
  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);
26383
+ auto match_count = SelectComparison<OP>(sliced, key, count, sel, count, &sel, &no_match_sel_offset);
26377
26384
  no_match_count += count - match_count;
26378
26385
  count = match_count;
26379
26386
  } else {
26380
- count = SelectComparison<OP>(col, key, vcount, sel, count, &sel, nullptr);
26387
+ count = SelectComparison<OP>(sliced, key, count, sel, count, &sel, nullptr);
26381
26388
  }
26382
26389
  }
26383
26390
 
@@ -43436,9 +43443,13 @@ static idx_t DistinctSelect(Vector &left, Vector &right, idx_t vcount, const Sel
43436
43443
  }
43437
43444
 
43438
43445
  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) {
43446
+ static idx_t DistinctSelectNotNull(Vector &left, Vector &right, const idx_t count, idx_t &true_count,
43447
+ const SelectionVector &sel, SelectionVector &maybe_vec, OptionalSelection &true_opt,
43448
+ OptionalSelection &false_opt) {
43449
+ VectorData lvdata, rvdata;
43450
+ left.Orrify(count, lvdata);
43451
+ right.Orrify(count, rvdata);
43452
+
43442
43453
  auto &lmask = lvdata.validity;
43443
43454
  auto &rmask = rvdata.validity;
43444
43455
 
@@ -43452,39 +43463,39 @@ static idx_t DistinctSelectNotNull(VectorData &lvdata, VectorData &rvdata, const
43452
43463
  return remaining;
43453
43464
  }
43454
43465
 
43466
+ // Slice the Vectors down to the rows that are not determined (i.e., neither is NULL)
43467
+ SelectionVector slicer(count);
43468
+ true_count = 0;
43455
43469
  idx_t false_count = 0;
43456
43470
  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);
43471
+ const auto result_idx = sel.get_index(i);
43472
+ const auto lidx = lvdata.sel->get_index(i);
43473
+ const auto ridx = rvdata.sel->get_index(i);
43460
43474
  const auto lnull = !lmask.RowIsValid(lidx);
43461
43475
  const auto rnull = !rmask.RowIsValid(ridx);
43462
43476
  if (lnull || rnull) {
43463
43477
  // If either is NULL then we can major distinguish them
43464
43478
  if (!OP::Operation(false, false, lnull, rnull)) {
43465
- false_vec.Append(false_count, idx);
43479
+ false_opt.Append(false_count, result_idx);
43466
43480
  } else {
43467
- true_vec.Append(true_count, idx);
43481
+ true_opt.Append(true_count, result_idx);
43468
43482
  }
43469
43483
  } else {
43470
43484
  // Neither is NULL, distinguish values.
43471
- maybe_vec.set_index(remaining++, idx);
43485
+ slicer.set_index(remaining, i);
43486
+ maybe_vec.set_index(remaining++, result_idx);
43472
43487
  }
43473
43488
  }
43474
- true_vec.Advance(true_count);
43475
- false_vec.Advance(false_count);
43476
43489
 
43477
- return remaining;
43478
- }
43490
+ true_opt.Advance(true_count);
43491
+ false_opt.Advance(false_count);
43479
43492
 
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
- }
43493
+ if (remaining && remaining < count) {
43494
+ left.Slice(slicer, remaining);
43495
+ right.Slice(slicer, remaining);
43487
43496
  }
43497
+
43498
+ return remaining;
43488
43499
  }
43489
43500
 
43490
43501
  struct PositionComparator {
@@ -43616,26 +43627,70 @@ static StructEntries &StructVectorGetSlicedEntries(Vector &parent, StructEntries
43616
43627
  return children;
43617
43628
  }
43618
43629
 
43630
+ static void ExtractNestedSelection(const SelectionVector &slice_sel, const idx_t count, const SelectionVector &sel,
43631
+ OptionalSelection &opt) {
43632
+
43633
+ for (idx_t i = 0; i < count;) {
43634
+ const auto slice_idx = slice_sel.get_index(i);
43635
+ const auto result_idx = sel.get_index(slice_idx);
43636
+ opt.Append(i, result_idx);
43637
+ }
43638
+ opt.Advance(count);
43639
+ }
43640
+
43641
+ static void DensifyNestedSelection(const SelectionVector &dense_sel, const idx_t count, SelectionVector &slice_sel) {
43642
+ for (idx_t i = 0; i < count; ++i) {
43643
+ slice_sel.set_index(i, dense_sel.get_index(i));
43644
+ }
43645
+ }
43646
+
43619
43647
  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) {
43648
+ static idx_t DistinctSelectStruct(Vector &left, Vector &right, idx_t count, const SelectionVector &sel,
43649
+ OptionalSelection &true_opt, OptionalSelection &false_opt) {
43650
+ if (count == 0) {
43651
+ return 0;
43652
+ }
43653
+
43623
43654
  // Avoid allocating in the 99% of the cases where we don't need to.
43624
43655
  StructEntries lsliced, rsliced;
43625
- auto &lchildren = StructVectorGetSlicedEntries(left, lsliced, vcount);
43626
- auto &rchildren = StructVectorGetSlicedEntries(right, rsliced, vcount);
43656
+ auto &lchildren = StructVectorGetSlicedEntries(left, lsliced, count);
43657
+ auto &rchildren = StructVectorGetSlicedEntries(right, rsliced, count);
43627
43658
  D_ASSERT(lchildren.size() == rchildren.size());
43628
43659
 
43660
+ // In order to reuse the comparators, we have to track what passed and failed internally.
43661
+ // To do that, we need local SVs that we then merge back into the real ones after every pass.
43662
+ const auto vcount = count;
43663
+ SelectionVector slice_sel(count);
43664
+ for (idx_t i = 0; i < count; ++i) {
43665
+ slice_sel.set_index(i, i);
43666
+ }
43667
+
43668
+ SelectionVector true_sel(count);
43669
+ SelectionVector false_sel(count);
43670
+
43629
43671
  idx_t match_count = 0;
43630
43672
  for (idx_t col_no = 0; col_no < lchildren.size(); ++col_no) {
43631
- auto &lchild = *lchildren[col_no];
43632
- auto &rchild = *rchildren[col_no];
43673
+ // Slice the children to maintain density
43674
+ Vector lchild(*lchildren[col_no]);
43675
+ lchild.Normalify(vcount);
43676
+ lchild.Slice(slice_sel, count);
43677
+
43678
+ Vector rchild(*rchildren[col_no]);
43679
+ rchild.Normalify(vcount);
43680
+ rchild.Slice(slice_sel, count);
43633
43681
 
43634
43682
  // Find everything that definitely matches
43635
43683
  auto true_count =
43636
- PositionComparator::Definite<OP>(lchild, rchild, vcount, maybe_vec, count, true_opt, maybe_vec);
43684
+ PositionComparator::Definite<OP>(lchild, rchild, count, slice_sel, count, &true_sel, false_sel);
43637
43685
  if (true_count > 0) {
43638
- true_opt.Advance(true_count);
43686
+ auto false_count = count - true_count;
43687
+
43688
+ // Extract the definite matches into the true result
43689
+ ExtractNestedSelection(false_count ? true_sel : slice_sel, true_count, sel, true_opt);
43690
+
43691
+ // Remove the definite matches from the slicing vector
43692
+ DensifyNestedSelection(false_sel, false_count, slice_sel);
43693
+
43639
43694
  match_count += true_count;
43640
43695
  count -= true_count;
43641
43696
  }
@@ -43643,12 +43698,28 @@ static idx_t DistinctSelectStruct(Vector &left, Vector &right, idx_t vcount, Vec
43643
43698
  if (col_no != lchildren.size() - 1) {
43644
43699
  // Find what might match on the next position
43645
43700
  true_count =
43646
- PositionComparator::Possible<OP>(lchild, rchild, vcount, maybe_vec, count, maybe_vec, false_opt);
43701
+ PositionComparator::Possible<OP>(lchild, rchild, count, slice_sel, count, true_sel, &false_sel);
43647
43702
  auto false_count = count - true_count;
43648
- false_opt.Advance(false_count);
43703
+
43704
+ // Extract the definite failures into the false result
43705
+ ExtractNestedSelection(true_count ? false_sel : slice_sel, false_count, sel, false_opt);
43706
+
43707
+ // Remove any definite failures from the slicing vector
43708
+ if (false_count) {
43709
+ DensifyNestedSelection(true_sel, true_count, slice_sel);
43710
+ }
43711
+
43649
43712
  count = true_count;
43650
43713
  } else {
43651
- true_count = PositionComparator::Final<OP>(lchild, rchild, vcount, maybe_vec, count, true_opt, false_opt);
43714
+ true_count = PositionComparator::Final<OP>(lchild, rchild, count, slice_sel, count, &true_sel, &false_sel);
43715
+ auto false_count = count - true_count;
43716
+
43717
+ // Extract the definite matches into the true result
43718
+ ExtractNestedSelection(false_count ? true_sel : slice_sel, true_count, sel, true_opt);
43719
+
43720
+ // Extract the definite failures into the false result
43721
+ ExtractNestedSelection(true_count ? false_sel : slice_sel, false_count, sel, false_opt);
43722
+
43652
43723
  match_count += true_count;
43653
43724
  }
43654
43725
  }
@@ -43657,28 +43728,27 @@ static idx_t DistinctSelectStruct(Vector &left, Vector &right, idx_t vcount, Vec
43657
43728
  }
43658
43729
 
43659
43730
  static void PositionListCursor(SelectionVector &cursor, VectorData &vdata, const idx_t pos,
43660
- const SelectionVector &maybe_vec, const idx_t count) {
43731
+ const SelectionVector &slice_sel, const idx_t count) {
43661
43732
  const auto data = (const list_entry_t *)vdata.data;
43662
43733
  for (idx_t i = 0; i < count; ++i) {
43663
- const auto idx = maybe_vec.get_index(i);
43734
+ const auto slice_idx = slice_sel.get_index(i);
43664
43735
 
43665
- const auto lidx = vdata.sel->get_index(idx);
43736
+ const auto lidx = vdata.sel->get_index(slice_idx);
43666
43737
  const auto &entry = data[lidx];
43667
- cursor.set_index(idx, entry.offset + pos);
43738
+ cursor.set_index(i, entry.offset + pos);
43668
43739
  }
43669
43740
  }
43670
43741
 
43671
43742
  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) {
43743
+ static idx_t DistinctSelectList(Vector &left, Vector &right, idx_t count, const SelectionVector &sel,
43744
+ OptionalSelection &true_opt, OptionalSelection &false_opt) {
43675
43745
  if (count == 0) {
43676
43746
  return count;
43677
43747
  }
43678
43748
 
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);
43749
+ // Create dictionary views of the children so we can vectorise the positional comparisons.
43750
+ SelectionVector lcursor(count);
43751
+ SelectionVector rcursor(count);
43682
43752
 
43683
43753
  Vector lchild(ListVector::GetEntry(left), lcursor, count);
43684
43754
  Vector rchild(ListVector::GetEntry(right), rcursor, count);
@@ -43696,105 +43766,137 @@ static idx_t DistinctSelectList(Vector &left, Vector &right, idx_t vcount, Vecto
43696
43766
  // ++left, ++right;
43697
43767
  // }
43698
43768
  // }
43769
+
43770
+ // Get pointers to the list entries
43771
+ VectorData lvdata;
43772
+ left.Orrify(count, lvdata);
43699
43773
  const auto ldata = (const list_entry_t *)lvdata.data;
43774
+
43775
+ VectorData rvdata;
43776
+ right.Orrify(count, rvdata);
43700
43777
  const auto rdata = (const list_entry_t *)rvdata.data;
43701
43778
 
43779
+ // In order to reuse the comparators, we have to track what passed and failed internally.
43780
+ // To do that, we need local SVs that we then merge back into the real ones after every pass.
43781
+ SelectionVector slice_sel(count);
43782
+ for (idx_t i = 0; i < count; ++i) {
43783
+ slice_sel.set_index(i, i);
43784
+ }
43785
+
43786
+ SelectionVector true_sel(count);
43787
+ SelectionVector false_sel(count);
43788
+
43702
43789
  idx_t match_count = 0;
43703
43790
  for (idx_t pos = 0; count > 0; ++pos) {
43704
43791
  // Set up the cursors for the current position
43705
- PositionListCursor(lcursor, lvdata, pos, maybe_vec, count);
43706
- PositionListCursor(rcursor, rvdata, pos, maybe_vec, count);
43792
+ PositionListCursor(lcursor, lvdata, pos, slice_sel, count);
43793
+ PositionListCursor(rcursor, rvdata, pos, slice_sel, count);
43707
43794
 
43708
43795
  // Tie-break the pairs where one of the LISTs is exhausted.
43709
43796
  idx_t true_count = 0;
43710
43797
  idx_t false_count = 0;
43711
43798
  idx_t maybe_count = 0;
43712
43799
  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);
43800
+ const auto slice_idx = slice_sel.get_index(i);
43801
+ const auto lidx = lvdata.sel->get_index(slice_idx);
43715
43802
  const auto &lentry = ldata[lidx];
43716
- const auto ridx = rvdata.sel->get_index(idx);
43803
+ const auto ridx = rvdata.sel->get_index(slice_idx);
43717
43804
  const auto &rentry = rdata[ridx];
43718
43805
  if (lentry.length == pos || rentry.length == pos) {
43806
+ const auto idx = sel.get_index(slice_idx);
43719
43807
  if (PositionComparator::TieBreak<OP>(lentry.length, rentry.length)) {
43720
43808
  true_opt.Append(true_count, idx);
43721
43809
  } else {
43722
43810
  false_opt.Append(false_count, idx);
43723
43811
  }
43724
43812
  } else {
43725
- maybe_vec.set_index(maybe_count++, idx);
43813
+ true_sel.set_index(maybe_count++, slice_idx);
43726
43814
  }
43727
43815
  }
43728
43816
  true_opt.Advance(true_count);
43729
43817
  false_opt.Advance(false_count);
43730
- count = maybe_count;
43731
43818
  match_count += true_count;
43732
43819
 
43820
+ // Redensify the list cursors
43821
+ if (maybe_count < count) {
43822
+ count = maybe_count;
43823
+ DensifyNestedSelection(true_sel, count, slice_sel);
43824
+ PositionListCursor(lcursor, lvdata, pos, slice_sel, count);
43825
+ PositionListCursor(rcursor, rvdata, pos, slice_sel, count);
43826
+ }
43827
+
43733
43828
  // 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;
43829
+ true_count = PositionComparator::Definite<OP>(lchild, rchild, count, slice_sel, count, &true_sel, false_sel);
43830
+ if (true_count) {
43831
+ false_count = count - true_count;
43832
+ ExtractNestedSelection(false_count ? true_sel : slice_sel, true_count, sel, true_opt);
43833
+ match_count += true_count;
43834
+
43835
+ // Redensify the list cursors
43836
+ count -= true_count;
43837
+ DensifyNestedSelection(false_sel, count, slice_sel);
43838
+ PositionListCursor(lcursor, lvdata, pos, slice_sel, count);
43839
+ PositionListCursor(rcursor, rvdata, pos, slice_sel, count);
43840
+ }
43738
43841
 
43739
43842
  // 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;
43843
+ true_count = PositionComparator::Possible<OP>(lchild, rchild, count, slice_sel, count, true_sel, &false_sel);
43844
+ false_count = count - true_count;
43845
+ ExtractNestedSelection(true_count ? false_sel : slice_sel, false_count, sel, false_opt);
43846
+
43847
+ if (false_count) {
43848
+ DensifyNestedSelection(true_sel, true_count, slice_sel);
43849
+ }
43850
+ count = true_count;
43744
43851
  }
43745
43852
 
43746
43853
  return match_count;
43747
43854
  }
43748
43855
 
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,
43856
+ template <class OP, class OPNESTED>
43857
+ static idx_t DistinctSelectNested(Vector &left, Vector &right, const SelectionVector *sel, const idx_t count,
43751
43858
  SelectionVector *true_sel, SelectionVector *false_sel) {
43752
- // We need multiple, real selections
43859
+ // The Select operations all use a dense pair of input vectors to partition
43860
+ // a selection vector in a single pass. But to implement progressive comparisons,
43861
+ // we have to make multiple passes, so we need to keep track of the original input positions
43862
+ // and then scatter the output selections when we are done.
43753
43863
  SelectionVector owned_sel;
43754
43864
  if (!sel) {
43755
43865
  sel = FlatVector::IncrementalSelectionVector(count, owned_sel);
43756
43866
  }
43757
43867
 
43758
- SelectionVector true_vec;
43759
- SelectionVector false_vec;
43760
- if (DENSE) {
43761
- true_vec.Initialize(vcount);
43762
- false_vec.Initialize(vcount);
43763
- }
43868
+ // Make buffered selections for progressive comparisons
43869
+ // TODO: Remove unnecessary allocations
43870
+ SelectionVector true_vec(count);
43871
+ OptionalSelection true_opt(&true_vec);
43764
43872
 
43765
- OptionalSelection true_opt(DENSE ? &true_vec : true_sel);
43766
- OptionalSelection false_opt(DENSE ? &false_vec : false_sel);
43873
+ SelectionVector false_vec(count);
43874
+ OptionalSelection false_opt(&false_vec);
43767
43875
 
43768
- // Handle NULL STRUCTs
43769
- VectorData lvdata, rvdata;
43770
- left.Orrify(vcount, lvdata);
43771
- right.Orrify(vcount, rvdata);
43876
+ SelectionVector maybe_vec(count);
43877
+
43878
+ // Handle NULL nested values
43879
+ Vector l_not_null(left);
43880
+ Vector r_not_null(right);
43772
43881
 
43773
- sel_t maybe_one;
43774
- SelectionVector maybe_vec(&maybe_one);
43775
- if (count > 1) {
43776
- maybe_vec.Initialize(count);
43777
- }
43778
43882
  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);
43883
+ auto unknown =
43884
+ DistinctSelectNotNull<OP>(l_not_null, r_not_null, count, match_count, *sel, maybe_vec, true_opt, false_opt);
43782
43885
 
43783
- idx_t true_count = 0;
43784
43886
  if (PhysicalType::LIST == left.GetType().InternalType()) {
43785
- true_count =
43786
- DistinctSelectList<OPNESTED>(left, right, vcount, lvdata, rvdata, count, maybe_vec, true_opt, false_opt);
43887
+ match_count += DistinctSelectList<OPNESTED>(l_not_null, r_not_null, unknown, maybe_vec, true_opt, false_opt);
43787
43888
  } else {
43788
- true_count =
43789
- DistinctSelectStruct<OPNESTED>(left, right, vcount, lvdata, rvdata, count, maybe_vec, true_opt, false_opt);
43889
+ match_count += DistinctSelectStruct<OPNESTED>(l_not_null, r_not_null, unknown, maybe_vec, true_opt, false_opt);
43790
43890
  }
43791
43891
 
43792
- auto false_count = count - true_count;
43793
- match_count += true_count;
43794
- no_match_count += false_count;
43892
+ // Copy the buffered selections to the output selections
43893
+ if (true_sel) {
43894
+ DensifyNestedSelection(true_vec, match_count, *true_sel);
43895
+ }
43795
43896
 
43796
- ScatterSelection<DENSE>(true_sel, match_count, *sel, true_vec);
43797
- ScatterSelection<DENSE>(false_sel, no_match_count, *sel, false_vec);
43897
+ if (false_sel) {
43898
+ DensifyNestedSelection(false_vec, count - match_count, *false_sel);
43899
+ }
43798
43900
 
43799
43901
  return match_count;
43800
43902
  }
@@ -43896,7 +43998,7 @@ static idx_t TemplatedDistinctSelectOperation(Vector &left, Vector &right, idx_t
43896
43998
  case PhysicalType::MAP:
43897
43999
  case PhysicalType::STRUCT:
43898
44000
  case PhysicalType::LIST:
43899
- return DistinctSelectNested<OP, DENSE, OPNESTED>(left, right, vcount, sel, count, true_sel, false_sel);
44001
+ return DistinctSelectNested<OP, OPNESTED>(left, right, sel, count, true_sel, false_sel);
43900
44002
  default:
43901
44003
  throw InternalException("Invalid type for distinct selection");
43902
44004
  }
@@ -44004,38 +44106,38 @@ idx_t VectorOperations::DistinctLessThanEquals(Vector &left, Vector &right, cons
44004
44106
  // true := A != B with nulls being equal, inputs selected
44005
44107
  idx_t VectorOperations::NestedNotEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
44006
44108
  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);
44109
+ return TemplatedDistinctSelectOperation<duckdb::DistinctFrom, true>(left, right, vcount, &sel, count, true_sel,
44110
+ false_sel);
44009
44111
  }
44010
44112
  // true := A == B with nulls being equal, inputs selected
44011
44113
  idx_t VectorOperations::NestedEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel, idx_t count,
44012
44114
  SelectionVector *true_sel, SelectionVector *false_sel) {
44013
- return TemplatedDistinctSelectOperation<duckdb::NotDistinctFrom, false>(left, right, vcount, &sel, count, true_sel,
44014
- false_sel);
44115
+ return TemplatedDistinctSelectOperation<duckdb::NotDistinctFrom, true>(left, right, vcount, &sel, count, true_sel,
44116
+ false_sel);
44015
44117
  }
44016
44118
  // true := A > B with nulls being maximal, inputs selected
44017
44119
  idx_t VectorOperations::NestedGreaterThan(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
44018
44120
  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);
44121
+ return TemplatedDistinctSelectOperation<duckdb::DistinctGreaterThan, true>(left, right, vcount, &sel, count,
44122
+ true_sel, false_sel);
44021
44123
  }
44022
44124
  // true := A >= B with nulls being maximal, inputs selected
44023
44125
  idx_t VectorOperations::NestedGreaterThanEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
44024
44126
  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);
44127
+ return TemplatedDistinctSelectOperation<duckdb::DistinctGreaterThanEquals, true>(left, right, vcount, &sel, count,
44128
+ true_sel, false_sel);
44027
44129
  }
44028
44130
  // true := A < B with nulls being maximal, inputs selected
44029
44131
  idx_t VectorOperations::NestedLessThan(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
44030
44132
  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);
44133
+ return TemplatedDistinctSelectOperation<duckdb::DistinctLessThan, true>(left, right, vcount, &sel, count, true_sel,
44134
+ false_sel);
44033
44135
  }
44034
44136
  // true := A <= B with nulls being maximal, inputs selected
44035
44137
  idx_t VectorOperations::NestedLessThanEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
44036
44138
  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);
44139
+ return TemplatedDistinctSelectOperation<duckdb::DistinctLessThanEquals, true>(left, right, vcount, &sel, count,
44140
+ true_sel, false_sel);
44039
44141
  }
44040
44142
 
44041
44143
  } // namespace duckdb
@@ -48171,45 +48273,63 @@ idx_t NestedSelector::Select<duckdb::GreaterThanEquals>(Vector &left, Vector &ri
48171
48273
  return VectorOperations::NestedGreaterThanEquals(left, right, vcount, sel, count, true_sel, false_sel);
48172
48274
  }
48173
48275
 
48174
- static inline idx_t SelectNotNull(VectorData &lvdata, VectorData &rvdata, const idx_t count,
48175
- OptionalSelection &false_vec, SelectionVector &maybe_vec) {
48276
+ static inline idx_t SelectNotNull(Vector &left, Vector &right, const idx_t count, const SelectionVector &sel,
48277
+ SelectionVector &maybe_vec, OptionalSelection &false_opt) {
48278
+
48279
+ VectorData lvdata, rvdata;
48280
+ left.Orrify(count, lvdata);
48281
+ right.Orrify(count, rvdata);
48282
+
48283
+ auto &lmask = lvdata.validity;
48284
+ auto &rmask = rvdata.validity;
48176
48285
 
48177
48286
  // For top-level comparisons, NULL semantics are in effect,
48178
48287
  // 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;
48288
+ idx_t remaining = 0;
48289
+ if (lmask.AllValid() && rmask.AllValid()) {
48290
+ // None are NULL, distinguish values.
48182
48291
  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
- }
48292
+ const auto idx = sel.get_index(i);
48293
+ maybe_vec.set_index(remaining++, idx);
48190
48294
  }
48191
- false_vec.Advance(false_count);
48295
+ return remaining;
48296
+ }
48192
48297
 
48193
- return true_count;
48194
- } else {
48195
- for (idx_t i = 0; i < count; ++i) {
48196
- maybe_vec.set_index(i, i);
48298
+ // Slice the Vectors down to the rows that are not determined (i.e., neither is NULL)
48299
+ SelectionVector slicer(count);
48300
+ idx_t false_count = 0;
48301
+ for (idx_t i = 0; i < count; ++i) {
48302
+ const auto result_idx = sel.get_index(i);
48303
+ const auto lidx = lvdata.sel->get_index(i);
48304
+ const auto ridx = rvdata.sel->get_index(i);
48305
+ if (!lmask.RowIsValid(lidx) || !rmask.RowIsValid(ridx)) {
48306
+ false_opt.Append(false_count, result_idx);
48307
+ } else {
48308
+ // Neither is NULL, distinguish values.
48309
+ slicer.set_index(remaining, i);
48310
+ maybe_vec.set_index(remaining++, result_idx);
48197
48311
  }
48198
- return count;
48199
48312
  }
48313
+ false_opt.Advance(false_count);
48314
+
48315
+ if (remaining && remaining < count) {
48316
+ left.Slice(slicer, remaining);
48317
+ right.Slice(slicer, remaining);
48318
+ }
48319
+
48320
+ return remaining;
48200
48321
  }
48201
48322
 
48202
- static void ScatterSelection(SelectionVector *target, const idx_t count, const SelectionVector *sel,
48203
- const SelectionVector &dense_vec) {
48323
+ static void ScatterSelection(SelectionVector *target, const idx_t count, const SelectionVector &dense_vec) {
48204
48324
  if (target) {
48205
48325
  for (idx_t i = 0; i < count; ++i) {
48206
- target->set_index(i, sel->get_index(dense_vec.get_index(i)));
48326
+ target->set_index(i, dense_vec.get_index(i));
48207
48327
  }
48208
48328
  }
48209
48329
  }
48210
48330
 
48211
48331
  template <typename OP>
48212
- static idx_t NestedSelectOperation(Vector &left, Vector &right, const SelectionVector *sel, idx_t vcount,
48332
+ static idx_t NestedSelectOperation(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
48213
48333
  SelectionVector *true_sel, SelectionVector *false_sel) {
48214
48334
  // The Select operations all use a dense pair of input vectors to partition
48215
48335
  // a selection vector in a single pass. But to implement progressive comparisons,
@@ -48217,47 +48337,34 @@ static idx_t NestedSelectOperation(Vector &left, Vector &right, const SelectionV
48217
48337
  // and then scatter the output selections when we are done.
48218
48338
  SelectionVector owned_sel;
48219
48339
  if (!sel) {
48220
- sel = FlatVector::IncrementalSelectionVector(vcount, owned_sel);
48340
+ sel = FlatVector::IncrementalSelectionVector(count, owned_sel);
48221
48341
  }
48222
48342
 
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);
48343
+ // Make buffered selections for progressive comparisons
48344
+ // TODO: Remove unnecessary allocations
48345
+ SelectionVector true_vec(count);
48229
48346
  OptionalSelection true_opt(&true_vec);
48230
48347
 
48231
- SelectionVector false_vec(vcount);
48348
+ SelectionVector false_vec(count);
48232
48349
  OptionalSelection false_opt(&false_vec);
48233
48350
 
48234
- SelectionVector maybe_vec(vcount);
48235
- auto count = SelectNotNull(lvdata, rvdata, vcount, false_opt, maybe_vec);
48236
- auto no_match_count = vcount - count;
48351
+ SelectionVector maybe_vec(count);
48237
48352
 
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
- }
48353
+ // Handle NULL nested values
48354
+ Vector l_not_null(left);
48355
+ Vector r_not_null(right);
48356
+
48357
+ auto match_count = SelectNotNull(l_not_null, r_not_null, count, *sel, maybe_vec, false_opt);
48358
+ auto no_match_count = count - match_count;
48359
+ count = match_count;
48245
48360
 
48246
48361
  // 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);
48362
+ match_count = NestedSelector::Select<OP>(l_not_null, r_not_null, count, maybe_vec, count, true_opt, false_opt);
48248
48363
  no_match_count += (count - match_count);
48249
48364
 
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);
48365
+ // Copy the buffered selections to the output selections
48366
+ ScatterSelection(true_sel, match_count, true_vec);
48367
+ ScatterSelection(false_sel, no_match_count, false_vec);
48261
48368
 
48262
48369
  return match_count;
48263
48370
  }
@@ -63944,14 +64051,15 @@ class DataTable;
63944
64051
  class PhysicalDelete : public PhysicalOperator {
63945
64052
  public:
63946
64053
  PhysicalDelete(vector<LogicalType> types, TableCatalogEntry &tableref, DataTable &table, idx_t row_id_index,
63947
- idx_t estimated_cardinality)
64054
+ idx_t estimated_cardinality, bool return_chunk)
63948
64055
  : PhysicalOperator(PhysicalOperatorType::DELETE_OPERATOR, move(types), estimated_cardinality),
63949
- tableref(tableref), table(table), row_id_index(row_id_index) {
64056
+ tableref(tableref), table(table), row_id_index(row_id_index), return_chunk(return_chunk) {
63950
64057
  }
63951
64058
 
63952
64059
  TableCatalogEntry &tableref;
63953
64060
  DataTable &table;
63954
64061
  idx_t row_id_index;
64062
+ bool return_chunk;
63955
64063
 
63956
64064
  public:
63957
64065
  // Source interface
@@ -63962,6 +64070,7 @@ public:
63962
64070
  public:
63963
64071
  // Sink interface
63964
64072
  unique_ptr<GlobalSinkState> GetGlobalSinkState(ClientContext &context) const override;
64073
+ unique_ptr<LocalSinkState> GetLocalSinkState(ExecutionContext &context) const override;
63965
64074
  SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate,
63966
64075
  DataChunk &input) const override;
63967
64076
 
@@ -63981,6 +64090,7 @@ public:
63981
64090
 
63982
64091
 
63983
64092
 
64093
+
63984
64094
  namespace duckdb {
63985
64095
 
63986
64096
  //===--------------------------------------------------------------------===//
@@ -63988,21 +64098,46 @@ namespace duckdb {
63988
64098
  //===--------------------------------------------------------------------===//
63989
64099
  class DeleteGlobalState : public GlobalSinkState {
63990
64100
  public:
63991
- DeleteGlobalState() : deleted_count(0) {
64101
+ DeleteGlobalState() : deleted_count(0), returned_chunk_count(0) {
63992
64102
  }
63993
64103
 
63994
64104
  mutex delete_lock;
63995
64105
  idx_t deleted_count;
64106
+ ChunkCollection return_chunk_collection;
64107
+ idx_t returned_chunk_count;
64108
+ };
64109
+
64110
+ class DeleteLocalState : public LocalSinkState {
64111
+ public:
64112
+ explicit DeleteLocalState(const vector<LogicalType> &table_types) {
64113
+ delete_chunk.Initialize(table_types);
64114
+ }
64115
+ DataChunk delete_chunk;
63996
64116
  };
63997
64117
 
63998
64118
  SinkResultType PhysicalDelete::Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate,
63999
64119
  DataChunk &input) const {
64000
64120
  auto &gstate = (DeleteGlobalState &)state;
64121
+ auto &ustate = (DeleteLocalState &)lstate;
64122
+
64123
+ // get rows and
64124
+ auto &transaction = Transaction::GetTransaction(context.client);
64125
+ auto &row_identifiers = input.data[row_id_index];
64126
+
64127
+ vector<column_t> column_ids;
64128
+ for (idx_t i = 0; i < table.column_definitions.size(); i++) {
64129
+ column_ids.emplace_back(i);
64130
+ };
64131
+ auto cfs = ColumnFetchState();
64001
64132
 
64002
- // delete data in the base table
64003
- // the row ids are given to us as the last column of the child chunk
64004
64133
  lock_guard<mutex> delete_guard(gstate.delete_lock);
64005
- gstate.deleted_count += table.Delete(tableref, context.client, input.data[row_id_index], input.size());
64134
+ if (return_chunk) {
64135
+ row_identifiers.Normalify(input.size());
64136
+ table.Fetch(transaction, ustate.delete_chunk, column_ids, row_identifiers, input.size(), cfs);
64137
+ gstate.return_chunk_collection.Append(ustate.delete_chunk);
64138
+ }
64139
+ gstate.deleted_count += table.Delete(tableref, context.client, row_identifiers, input.size());
64140
+
64006
64141
  return SinkResultType::NEED_MORE_INPUT;
64007
64142
  }
64008
64143
 
@@ -64010,6 +64145,10 @@ unique_ptr<GlobalSinkState> PhysicalDelete::GetGlobalSinkState(ClientContext &co
64010
64145
  return make_unique<DeleteGlobalState>();
64011
64146
  }
64012
64147
 
64148
+ unique_ptr<LocalSinkState> PhysicalDelete::GetLocalSinkState(ExecutionContext &context) const {
64149
+ return make_unique<DeleteLocalState>(table.GetTypes());
64150
+ }
64151
+
64013
64152
  //===--------------------------------------------------------------------===//
64014
64153
  // Source
64015
64154
  //===--------------------------------------------------------------------===//
@@ -64033,9 +64172,22 @@ void PhysicalDelete::GetData(ExecutionContext &context, DataChunk &chunk, Global
64033
64172
  return;
64034
64173
  }
64035
64174
 
64036
- chunk.SetCardinality(1);
64037
- chunk.SetValue(0, 0, Value::BIGINT(g.deleted_count));
64038
- state.finished = true;
64175
+ if (!return_chunk) {
64176
+ chunk.SetCardinality(1);
64177
+ chunk.SetValue(0, 0, Value::BIGINT(g.deleted_count));
64178
+ state.finished = true;
64179
+ }
64180
+
64181
+ idx_t chunk_return = g.returned_chunk_count;
64182
+ if (chunk_return >= g.return_chunk_collection.Chunks().size()) {
64183
+ return;
64184
+ }
64185
+ chunk.Reference(g.return_chunk_collection.GetChunk(chunk_return));
64186
+ chunk.SetCardinality((g.return_chunk_collection.GetChunk(chunk_return)).size());
64187
+ g.returned_chunk_count += 1;
64188
+ if (g.returned_chunk_count >= g.return_chunk_collection.Chunks().size()) {
64189
+ state.finished = true;
64190
+ }
64039
64191
  }
64040
64192
 
64041
64193
  } // namespace duckdb
@@ -64482,10 +64634,10 @@ class PhysicalUpdate : public PhysicalOperator {
64482
64634
  public:
64483
64635
  PhysicalUpdate(vector<LogicalType> types, TableCatalogEntry &tableref, DataTable &table, vector<column_t> columns,
64484
64636
  vector<unique_ptr<Expression>> expressions, vector<unique_ptr<Expression>> bound_defaults,
64485
- idx_t estimated_cardinality)
64637
+ idx_t estimated_cardinality, bool return_chunk)
64486
64638
  : PhysicalOperator(PhysicalOperatorType::UPDATE, move(types), estimated_cardinality), tableref(tableref),
64487
64639
  table(table), columns(std::move(columns)), expressions(move(expressions)),
64488
- bound_defaults(move(bound_defaults)) {
64640
+ bound_defaults(move(bound_defaults)), return_chunk(return_chunk) {
64489
64641
  }
64490
64642
 
64491
64643
  TableCatalogEntry &tableref;
@@ -64494,6 +64646,8 @@ public:
64494
64646
  vector<unique_ptr<Expression>> expressions;
64495
64647
  vector<unique_ptr<Expression>> bound_defaults;
64496
64648
  bool update_is_del_and_insert;
64649
+ //! If the returning statement is present, return the whole chunk
64650
+ bool return_chunk;
64497
64651
 
64498
64652
  public:
64499
64653
  // Source interface
@@ -64527,6 +64681,7 @@ public:
64527
64681
 
64528
64682
 
64529
64683
 
64684
+
64530
64685
  namespace duckdb {
64531
64686
 
64532
64687
  //===--------------------------------------------------------------------===//
@@ -64534,12 +64689,14 @@ namespace duckdb {
64534
64689
  //===--------------------------------------------------------------------===//
64535
64690
  class UpdateGlobalState : public GlobalSinkState {
64536
64691
  public:
64537
- UpdateGlobalState() : updated_count(0) {
64692
+ UpdateGlobalState() : updated_count(0), returned_chunk_count(0) {
64538
64693
  }
64539
64694
 
64540
64695
  mutex lock;
64541
64696
  idx_t updated_count;
64542
64697
  unordered_set<row_t> updated_columns;
64698
+ ChunkCollection return_chunk_collection;
64699
+ idx_t returned_chunk_count;
64543
64700
  };
64544
64701
 
64545
64702
  class UpdateLocalState : public LocalSinkState {
@@ -64619,9 +64776,21 @@ SinkResultType PhysicalUpdate::Sink(ExecutionContext &context, GlobalSinkState &
64619
64776
  }
64620
64777
  table.Append(tableref, context.client, mock_chunk);
64621
64778
  } else {
64779
+ if (return_chunk) {
64780
+ mock_chunk.SetCardinality(update_chunk);
64781
+ for (idx_t i = 0; i < columns.size(); i++) {
64782
+ mock_chunk.data[columns[i]].Reference(update_chunk.data[i]);
64783
+ }
64784
+ }
64622
64785
  table.Update(tableref, context.client, row_ids, columns, update_chunk);
64623
64786
  }
64787
+
64788
+ if (return_chunk) {
64789
+ gstate.return_chunk_collection.Append(mock_chunk);
64790
+ }
64791
+
64624
64792
  gstate.updated_count += chunk.size();
64793
+
64625
64794
  return SinkResultType::NEED_MORE_INPUT;
64626
64795
  }
64627
64796
 
@@ -64662,10 +64831,22 @@ void PhysicalUpdate::GetData(ExecutionContext &context, DataChunk &chunk, Global
64662
64831
  if (state.finished) {
64663
64832
  return;
64664
64833
  }
64834
+ if (!return_chunk) {
64835
+ chunk.SetCardinality(1);
64836
+ chunk.SetValue(0, 0, Value::BIGINT(g.updated_count));
64837
+ state.finished = true;
64838
+ }
64665
64839
 
64666
- chunk.SetCardinality(1);
64667
- chunk.SetValue(0, 0, Value::BIGINT(g.updated_count));
64668
- state.finished = true;
64840
+ idx_t chunk_return = g.returned_chunk_count;
64841
+ if (chunk_return >= g.return_chunk_collection.Chunks().size()) {
64842
+ return;
64843
+ }
64844
+ chunk.Reference(g.return_chunk_collection.GetChunk(chunk_return));
64845
+ chunk.SetCardinality((g.return_chunk_collection.GetChunk(chunk_return)).size());
64846
+ g.returned_chunk_count += 1;
64847
+ if (g.returned_chunk_count >= g.return_chunk_collection.Chunks().size()) {
64848
+ state.finished = true;
64849
+ }
64669
64850
  }
64670
64851
 
64671
64852
  } // namespace duckdb
@@ -68288,14 +68469,27 @@ namespace duckdb {
68288
68469
  class LogicalDelete : public LogicalOperator {
68289
68470
  public:
68290
68471
  explicit LogicalDelete(TableCatalogEntry *table)
68291
- : LogicalOperator(LogicalOperatorType::LOGICAL_DELETE), table(table) {
68472
+ : LogicalOperator(LogicalOperatorType::LOGICAL_DELETE), table(table), table_index(0), return_chunk(false) {
68292
68473
  }
68293
68474
 
68294
68475
  TableCatalogEntry *table;
68476
+ idx_t table_index;
68477
+ bool return_chunk;
68295
68478
 
68296
68479
  protected:
68480
+ vector<ColumnBinding> GetColumnBindings() override {
68481
+ if (return_chunk) {
68482
+ return GenerateColumnBindings(table_index, table->columns.size());
68483
+ }
68484
+ return {ColumnBinding(0, 0)};
68485
+ }
68486
+
68297
68487
  void ResolveTypes() override {
68298
- types.emplace_back(LogicalType::BIGINT);
68488
+ if (return_chunk) {
68489
+ types = table->GetTypes();
68490
+ } else {
68491
+ types.emplace_back(LogicalType::BIGINT);
68492
+ }
68299
68493
  }
68300
68494
  };
68301
68495
  } // namespace duckdb
@@ -68314,8 +68508,8 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalDelete &op
68314
68508
  auto &bound_ref = (BoundReferenceExpression &)*op.expressions[0];
68315
68509
 
68316
68510
  dependencies.insert(op.table);
68317
- auto del =
68318
- make_unique<PhysicalDelete>(op.types, *op.table, *op.table->storage, bound_ref.index, op.estimated_cardinality);
68511
+ auto del = make_unique<PhysicalDelete>(op.types, *op.table, *op.table->storage, bound_ref.index,
68512
+ op.estimated_cardinality, op.return_chunk);
68319
68513
  del->children.push_back(move(plan));
68320
68514
  return move(del);
68321
68515
  }
@@ -70604,17 +70798,33 @@ namespace duckdb {
70604
70798
  class LogicalUpdate : public LogicalOperator {
70605
70799
  public:
70606
70800
  explicit LogicalUpdate(TableCatalogEntry *table)
70607
- : LogicalOperator(LogicalOperatorType::LOGICAL_UPDATE), table(table) {
70801
+ : LogicalOperator(LogicalOperatorType::LOGICAL_UPDATE), table(table), table_index(0), return_chunk(false) {
70608
70802
  }
70609
70803
 
70804
+ //! The base table to update
70610
70805
  TableCatalogEntry *table;
70806
+ //! table catalog index
70807
+ idx_t table_index;
70808
+ //! if returning option is used, return the update chunk
70809
+ bool return_chunk;
70611
70810
  vector<column_t> columns;
70612
70811
  vector<unique_ptr<Expression>> bound_defaults;
70613
70812
  bool update_is_del_and_insert;
70614
70813
 
70615
70814
  protected:
70815
+ vector<ColumnBinding> GetColumnBindings() override {
70816
+ if (return_chunk) {
70817
+ return GenerateColumnBindings(table_index, table->columns.size());
70818
+ }
70819
+ return {ColumnBinding(0, 0)};
70820
+ }
70821
+
70616
70822
  void ResolveTypes() override {
70617
- types.emplace_back(LogicalType::BIGINT);
70823
+ if (return_chunk) {
70824
+ types = table->GetTypes();
70825
+ } else {
70826
+ types.emplace_back(LogicalType::BIGINT);
70827
+ }
70618
70828
  }
70619
70829
  };
70620
70830
  } // namespace duckdb
@@ -70629,7 +70839,8 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalUpdate &op
70629
70839
 
70630
70840
  dependencies.insert(op.table);
70631
70841
  auto update = make_unique<PhysicalUpdate>(op.types, *op.table, *op.table->storage, op.columns, move(op.expressions),
70632
- move(op.bound_defaults), op.estimated_cardinality);
70842
+ move(op.bound_defaults), op.estimated_cardinality, op.return_chunk);
70843
+
70633
70844
  update->update_is_del_and_insert = op.update_is_del_and_insert;
70634
70845
  update->children.push_back(move(plan));
70635
70846
  return move(update);
@@ -97377,8 +97588,7 @@ void ArrowTableFunction::ArrowToDuckDB(ArrowScanState &scan_state,
97377
97588
  if (array.length != scan_state.chunk->arrow_array.length) {
97378
97589
  throw InvalidInputException("arrow_scan: array length mismatch");
97379
97590
  }
97380
- output.data[idx].GetBuffer()->SetAuxiliaryData(make_unique<ArrowAuxiliaryData>(scan_state.chunk),
97381
- VectorAuxiliaryDataType::ARROW_AUXILIARY);
97591
+ output.data[idx].GetBuffer()->SetAuxiliaryData(make_unique<ArrowAuxiliaryData>(scan_state.chunk));
97382
97592
  if (array.dictionary) {
97383
97593
  ColumnArrowToDuckDBDictionary(output.data[idx], array, scan_state, output.size(), arrow_convert_data,
97384
97594
  col_idx, arrow_convert_idx);
@@ -118983,6 +119193,7 @@ public:
118983
119193
  unique_ptr<ParsedExpression> condition;
118984
119194
  unique_ptr<TableRef> table;
118985
119195
  vector<unique_ptr<TableRef>> using_clauses;
119196
+ vector<unique_ptr<ParsedExpression>> returning_list;
118986
119197
 
118987
119198
  protected:
118988
119199
  DeleteStatement(const DeleteStatement &other);
@@ -120287,6 +120498,8 @@ public:
120287
120498
  unique_ptr<TableRef> from_table;
120288
120499
  vector<string> columns;
120289
120500
  vector<unique_ptr<ParsedExpression>> expressions;
120501
+ //! keep track of optional returningList if statement contains a RETURNING keyword
120502
+ vector<unique_ptr<ParsedExpression>> returning_list;
120290
120503
 
120291
120504
  protected:
120292
120505
  UpdateStatement(const UpdateStatement &other);
@@ -127682,10 +127895,14 @@ void RemoveUnusedColumns::VisitOperator(LogicalOperator &op) {
127682
127895
  remove.VisitOperator(*op.children[0]);
127683
127896
  return;
127684
127897
  }
127685
- case LogicalOperatorType::LOGICAL_INSERT: {
127686
- //! When RETURNING is used, a PROJECTION is the top level operator
127687
- //! We still need to project all values from the insert so the projection
127688
- //! on top of the INSERT can select from only that table values being inserted
127898
+ case LogicalOperatorType::LOGICAL_INSERT:
127899
+ case LogicalOperatorType::LOGICAL_UPDATE:
127900
+ case LogicalOperatorType::LOGICAL_DELETE: {
127901
+ //! When RETURNING is used, a PROJECTION is the top level operator for INSERTS, UPDATES, and DELETES
127902
+ //! We still need to project all values from these operators so the projection
127903
+ //! on top of them can select from only the table values being inserted.
127904
+ //! TODO: Push down the projections from the returning statement
127905
+ //! TODO: Be careful because you might be adding expressions when a user returns *
127689
127906
  RemoveUnusedColumns remove(binder, context, true);
127690
127907
  remove.VisitOperatorExpressions(op);
127691
127908
  remove.VisitOperator(*op.children[0]);
@@ -149630,6 +149847,10 @@ unique_ptr<DeleteStatement> Transformer::TransformDelete(duckdb_libpgquery::PGNo
149630
149847
  result->using_clauses.push_back(move(using_entry));
149631
149848
  }
149632
149849
  }
149850
+
149851
+ if (stmt->returningList) {
149852
+ Transformer::TransformExpressionList(*(stmt->returningList), result->returning_list);
149853
+ }
149633
149854
  return result;
149634
149855
  }
149635
149856
 
@@ -150394,6 +150615,11 @@ unique_ptr<UpdateStatement> Transformer::TransformUpdate(duckdb_libpgquery::PGNo
150394
150615
  result->expressions.push_back(TransformExpression(target->val));
150395
150616
  }
150396
150617
 
150618
+ // Grab and transform the returning columns from the parser.
150619
+ if (stmt->returningList) {
150620
+ Transformer::TransformExpressionList(*(stmt->returningList), result->returning_list);
150621
+ }
150622
+
150397
150623
  result->condition = TransformExpression(stmt->whereClause);
150398
150624
  return result;
150399
150625
  }
@@ -155594,6 +155820,32 @@ unique_ptr<BoundCreateTableInfo> Binder::BindCreateTableInfo(unique_ptr<CreateIn
155594
155820
 
155595
155821
 
155596
155822
 
155823
+ //===----------------------------------------------------------------------===//
155824
+ // DuckDB
155825
+ //
155826
+ // duckdb/planner/expression_binder/returning_binder.hpp
155827
+ //
155828
+ //
155829
+ //===----------------------------------------------------------------------===//
155830
+
155831
+
155832
+
155833
+
155834
+
155835
+ namespace duckdb {
155836
+
155837
+ //! The RETURNING binder is responsible for binding expressions within the RETURNING statement
155838
+ class ReturningBinder : public ExpressionBinder {
155839
+ public:
155840
+ ReturningBinder(Binder &binder, ClientContext &context);
155841
+
155842
+ protected:
155843
+ BindResult BindExpression(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth,
155844
+ bool root_expression = false) override;
155845
+ };
155846
+
155847
+ } // namespace duckdb
155848
+
155597
155849
 
155598
155850
 
155599
155851
 
@@ -155668,10 +155920,21 @@ BoundStatement Binder::Bind(DeleteStatement &stmt) {
155668
155920
  LogicalType::ROW_TYPE, ColumnBinding(get.table_index, get.column_ids.size())));
155669
155921
  get.column_ids.push_back(COLUMN_IDENTIFIER_ROW_ID);
155670
155922
 
155671
- result.plan = move(del);
155672
- result.names = {"Count"};
155673
- result.types = {LogicalType::BIGINT};
155674
- this->allow_stream_result = false;
155923
+ if (!stmt.returning_list.empty()) {
155924
+ del->return_chunk = true;
155925
+
155926
+ auto update_table_index = GenerateTableIndex();
155927
+ del->table_index = update_table_index;
155928
+
155929
+ unique_ptr<LogicalOperator> del_as_logicaloperator = move(del);
155930
+ return BindReturning(move(stmt.returning_list), table, update_table_index, move(del_as_logicaloperator),
155931
+ move(result));
155932
+ } else {
155933
+ result.plan = move(del);
155934
+ result.names = {"Count"};
155935
+ result.types = {LogicalType::BIGINT};
155936
+ this->allow_stream_result = false;
155937
+ }
155675
155938
  return result;
155676
155939
  }
155677
155940
 
@@ -155994,31 +156257,6 @@ protected:
155994
156257
 
155995
156258
 
155996
156259
 
155997
- //===----------------------------------------------------------------------===//
155998
- // DuckDB
155999
- //
156000
- // duckdb/planner/expression_binder/returning_binder.hpp
156001
- //
156002
- //
156003
- //===----------------------------------------------------------------------===//
156004
-
156005
-
156006
-
156007
-
156008
-
156009
- namespace duckdb {
156010
-
156011
- //! The RETURNING binder is responsible for binding expressions within the RETURNING statement
156012
- class ReturningBinder : public ExpressionBinder {
156013
- public:
156014
- ReturningBinder(Binder &binder, ClientContext &context);
156015
-
156016
- protected:
156017
- BindResult BindExpression(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth,
156018
- bool root_expression = false) override;
156019
- };
156020
-
156021
- } // namespace duckdb
156022
156260
 
156023
156261
 
156024
156262
  namespace duckdb {
@@ -156139,57 +156377,15 @@ BoundStatement Binder::Bind(InsertStatement &stmt) {
156139
156377
 
156140
156378
  if (!stmt.returning_list.empty()) {
156141
156379
  insert->return_chunk = true;
156142
- // clear result type and names because returning list will update them
156143
156380
  result.types.clear();
156144
156381
  result.names.clear();
156145
-
156146
156382
  auto insert_table_index = GenerateTableIndex();
156147
156383
  insert->table_index = insert_table_index;
156384
+ unique_ptr<LogicalOperator> index_as_logicaloperator = move(insert);
156148
156385
 
156149
- auto binder = Binder::CreateBinder(context);
156150
- auto types = table->GetTypes();
156151
- vector<std::string> names;
156152
- for (auto &col : table->columns) {
156153
- names.push_back(col.name);
156154
- }
156155
-
156156
- binder->bind_context.AddGenericBinding(insert->table_index, stmt.table, names, types);
156157
- ReturningBinder returning_binder(*binder, context);
156158
-
156159
- unique_ptr<LogicalOperator> insert_as_logicaloperator = move(insert);
156160
-
156161
- vector<unique_ptr<Expression>> projection_expressions;
156162
- LogicalType result_type;
156163
- for (auto &returning_expr : stmt.returning_list) {
156164
- auto expr_type = returning_expr->GetExpressionType();
156165
- if (expr_type == ExpressionType::STAR) {
156166
- auto generated_star_list = vector<unique_ptr<ParsedExpression>>();
156167
- binder->bind_context.GenerateAllColumnExpressions((StarExpression &)*returning_expr,
156168
- generated_star_list);
156169
-
156170
- for (auto &star_column : generated_star_list) {
156171
- auto star_expr = returning_binder.Bind(star_column, &result_type);
156172
- result.types.push_back(result_type);
156173
- result.names.push_back(star_expr->GetName());
156174
- projection_expressions.push_back(move(star_expr));
156175
- }
156176
- } else {
156177
- auto expr = returning_binder.Bind(returning_expr, &result_type);
156178
- result.names.push_back(expr->GetName());
156179
- result.types.push_back(result_type);
156180
- projection_expressions.push_back(move(expr));
156181
- }
156182
- }
156183
-
156184
- auto projection = make_unique<LogicalProjection>(GenerateTableIndex(), move(projection_expressions));
156185
- projection->AddChild(move(insert_as_logicaloperator));
156186
- result.plan = move(projection);
156187
- D_ASSERT(result.types.size() == result.names.size());
156188
- this->allow_stream_result = true;
156189
- return result;
156386
+ return BindReturning(move(stmt.returning_list), table, insert_table_index, move(index_as_logicaloperator),
156387
+ move(result));
156190
156388
  } else {
156191
- insert->table_index = 0;
156192
- insert->return_chunk = false;
156193
156389
  D_ASSERT(result.types.size() == result.names.size());
156194
156390
  result.plan = move(insert);
156195
156391
  this->allow_stream_result = false;
@@ -156644,6 +156840,8 @@ static void BindUpdateConstraints(TableCatalogEntry &table, LogicalGet &get, Log
156644
156840
  }
156645
156841
  // for index updates we always turn any update into an insert and a delete
156646
156842
  // we thus need all the columns to be available, hence we check if the update touches any index columns
156843
+ // If the returning keyword is used, we need access to the whole row in case the user requests it.
156844
+ // Therefore switch the update to a delete and insert.
156647
156845
  update.update_is_del_and_insert = false;
156648
156846
  table.storage->info->indexes.Scan([&](Index &index) {
156649
156847
  if (index.IndexIsUpdated(update.columns)) {
@@ -156661,8 +156859,9 @@ static void BindUpdateConstraints(TableCatalogEntry &table, LogicalGet &get, Log
156661
156859
  }
156662
156860
  }
156663
156861
 
156664
- if (update.update_is_del_and_insert) {
156665
- // the update updates a column required by an index, push projections for all columns
156862
+ if (update.update_is_del_and_insert || update.return_chunk) {
156863
+ // the update updates a column required by an index or requires returning the updated rows,
156864
+ // push projections for all columns
156666
156865
  unordered_set<column_t> all_columns;
156667
156866
  for (idx_t i = 0; i < table.storage->column_definitions.size(); i++) {
156668
156867
  all_columns.insert(i);
@@ -156700,6 +156899,11 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) {
156700
156899
  this->read_only = false;
156701
156900
  }
156702
156901
  auto update = make_unique<LogicalUpdate>(table);
156902
+
156903
+ // set return_chunk boolean early because it needs uses update_is_del_and_insert logic
156904
+ if (!stmt.returning_list.empty()) {
156905
+ update->return_chunk = true;
156906
+ }
156703
156907
  // bind the default values
156704
156908
  BindDefaultValues(table->columns, update->bound_defaults);
156705
156909
 
@@ -156718,6 +156922,7 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) {
156718
156922
 
156719
156923
  auto proj_index = GenerateTableIndex();
156720
156924
  vector<unique_ptr<Expression>> projection_expressions;
156925
+
156721
156926
  for (idx_t i = 0; i < stmt.columns.size(); i++) {
156722
156927
  auto &colname = stmt.columns[i];
156723
156928
  auto &expr = stmt.expressions[i];
@@ -156743,6 +156948,7 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) {
156743
156948
  projection_expressions.push_back(move(bound_expr));
156744
156949
  }
156745
156950
  }
156951
+
156746
156952
  // now create the projection
156747
156953
  auto proj = make_unique<LogicalProjection>(proj_index, move(projection_expressions));
156748
156954
  proj->AddChild(move(root));
@@ -156758,10 +156964,21 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) {
156758
156964
  // set the projection as child of the update node and finalize the result
156759
156965
  update->AddChild(move(proj));
156760
156966
 
156761
- result.names = {"Count"};
156762
- result.types = {LogicalType::BIGINT};
156763
- result.plan = move(update);
156764
- this->allow_stream_result = false;
156967
+ if (!stmt.returning_list.empty()) {
156968
+ auto update_table_index = GenerateTableIndex();
156969
+ update->table_index = update_table_index;
156970
+ unique_ptr<LogicalOperator> update_as_logicaloperator = move(update);
156971
+
156972
+ return BindReturning(move(stmt.returning_list), table, update_table_index, move(update_as_logicaloperator),
156973
+ move(result));
156974
+
156975
+ } else {
156976
+ update->table_index = 0;
156977
+ result.names = {"Count"};
156978
+ result.types = {LogicalType::BIGINT};
156979
+ result.plan = move(update);
156980
+ this->allow_stream_result = false;
156981
+ }
156765
156982
  return result;
156766
156983
  }
156767
156984
 
@@ -158024,6 +158241,7 @@ unique_ptr<LogicalOperator> Binder::CreatePlan(BoundTableFunction &ref) {
158024
158241
 
158025
158242
 
158026
158243
 
158244
+
158027
158245
  #include <algorithm>
158028
158246
 
158029
158247
 
@@ -158392,6 +158610,53 @@ string Binder::FormatErrorRecursive(idx_t query_location, const string &message,
158392
158610
  return context.FormatErrorRecursive(message, values);
158393
158611
  }
158394
158612
 
158613
+ BoundStatement Binder::BindReturning(vector<unique_ptr<ParsedExpression>> returning_list, TableCatalogEntry *table,
158614
+ idx_t update_table_index, unique_ptr<LogicalOperator> child_operator,
158615
+ BoundStatement result) {
158616
+
158617
+ vector<LogicalType> types;
158618
+ vector<std::string> names;
158619
+
158620
+ auto binder = Binder::CreateBinder(context);
158621
+
158622
+ for (auto &col : table->columns) {
158623
+ names.push_back(col.name);
158624
+ types.push_back(col.type);
158625
+ }
158626
+
158627
+ binder->bind_context.AddGenericBinding(update_table_index, table->name, names, types);
158628
+ ReturningBinder returning_binder(*binder, context);
158629
+
158630
+ vector<unique_ptr<Expression>> projection_expressions;
158631
+ LogicalType result_type;
158632
+ for (auto &returning_expr : returning_list) {
158633
+ auto expr_type = returning_expr->GetExpressionType();
158634
+ if (expr_type == ExpressionType::STAR) {
158635
+ auto generated_star_list = vector<unique_ptr<ParsedExpression>>();
158636
+ binder->bind_context.GenerateAllColumnExpressions((StarExpression &)*returning_expr, generated_star_list);
158637
+
158638
+ for (auto &star_column : generated_star_list) {
158639
+ auto star_expr = returning_binder.Bind(star_column, &result_type);
158640
+ result.types.push_back(result_type);
158641
+ result.names.push_back(star_expr->GetName());
158642
+ projection_expressions.push_back(move(star_expr));
158643
+ }
158644
+ } else {
158645
+ auto expr = returning_binder.Bind(returning_expr, &result_type);
158646
+ result.names.push_back(expr->GetName());
158647
+ result.types.push_back(result_type);
158648
+ projection_expressions.push_back(move(expr));
158649
+ }
158650
+ }
158651
+
158652
+ auto projection = make_unique<LogicalProjection>(GenerateTableIndex(), move(projection_expressions));
158653
+ projection->AddChild(move(child_operator));
158654
+ D_ASSERT(result.types.size() == result.names.size());
158655
+ result.plan = move(projection);
158656
+ this->allow_stream_result = true;
158657
+ return result;
158658
+ }
158659
+
158395
158660
  } // namespace duckdb
158396
158661
 
158397
158662