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/package.json +1 -1
- package/src/duckdb.cpp +535 -270
- package/src/duckdb.hpp +6 -3
- package/src/parquet-amalgamation.cpp +34072 -34072
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
|
-
|
|
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
|
-
|
|
5319
|
+
agg_chunk_result->Append(*new_chunk, true);
|
|
5316
5320
|
}
|
|
5317
5321
|
}
|
|
5318
|
-
|
|
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
|
|
26374
|
+
// Gather a dense Vector containing the column values being matched
|
|
26371
26375
|
Vector key(col.GetType());
|
|
26372
|
-
RowOperations::Gather(rows, sel, key,
|
|
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>(
|
|
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>(
|
|
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(
|
|
43440
|
-
const SelectionVector &sel, SelectionVector &maybe_vec, OptionalSelection &
|
|
43441
|
-
OptionalSelection &
|
|
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
|
|
43458
|
-
const auto lidx = lvdata.sel->get_index(
|
|
43459
|
-
const auto ridx = rvdata.sel->get_index(
|
|
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
|
-
|
|
43479
|
+
false_opt.Append(false_count, result_idx);
|
|
43466
43480
|
} else {
|
|
43467
|
-
|
|
43481
|
+
true_opt.Append(true_count, result_idx);
|
|
43468
43482
|
}
|
|
43469
43483
|
} else {
|
|
43470
43484
|
// Neither is NULL, distinguish values.
|
|
43471
|
-
|
|
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
|
-
|
|
43478
|
-
|
|
43490
|
+
true_opt.Advance(true_count);
|
|
43491
|
+
false_opt.Advance(false_count);
|
|
43479
43492
|
|
|
43480
|
-
|
|
43481
|
-
|
|
43482
|
-
|
|
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
|
|
43621
|
-
|
|
43622
|
-
|
|
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,
|
|
43626
|
-
auto &rchildren = StructVectorGetSlicedEntries(right, rsliced,
|
|
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
|
-
|
|
43632
|
-
|
|
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,
|
|
43684
|
+
PositionComparator::Definite<OP>(lchild, rchild, count, slice_sel, count, &true_sel, false_sel);
|
|
43637
43685
|
if (true_count > 0) {
|
|
43638
|
-
|
|
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,
|
|
43701
|
+
PositionComparator::Possible<OP>(lchild, rchild, count, slice_sel, count, true_sel, &false_sel);
|
|
43647
43702
|
auto false_count = count - true_count;
|
|
43648
|
-
|
|
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,
|
|
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 &
|
|
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
|
|
43734
|
+
const auto slice_idx = slice_sel.get_index(i);
|
|
43664
43735
|
|
|
43665
|
-
const auto lidx = vdata.sel->get_index(
|
|
43736
|
+
const auto lidx = vdata.sel->get_index(slice_idx);
|
|
43666
43737
|
const auto &entry = data[lidx];
|
|
43667
|
-
cursor.set_index(
|
|
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
|
|
43673
|
-
|
|
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
|
-
//
|
|
43680
|
-
SelectionVector lcursor(
|
|
43681
|
-
SelectionVector rcursor(
|
|
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,
|
|
43706
|
-
PositionListCursor(rcursor, rvdata, pos,
|
|
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
|
|
43714
|
-
const auto lidx = lvdata.sel->get_index(
|
|
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(
|
|
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
|
-
|
|
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,
|
|
43735
|
-
|
|
43736
|
-
|
|
43737
|
-
|
|
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
|
-
|
|
43741
|
-
false_count = count -
|
|
43742
|
-
|
|
43743
|
-
|
|
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,
|
|
43750
|
-
static idx_t DistinctSelectNested(Vector &left, Vector &right,
|
|
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
|
-
//
|
|
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
|
-
|
|
43759
|
-
|
|
43760
|
-
|
|
43761
|
-
|
|
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
|
-
|
|
43766
|
-
OptionalSelection false_opt(
|
|
43873
|
+
SelectionVector false_vec(count);
|
|
43874
|
+
OptionalSelection false_opt(&false_vec);
|
|
43767
43875
|
|
|
43768
|
-
|
|
43769
|
-
|
|
43770
|
-
|
|
43771
|
-
|
|
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
|
-
|
|
43780
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
43793
|
-
|
|
43794
|
-
|
|
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
|
-
|
|
43797
|
-
|
|
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,
|
|
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,
|
|
44008
|
-
|
|
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,
|
|
44014
|
-
|
|
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,
|
|
44020
|
-
|
|
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,
|
|
44026
|
-
|
|
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,
|
|
44032
|
-
|
|
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,
|
|
44038
|
-
|
|
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(
|
|
48175
|
-
|
|
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
|
-
|
|
48180
|
-
|
|
48181
|
-
|
|
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
|
|
48184
|
-
|
|
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
|
-
|
|
48295
|
+
return remaining;
|
|
48296
|
+
}
|
|
48192
48297
|
|
|
48193
|
-
|
|
48194
|
-
|
|
48195
|
-
|
|
48196
|
-
|
|
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
|
|
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,
|
|
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
|
|
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(
|
|
48340
|
+
sel = FlatVector::IncrementalSelectionVector(count, owned_sel);
|
|
48221
48341
|
}
|
|
48222
48342
|
|
|
48223
|
-
|
|
48224
|
-
|
|
48225
|
-
|
|
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(
|
|
48348
|
+
SelectionVector false_vec(count);
|
|
48232
48349
|
OptionalSelection false_opt(&false_vec);
|
|
48233
48350
|
|
|
48234
|
-
SelectionVector maybe_vec(
|
|
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
|
-
//
|
|
48239
|
-
|
|
48240
|
-
|
|
48241
|
-
|
|
48242
|
-
|
|
48243
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
48251
|
-
|
|
48252
|
-
|
|
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
|
-
|
|
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
|
-
|
|
64037
|
-
|
|
64038
|
-
|
|
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
|
-
|
|
64667
|
-
|
|
64668
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
127687
|
-
|
|
127688
|
-
//!
|
|
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
|
-
|
|
155672
|
-
|
|
155673
|
-
|
|
155674
|
-
|
|
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
|
-
|
|
156150
|
-
|
|
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
|
|
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
|
-
|
|
156762
|
-
|
|
156763
|
-
|
|
156764
|
-
|
|
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
|
|