duckdb 0.3.3-dev482.0 → 0.3.3-dev508.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 +312 -64
- package/src/duckdb.hpp +5 -2
- package/src/parquet-amalgamation.cpp +23874 -23874
package/package.json
CHANGED
package/src/duckdb.cpp
CHANGED
|
@@ -32766,6 +32766,16 @@ void DataChunk::Split(DataChunk &other, idx_t split_idx) {
|
|
|
32766
32766
|
other.SetCardinality(*this);
|
|
32767
32767
|
}
|
|
32768
32768
|
|
|
32769
|
+
void DataChunk::Fuse(DataChunk &other) {
|
|
32770
|
+
D_ASSERT(other.size() == size());
|
|
32771
|
+
const idx_t num_cols = other.data.size();
|
|
32772
|
+
for (idx_t col_idx = 0; col_idx < num_cols; ++col_idx) {
|
|
32773
|
+
data.emplace_back(move(other.data[col_idx]));
|
|
32774
|
+
vector_caches.emplace_back(move(other.vector_caches[col_idx]));
|
|
32775
|
+
}
|
|
32776
|
+
other.Destroy();
|
|
32777
|
+
}
|
|
32778
|
+
|
|
32769
32779
|
void DataChunk::Append(const DataChunk &other, bool resize, SelectionVector *sel, idx_t sel_count) {
|
|
32770
32780
|
idx_t new_size = sel ? size() + sel_count : size() + other.size();
|
|
32771
32781
|
if (other.size() == 0) {
|
|
@@ -57834,8 +57844,28 @@ PhysicalPiecewiseMergeJoin::PhysicalPiecewiseMergeJoin(LogicalOperator &op, uniq
|
|
|
57834
57844
|
JoinType join_type, idx_t estimated_cardinality)
|
|
57835
57845
|
: PhysicalComparisonJoin(op, PhysicalOperatorType::PIECEWISE_MERGE_JOIN, move(cond), join_type,
|
|
57836
57846
|
estimated_cardinality) {
|
|
57837
|
-
//
|
|
57838
|
-
|
|
57847
|
+
// Reorder the conditions so that ranges are at the front.
|
|
57848
|
+
// TODO: use stats to improve the choice?
|
|
57849
|
+
if (conditions.size() > 1) {
|
|
57850
|
+
auto conditions_p = std::move(conditions);
|
|
57851
|
+
conditions.resize(conditions_p.size());
|
|
57852
|
+
idx_t range_position = 0;
|
|
57853
|
+
idx_t other_position = conditions_p.size();
|
|
57854
|
+
for (idx_t i = 0; i < conditions_p.size(); ++i) {
|
|
57855
|
+
switch (conditions_p[i].comparison) {
|
|
57856
|
+
case ExpressionType::COMPARE_LESSTHAN:
|
|
57857
|
+
case ExpressionType::COMPARE_LESSTHANOREQUALTO:
|
|
57858
|
+
case ExpressionType::COMPARE_GREATERTHAN:
|
|
57859
|
+
case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
|
|
57860
|
+
conditions[range_position++] = std::move(conditions_p[i]);
|
|
57861
|
+
break;
|
|
57862
|
+
default:
|
|
57863
|
+
conditions[--other_position] = std::move(conditions_p[i]);
|
|
57864
|
+
break;
|
|
57865
|
+
}
|
|
57866
|
+
}
|
|
57867
|
+
}
|
|
57868
|
+
|
|
57839
57869
|
for (auto &cond : conditions) {
|
|
57840
57870
|
D_ASSERT(cond.left->return_type == cond.right->return_type);
|
|
57841
57871
|
join_key_types.push_back(cond.left->return_type);
|
|
@@ -57854,8 +57884,16 @@ PhysicalPiecewiseMergeJoin::PhysicalPiecewiseMergeJoin(LogicalOperator &op, uniq
|
|
|
57854
57884
|
lhs_orders.emplace_back(BoundOrderByNode(OrderType::DESCENDING, OrderByNullType::NULLS_LAST, move(left)));
|
|
57855
57885
|
rhs_orders.emplace_back(BoundOrderByNode(OrderType::DESCENDING, OrderByNullType::NULLS_LAST, move(right)));
|
|
57856
57886
|
break;
|
|
57887
|
+
case ExpressionType::COMPARE_NOTEQUAL:
|
|
57888
|
+
case ExpressionType::COMPARE_DISTINCT_FROM:
|
|
57889
|
+
// Allowed in multi-predicate joins, but can't be first/sort.
|
|
57890
|
+
D_ASSERT(!lhs_orders.empty());
|
|
57891
|
+
lhs_orders.emplace_back(BoundOrderByNode(OrderType::INVALID, OrderByNullType::NULLS_LAST, move(left)));
|
|
57892
|
+
rhs_orders.emplace_back(BoundOrderByNode(OrderType::INVALID, OrderByNullType::NULLS_LAST, move(right)));
|
|
57893
|
+
break;
|
|
57894
|
+
|
|
57857
57895
|
default:
|
|
57858
|
-
// COMPARE
|
|
57896
|
+
// COMPARE EQUAL not supported with merge join
|
|
57859
57897
|
throw NotImplementedException("Unimplemented join type for merge join");
|
|
57860
57898
|
}
|
|
57861
57899
|
}
|
|
@@ -57871,6 +57909,7 @@ public:
|
|
|
57871
57909
|
MergeJoinGlobalState(BufferManager &buffer_manager, const vector<BoundOrderByNode> &orders, RowLayout &rhs_layout)
|
|
57872
57910
|
: rhs_global_sort_state(buffer_manager, orders, rhs_layout), rhs_has_null(0), rhs_count(0),
|
|
57873
57911
|
memory_per_thread(0) {
|
|
57912
|
+
D_ASSERT(orders.size() == 1);
|
|
57874
57913
|
}
|
|
57875
57914
|
|
|
57876
57915
|
inline idx_t Count() const {
|
|
@@ -57892,11 +57931,12 @@ public:
|
|
|
57892
57931
|
};
|
|
57893
57932
|
|
|
57894
57933
|
unique_ptr<GlobalSinkState> PhysicalPiecewiseMergeJoin::GetGlobalSinkState(ClientContext &context) const {
|
|
57895
|
-
// Get the payload layout from the rhs types
|
|
57934
|
+
// Get the payload layout from the rhs types and tail predicates
|
|
57896
57935
|
RowLayout rhs_layout;
|
|
57897
|
-
|
|
57898
|
-
|
|
57899
|
-
|
|
57936
|
+
rhs_layout.Initialize(children[1]->types);
|
|
57937
|
+
vector<BoundOrderByNode> rhs_order;
|
|
57938
|
+
rhs_order.emplace_back(rhs_orders[0].Copy());
|
|
57939
|
+
auto state = make_unique<MergeJoinGlobalState>(BufferManager::GetBufferManager(context), rhs_order, rhs_layout);
|
|
57900
57940
|
// Set external (can be force with the PRAGMA)
|
|
57901
57941
|
auto &config = ClientConfig::GetConfig(context);
|
|
57902
57942
|
state->rhs_global_sort_state.external = config.force_external;
|
|
@@ -57963,6 +58003,94 @@ unique_ptr<LocalSinkState> PhysicalPiecewiseMergeJoin::GetLocalSinkState(Executi
|
|
|
57963
58003
|
return move(result);
|
|
57964
58004
|
}
|
|
57965
58005
|
|
|
58006
|
+
static idx_t PiecewiseMergeNulls(DataChunk &keys, const vector<JoinCondition> &conditions) {
|
|
58007
|
+
// Merge the validity masks of the comparison keys into the primary
|
|
58008
|
+
// Return the number of NULLs in the resulting chunk
|
|
58009
|
+
D_ASSERT(keys.ColumnCount() > 0);
|
|
58010
|
+
const auto count = keys.size();
|
|
58011
|
+
|
|
58012
|
+
size_t all_constant = 0;
|
|
58013
|
+
for (auto &v : keys.data) {
|
|
58014
|
+
if (v.GetVectorType() == VectorType::CONSTANT_VECTOR) {
|
|
58015
|
+
++all_constant;
|
|
58016
|
+
}
|
|
58017
|
+
}
|
|
58018
|
+
|
|
58019
|
+
auto &primary = keys.data[0];
|
|
58020
|
+
if (all_constant == keys.data.size()) {
|
|
58021
|
+
// Either all NULL or no NULLs
|
|
58022
|
+
for (auto &v : keys.data) {
|
|
58023
|
+
if (ConstantVector::IsNull(v)) {
|
|
58024
|
+
ConstantVector::SetNull(primary, true);
|
|
58025
|
+
return count;
|
|
58026
|
+
}
|
|
58027
|
+
}
|
|
58028
|
+
return 0;
|
|
58029
|
+
} else if (keys.ColumnCount() > 1) {
|
|
58030
|
+
// Normalify the primary, as it will need to merge arbitrary validity masks
|
|
58031
|
+
primary.Normalify(count);
|
|
58032
|
+
auto &pvalidity = FlatVector::Validity(primary);
|
|
58033
|
+
for (size_t c = 1; c < keys.data.size(); ++c) {
|
|
58034
|
+
// Skip comparisons that accept NULLs
|
|
58035
|
+
if (conditions[c].comparison == ExpressionType::COMPARE_DISTINCT_FROM) {
|
|
58036
|
+
continue;
|
|
58037
|
+
}
|
|
58038
|
+
// Orrify the rest, as the sort code will do this anyway.
|
|
58039
|
+
auto &v = keys.data[c];
|
|
58040
|
+
VectorData vdata;
|
|
58041
|
+
v.Orrify(count, vdata);
|
|
58042
|
+
auto &vvalidity = vdata.validity;
|
|
58043
|
+
if (vvalidity.AllValid()) {
|
|
58044
|
+
continue;
|
|
58045
|
+
}
|
|
58046
|
+
pvalidity.EnsureWritable();
|
|
58047
|
+
switch (v.GetVectorType()) {
|
|
58048
|
+
case VectorType::FLAT_VECTOR: {
|
|
58049
|
+
// Merge entire entries
|
|
58050
|
+
auto pmask = pvalidity.GetData();
|
|
58051
|
+
const auto entry_count = pvalidity.EntryCount(count);
|
|
58052
|
+
for (idx_t entry_idx = 0; entry_idx < entry_count; ++entry_idx) {
|
|
58053
|
+
pmask[entry_idx] &= vvalidity.GetValidityEntry(entry_idx);
|
|
58054
|
+
}
|
|
58055
|
+
break;
|
|
58056
|
+
}
|
|
58057
|
+
case VectorType::CONSTANT_VECTOR:
|
|
58058
|
+
// All or nothing
|
|
58059
|
+
if (ConstantVector::IsNull(v)) {
|
|
58060
|
+
pvalidity.SetAllInvalid(count);
|
|
58061
|
+
return count;
|
|
58062
|
+
}
|
|
58063
|
+
break;
|
|
58064
|
+
default:
|
|
58065
|
+
// One by one
|
|
58066
|
+
for (idx_t i = 0; i < count; ++i) {
|
|
58067
|
+
const auto idx = vdata.sel->get_index(i);
|
|
58068
|
+
if (!vvalidity.RowIsValidUnsafe(idx)) {
|
|
58069
|
+
pvalidity.SetInvalidUnsafe(i);
|
|
58070
|
+
}
|
|
58071
|
+
}
|
|
58072
|
+
break;
|
|
58073
|
+
}
|
|
58074
|
+
}
|
|
58075
|
+
return count - pvalidity.CountValid(count);
|
|
58076
|
+
} else {
|
|
58077
|
+
return count - CountValid(primary, count);
|
|
58078
|
+
}
|
|
58079
|
+
}
|
|
58080
|
+
|
|
58081
|
+
static inline void SinkPiecewiseMergeChunk(LocalSortState &sort_state, DataChunk &join_keys, DataChunk &input) {
|
|
58082
|
+
if (join_keys.ColumnCount() > 1) {
|
|
58083
|
+
// Only sort the first key
|
|
58084
|
+
DataChunk join_head;
|
|
58085
|
+
join_head.data.emplace_back(Vector(join_keys.data[0]));
|
|
58086
|
+
join_head.SetCardinality(join_keys.size());
|
|
58087
|
+
|
|
58088
|
+
sort_state.SinkChunk(join_head, input);
|
|
58089
|
+
} else {
|
|
58090
|
+
sort_state.SinkChunk(join_keys, input);
|
|
58091
|
+
}
|
|
58092
|
+
}
|
|
58093
|
+
|
|
57966
58094
|
SinkResultType PhysicalPiecewiseMergeJoin::Sink(ExecutionContext &context, GlobalSinkState &gstate_p,
|
|
57967
58095
|
LocalSinkState &lstate_p, DataChunk &input) const {
|
|
57968
58096
|
auto &gstate = (MergeJoinGlobalState &)gstate_p;
|
|
@@ -57982,15 +58110,11 @@ SinkResultType PhysicalPiecewiseMergeJoin::Sink(ExecutionContext &context, Globa
|
|
|
57982
58110
|
lstate.rhs_executor.Execute(input, join_keys);
|
|
57983
58111
|
|
|
57984
58112
|
// Count the NULLs so we can exclude them later
|
|
57985
|
-
|
|
57986
|
-
|
|
57987
|
-
for (auto &key : join_keys.data) {
|
|
57988
|
-
lstate.rhs_has_null += (count - CountValid(key, count));
|
|
57989
|
-
}
|
|
57990
|
-
lstate.rhs_count += count;
|
|
58113
|
+
lstate.rhs_has_null += PiecewiseMergeNulls(join_keys, conditions);
|
|
58114
|
+
lstate.rhs_count += join_keys.size();
|
|
57991
58115
|
|
|
57992
58116
|
// Sink the data into the local sort state
|
|
57993
|
-
local_sort_state
|
|
58117
|
+
SinkPiecewiseMergeChunk(local_sort_state, join_keys, input);
|
|
57994
58118
|
|
|
57995
58119
|
// When sorting data reaches a certain size, we sort it
|
|
57996
58120
|
if (local_sort_state.SizeInBytes() >= gstate.memory_per_thread) {
|
|
@@ -58115,9 +58239,9 @@ public:
|
|
|
58115
58239
|
: op(op), buffer_manager(buffer_manager), force_external(force_external), left_position(0), first_fetch(true),
|
|
58116
58240
|
finished(true), right_position(0), right_chunk_index(0) {
|
|
58117
58241
|
vector<LogicalType> condition_types;
|
|
58118
|
-
for (auto &
|
|
58119
|
-
lhs_executor.AddExpression(*
|
|
58120
|
-
condition_types.push_back(
|
|
58242
|
+
for (auto &order : op.lhs_orders) {
|
|
58243
|
+
lhs_executor.AddExpression(*order.expression);
|
|
58244
|
+
condition_types.push_back(order.expression->return_type);
|
|
58121
58245
|
}
|
|
58122
58246
|
lhs_keys.Initialize(condition_types);
|
|
58123
58247
|
if (IsLeftOuterJoin(op.join_type)) {
|
|
@@ -58125,6 +58249,18 @@ public:
|
|
|
58125
58249
|
memset(lhs_found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE);
|
|
58126
58250
|
}
|
|
58127
58251
|
lhs_layout.Initialize(op.children[0]->types);
|
|
58252
|
+
lhs_payload.Initialize(op.children[0]->types);
|
|
58253
|
+
|
|
58254
|
+
lhs_order.emplace_back(op.lhs_orders[0].Copy());
|
|
58255
|
+
|
|
58256
|
+
// Set up shared data for multiple predicates
|
|
58257
|
+
sel.Initialize(STANDARD_VECTOR_SIZE);
|
|
58258
|
+
condition_types.clear();
|
|
58259
|
+
for (auto &order : op.rhs_orders) {
|
|
58260
|
+
rhs_executor.AddExpression(*order.expression);
|
|
58261
|
+
condition_types.push_back(order.expression->return_type);
|
|
58262
|
+
}
|
|
58263
|
+
rhs_keys.Initialize(condition_types);
|
|
58128
58264
|
}
|
|
58129
58265
|
|
|
58130
58266
|
const PhysicalPiecewiseMergeJoin &op;
|
|
@@ -58133,8 +58269,10 @@ public:
|
|
|
58133
58269
|
|
|
58134
58270
|
// Block sorting
|
|
58135
58271
|
DataChunk lhs_keys;
|
|
58272
|
+
DataChunk lhs_payload;
|
|
58136
58273
|
ExpressionExecutor lhs_executor;
|
|
58137
58274
|
unique_ptr<bool[]> lhs_found_match;
|
|
58275
|
+
vector<BoundOrderByNode> lhs_order;
|
|
58138
58276
|
RowLayout lhs_layout;
|
|
58139
58277
|
unique_ptr<LocalSortState> lhs_local_state;
|
|
58140
58278
|
unique_ptr<GlobalSortState> lhs_global_state;
|
|
@@ -58151,6 +58289,12 @@ public:
|
|
|
58151
58289
|
idx_t right_chunk_index;
|
|
58152
58290
|
idx_t right_base;
|
|
58153
58291
|
|
|
58292
|
+
// Secondary predicate shared data
|
|
58293
|
+
SelectionVector sel;
|
|
58294
|
+
DataChunk rhs_keys;
|
|
58295
|
+
DataChunk rhs_input;
|
|
58296
|
+
ExpressionExecutor rhs_executor;
|
|
58297
|
+
|
|
58154
58298
|
public:
|
|
58155
58299
|
void ResolveJoinKeys(DataChunk &input) {
|
|
58156
58300
|
// resolve the join keys for the input
|
|
@@ -58158,18 +58302,14 @@ public:
|
|
|
58158
58302
|
lhs_executor.Execute(input, lhs_keys);
|
|
58159
58303
|
|
|
58160
58304
|
// Count the NULLs so we can exclude them later
|
|
58161
|
-
// TODO: Sort any multi-comparison NULLs to the end using an initial sort column
|
|
58162
58305
|
lhs_count = lhs_keys.size();
|
|
58163
|
-
|
|
58164
|
-
lhs_has_null = lhs_count - CountValid(key, lhs_count);
|
|
58165
|
-
break;
|
|
58166
|
-
}
|
|
58306
|
+
lhs_has_null = PiecewiseMergeNulls(lhs_keys, op.conditions);
|
|
58167
58307
|
|
|
58168
58308
|
// sort by join key
|
|
58169
|
-
lhs_global_state = make_unique<GlobalSortState>(buffer_manager,
|
|
58309
|
+
lhs_global_state = make_unique<GlobalSortState>(buffer_manager, lhs_order, lhs_layout);
|
|
58170
58310
|
lhs_local_state = make_unique<LocalSortState>();
|
|
58171
58311
|
lhs_local_state->Initialize(*lhs_global_state, buffer_manager);
|
|
58172
|
-
lhs_local_state
|
|
58312
|
+
SinkPiecewiseMergeChunk(*lhs_local_state, lhs_keys, input);
|
|
58173
58313
|
|
|
58174
58314
|
// Set external (can be force with the PRAGMA)
|
|
58175
58315
|
lhs_global_state->external = force_external;
|
|
@@ -58180,6 +58320,17 @@ public:
|
|
|
58180
58320
|
merge_sorter.PerformInMergeRound();
|
|
58181
58321
|
lhs_global_state->CompleteMergeRound();
|
|
58182
58322
|
}
|
|
58323
|
+
|
|
58324
|
+
// Scan the sorted payload
|
|
58325
|
+
D_ASSERT(lhs_global_state->sorted_blocks.size() == 1);
|
|
58326
|
+
|
|
58327
|
+
PayloadScanner scanner(*lhs_global_state->sorted_blocks[0]->payload_data, *lhs_global_state);
|
|
58328
|
+
lhs_payload.Reset();
|
|
58329
|
+
scanner.Scan(lhs_payload);
|
|
58330
|
+
|
|
58331
|
+
// Recompute the sorted keys from the sorted input
|
|
58332
|
+
lhs_keys.Reset();
|
|
58333
|
+
lhs_executor.Execute(lhs_payload, lhs_keys);
|
|
58183
58334
|
}
|
|
58184
58335
|
|
|
58185
58336
|
void Finalize(PhysicalOperator *op, ExecutionContext &context) override {
|
|
@@ -58228,8 +58379,8 @@ struct BlockMergeInfo {
|
|
|
58228
58379
|
}
|
|
58229
58380
|
};
|
|
58230
58381
|
|
|
58231
|
-
static
|
|
58232
|
-
|
|
58382
|
+
static idx_t SliceSortedPayload(DataChunk &payload, BlockMergeInfo &info, const idx_t result_count,
|
|
58383
|
+
const idx_t left_cols = 0) {
|
|
58233
58384
|
// There should only be one sorted block if they have been sorted
|
|
58234
58385
|
D_ASSERT(info.state.sorted_blocks.size() == 1);
|
|
58235
58386
|
SBScanState read_state(info.state.buffer_manager, info.state);
|
|
@@ -58238,33 +58389,50 @@ static void SliceSortedPayload(DataChunk &payload, BlockMergeInfo &info, const i
|
|
|
58238
58389
|
|
|
58239
58390
|
// We have to create pointers for the entire block
|
|
58240
58391
|
// because unswizzle works on ranges not selections.
|
|
58241
|
-
|
|
58392
|
+
const auto first_idx = info.result.get_index(0);
|
|
58393
|
+
read_state.SetIndices(info.block_idx, info.base_idx + first_idx);
|
|
58242
58394
|
read_state.PinData(sorted_data);
|
|
58243
58395
|
const auto data_ptr = read_state.DataPtr(sorted_data);
|
|
58244
|
-
const auto next = vcount - info.base_idx;
|
|
58245
58396
|
|
|
58246
58397
|
// Set up a batch of pointers to scan data from
|
|
58247
|
-
Vector addresses(LogicalType::POINTER,
|
|
58398
|
+
Vector addresses(LogicalType::POINTER, result_count);
|
|
58248
58399
|
auto data_pointers = FlatVector::GetData<data_ptr_t>(addresses);
|
|
58249
58400
|
|
|
58250
|
-
// Set up the data pointers
|
|
58401
|
+
// Set up the data pointers for the values that are actually referenced
|
|
58402
|
+
// and normalise the selection vector to zero
|
|
58251
58403
|
data_ptr_t row_ptr = data_ptr;
|
|
58252
58404
|
const idx_t &row_width = sorted_data.layout.GetRowWidth();
|
|
58253
|
-
|
|
58254
|
-
|
|
58255
|
-
|
|
58405
|
+
|
|
58406
|
+
auto prev_idx = first_idx;
|
|
58407
|
+
info.result.set_index(0, 0);
|
|
58408
|
+
idx_t addr_count = 0;
|
|
58409
|
+
data_pointers[addr_count++] = row_ptr;
|
|
58410
|
+
for (idx_t i = 1; i < result_count; ++i) {
|
|
58411
|
+
const auto row_idx = info.result.get_index(i);
|
|
58412
|
+
info.result.set_index(i, row_idx - first_idx);
|
|
58413
|
+
if (row_idx == prev_idx) {
|
|
58414
|
+
continue;
|
|
58415
|
+
}
|
|
58416
|
+
row_ptr += (row_idx - prev_idx) * row_width;
|
|
58417
|
+
data_pointers[addr_count++] = row_ptr;
|
|
58418
|
+
prev_idx = row_idx;
|
|
58256
58419
|
}
|
|
58257
58420
|
// Unswizzle the offsets back to pointers (if needed)
|
|
58258
58421
|
if (!sorted_data.layout.AllConstant() && info.state.external) {
|
|
58422
|
+
const auto next = prev_idx + 1;
|
|
58259
58423
|
RowOperations::UnswizzlePointers(sorted_data.layout, data_ptr, read_state.payload_heap_handle->Ptr(), next);
|
|
58260
58424
|
}
|
|
58261
58425
|
|
|
58262
58426
|
// Deserialize the payload data
|
|
58427
|
+
auto sel = FlatVector::IncrementalSelectionVector();
|
|
58263
58428
|
for (idx_t col_idx = 0; col_idx < sorted_data.layout.ColumnCount(); col_idx++) {
|
|
58264
58429
|
const auto col_offset = sorted_data.layout.GetOffsets()[col_idx];
|
|
58265
|
-
|
|
58266
|
-
|
|
58430
|
+
auto &col = payload.data[left_cols + col_idx];
|
|
58431
|
+
RowOperations::Gather(addresses, *sel, col, *sel, addr_count, col_offset, col_idx);
|
|
58432
|
+
col.Slice(info.result, result_count);
|
|
58267
58433
|
}
|
|
58434
|
+
|
|
58435
|
+
return first_idx;
|
|
58268
58436
|
}
|
|
58269
58437
|
|
|
58270
58438
|
static void MergeJoinPinSortingBlock(SBScanState &scan, const idx_t block_idx) {
|
|
@@ -58372,16 +58540,9 @@ void PhysicalPiecewiseMergeJoin::ResolveSimpleJoin(ExecutionContext &context, Da
|
|
|
58372
58540
|
memset(found_match, 0, sizeof(found_match));
|
|
58373
58541
|
MergeJoinSimpleBlocks(state, gstate, found_match, conditions[0].comparison);
|
|
58374
58542
|
|
|
58375
|
-
//
|
|
58376
|
-
idx_t left_position = 0;
|
|
58543
|
+
// use the sorted payload
|
|
58377
58544
|
const auto lhs_not_null = state.lhs_count - state.lhs_has_null;
|
|
58378
|
-
|
|
58379
|
-
left_info.result.Initialize(nullptr);
|
|
58380
|
-
|
|
58381
|
-
DataChunk payload;
|
|
58382
|
-
payload.Initialize(input.GetTypes());
|
|
58383
|
-
SliceSortedPayload(payload, left_info, state.lhs_count, state.lhs_count);
|
|
58384
|
-
payload.SetCardinality(state.lhs_count);
|
|
58545
|
+
auto &payload = state.lhs_payload;
|
|
58385
58546
|
|
|
58386
58547
|
// now construct the result based on the join result
|
|
58387
58548
|
switch (join_type) {
|
|
@@ -58488,11 +58649,37 @@ static idx_t MergeJoinComplexBlocks(BlockMergeInfo &l, BlockMergeInfo &r, const
|
|
|
58488
58649
|
return result_count;
|
|
58489
58650
|
}
|
|
58490
58651
|
|
|
58652
|
+
static idx_t SelectJoinTail(const ExpressionType &condition, Vector &left, Vector &right, const SelectionVector *sel,
|
|
58653
|
+
idx_t count, SelectionVector *true_sel) {
|
|
58654
|
+
switch (condition) {
|
|
58655
|
+
case ExpressionType::COMPARE_NOTEQUAL:
|
|
58656
|
+
return VectorOperations::NotEquals(left, right, sel, count, true_sel, nullptr);
|
|
58657
|
+
case ExpressionType::COMPARE_LESSTHAN:
|
|
58658
|
+
return VectorOperations::LessThan(left, right, sel, count, true_sel, nullptr);
|
|
58659
|
+
case ExpressionType::COMPARE_GREATERTHAN:
|
|
58660
|
+
return VectorOperations::GreaterThan(left, right, sel, count, true_sel, nullptr);
|
|
58661
|
+
case ExpressionType::COMPARE_LESSTHANOREQUALTO:
|
|
58662
|
+
return VectorOperations::LessThanEquals(left, right, sel, count, true_sel, nullptr);
|
|
58663
|
+
case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
|
|
58664
|
+
return VectorOperations::GreaterThanEquals(left, right, sel, count, true_sel, nullptr);
|
|
58665
|
+
case ExpressionType::COMPARE_DISTINCT_FROM:
|
|
58666
|
+
return VectorOperations::DistinctFrom(left, right, sel, count, true_sel, nullptr);
|
|
58667
|
+
case ExpressionType::COMPARE_NOT_DISTINCT_FROM:
|
|
58668
|
+
case ExpressionType::COMPARE_EQUAL:
|
|
58669
|
+
default:
|
|
58670
|
+
throw InternalException("Unsupported comparison type for PhysicalPiecewiseMergeJoin");
|
|
58671
|
+
}
|
|
58672
|
+
|
|
58673
|
+
return count;
|
|
58674
|
+
}
|
|
58675
|
+
|
|
58491
58676
|
OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionContext &context, DataChunk &input,
|
|
58492
58677
|
DataChunk &chunk, OperatorState &state_p) const {
|
|
58493
58678
|
auto &state = (PiecewiseMergeJoinState &)state_p;
|
|
58494
58679
|
auto &gstate = (MergeJoinGlobalState &)*sink_state;
|
|
58495
58680
|
auto &rsorted = *gstate.rhs_global_sort_state.sorted_blocks[0];
|
|
58681
|
+
const auto left_cols = input.ColumnCount();
|
|
58682
|
+
const auto tail_cols = conditions.size() - 1;
|
|
58496
58683
|
do {
|
|
58497
58684
|
if (state.first_fetch) {
|
|
58498
58685
|
state.ResolveJoinKeys(input);
|
|
@@ -58508,7 +58695,7 @@ OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionConte
|
|
|
58508
58695
|
if (IsLeftOuterJoin(join_type)) {
|
|
58509
58696
|
// left join: before we move to the next chunk, see if we need to output any vectors that didn't
|
|
58510
58697
|
// have a match found
|
|
58511
|
-
PhysicalJoin::ConstructLeftJoinResult(
|
|
58698
|
+
PhysicalJoin::ConstructLeftJoinResult(state.lhs_payload, chunk, state.lhs_found_match.get());
|
|
58512
58699
|
memset(state.lhs_found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE);
|
|
58513
58700
|
}
|
|
58514
58701
|
state.first_fetch = true;
|
|
@@ -58537,22 +58724,60 @@ OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionConte
|
|
|
58537
58724
|
state.finished = true;
|
|
58538
58725
|
}
|
|
58539
58726
|
} else {
|
|
58727
|
+
// found matches: extract them
|
|
58728
|
+
chunk.Reset();
|
|
58729
|
+
for (idx_t c = 0; c < state.lhs_payload.ColumnCount(); ++c) {
|
|
58730
|
+
chunk.data[c].Slice(state.lhs_payload.data[c], left_info.result, result_count);
|
|
58731
|
+
}
|
|
58732
|
+
const auto first_idx = SliceSortedPayload(chunk, right_info, result_count, left_cols);
|
|
58733
|
+
chunk.SetCardinality(result_count);
|
|
58734
|
+
|
|
58735
|
+
auto sel = FlatVector::IncrementalSelectionVector();
|
|
58736
|
+
if (tail_cols) {
|
|
58737
|
+
// If there are more expressions to compute,
|
|
58738
|
+
// split the result chunk into the left and right halves
|
|
58739
|
+
// so we can compute the values for comparison.
|
|
58740
|
+
chunk.Split(state.rhs_input, left_cols);
|
|
58741
|
+
state.rhs_executor.SetChunk(state.rhs_input);
|
|
58742
|
+
state.rhs_keys.Reset();
|
|
58743
|
+
|
|
58744
|
+
auto tail_count = result_count;
|
|
58745
|
+
for (size_t cmp_idx = 1; cmp_idx < conditions.size(); ++cmp_idx) {
|
|
58746
|
+
Vector left(state.lhs_keys.data[cmp_idx]);
|
|
58747
|
+
left.Slice(left_info.result, result_count);
|
|
58748
|
+
|
|
58749
|
+
auto &right = state.rhs_keys.data[cmp_idx];
|
|
58750
|
+
state.rhs_executor.ExecuteExpression(cmp_idx, right);
|
|
58751
|
+
|
|
58752
|
+
if (tail_count < result_count) {
|
|
58753
|
+
left.Slice(*sel, tail_count);
|
|
58754
|
+
right.Slice(*sel, tail_count);
|
|
58755
|
+
}
|
|
58756
|
+
tail_count =
|
|
58757
|
+
SelectJoinTail(conditions[cmp_idx].comparison, left, right, sel, tail_count, &state.sel);
|
|
58758
|
+
sel = &state.sel;
|
|
58759
|
+
}
|
|
58760
|
+
chunk.Fuse(state.rhs_input);
|
|
58761
|
+
|
|
58762
|
+
if (tail_count < result_count) {
|
|
58763
|
+
result_count = tail_count;
|
|
58764
|
+
chunk.Slice(*sel, result_count);
|
|
58765
|
+
}
|
|
58766
|
+
}
|
|
58767
|
+
|
|
58540
58768
|
// found matches: mark the found matches if required
|
|
58541
58769
|
if (state.lhs_found_match) {
|
|
58542
58770
|
for (idx_t i = 0; i < result_count; i++) {
|
|
58543
|
-
state.lhs_found_match[left_info.result[i]] = true;
|
|
58771
|
+
state.lhs_found_match[left_info.result[sel->get_index(i)]] = true;
|
|
58544
58772
|
}
|
|
58545
58773
|
}
|
|
58546
58774
|
if (gstate.rhs_found_match) {
|
|
58547
58775
|
// Absolute position of the block + start position inside that block
|
|
58548
|
-
const idx_t base_index =
|
|
58776
|
+
const idx_t base_index = right_info.base_idx + first_idx;
|
|
58549
58777
|
for (idx_t i = 0; i < result_count; i++) {
|
|
58550
|
-
gstate.rhs_found_match[base_index + right_info.result[i]] = true;
|
|
58778
|
+
gstate.rhs_found_match[base_index + right_info.result[sel->get_index(i)]] = true;
|
|
58551
58779
|
}
|
|
58552
58780
|
}
|
|
58553
|
-
// found matches: output them
|
|
58554
|
-
SliceSortedPayload(chunk, left_info, result_count, input.size());
|
|
58555
|
-
SliceSortedPayload(chunk, right_info, result_count, right_info.entry_idx + 1, input.ColumnCount());
|
|
58556
58781
|
chunk.SetCardinality(result_count);
|
|
58557
58782
|
chunk.Verify();
|
|
58558
58783
|
}
|
|
@@ -58638,7 +58863,7 @@ void PhysicalPiecewiseMergeJoin::GetData(ExecutionContext &context, DataChunk &r
|
|
|
58638
58863
|
|
|
58639
58864
|
// ConstructFullOuterJoinResult(sink.rhs_found_match.get(), sink.right_chunks, chunk, state.right_outer_position);
|
|
58640
58865
|
DataChunk rhs_chunk;
|
|
58641
|
-
rhs_chunk.Initialize(
|
|
58866
|
+
rhs_chunk.Initialize(sink.rhs_global_sort_state.payload_layout.GetTypes());
|
|
58642
58867
|
SelectionVector rsel(STANDARD_VECTOR_SIZE);
|
|
58643
58868
|
for (;;) {
|
|
58644
58869
|
// Read the next sorted chunk
|
|
@@ -58660,12 +58885,14 @@ void PhysicalPiecewiseMergeJoin::GetData(ExecutionContext &context, DataChunk &r
|
|
|
58660
58885
|
|
|
58661
58886
|
if (result_count > 0) {
|
|
58662
58887
|
// if there were any tuples that didn't find a match, output them
|
|
58663
|
-
const idx_t left_column_count =
|
|
58888
|
+
const idx_t left_column_count = children[0]->types.size();
|
|
58664
58889
|
for (idx_t col_idx = 0; col_idx < left_column_count; ++col_idx) {
|
|
58665
58890
|
result.data[col_idx].SetVectorType(VectorType::CONSTANT_VECTOR);
|
|
58666
58891
|
ConstantVector::SetNull(result.data[col_idx], true);
|
|
58667
58892
|
}
|
|
58668
|
-
|
|
58893
|
+
const idx_t right_column_count = children[1]->types.size();
|
|
58894
|
+
;
|
|
58895
|
+
for (idx_t col_idx = 0; col_idx < right_column_count; ++col_idx) {
|
|
58669
58896
|
result.data[left_column_count + col_idx].Slice(rhs_chunk.data[col_idx], rsel, result_count);
|
|
58670
58897
|
}
|
|
58671
58898
|
result.SetCardinality(result_count);
|
|
@@ -65382,16 +65609,28 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalComparison
|
|
|
65382
65609
|
}
|
|
65383
65610
|
|
|
65384
65611
|
bool has_equality = false;
|
|
65385
|
-
bool has_inequality = false;
|
|
65612
|
+
// bool has_inequality = false;
|
|
65613
|
+
bool has_range = false;
|
|
65386
65614
|
bool has_null_equal_conditions = false;
|
|
65387
|
-
for (
|
|
65388
|
-
|
|
65389
|
-
|
|
65615
|
+
for (size_t c = 0; c < op.conditions.size(); ++c) {
|
|
65616
|
+
auto &cond = op.conditions[c];
|
|
65617
|
+
switch (cond.comparison) {
|
|
65618
|
+
case ExpressionType::COMPARE_EQUAL:
|
|
65619
|
+
case ExpressionType::COMPARE_NOT_DISTINCT_FROM:
|
|
65390
65620
|
has_equality = true;
|
|
65391
|
-
|
|
65392
|
-
|
|
65393
|
-
|
|
65394
|
-
|
|
65621
|
+
break;
|
|
65622
|
+
case ExpressionType::COMPARE_LESSTHAN:
|
|
65623
|
+
case ExpressionType::COMPARE_GREATERTHAN:
|
|
65624
|
+
case ExpressionType::COMPARE_LESSTHANOREQUALTO:
|
|
65625
|
+
case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
|
|
65626
|
+
has_range = true;
|
|
65627
|
+
break;
|
|
65628
|
+
case ExpressionType::COMPARE_NOTEQUAL:
|
|
65629
|
+
case ExpressionType::COMPARE_DISTINCT_FROM:
|
|
65630
|
+
// has_inequality = true;
|
|
65631
|
+
break;
|
|
65632
|
+
default:
|
|
65633
|
+
throw NotImplementedException("Unimplemented comparison join");
|
|
65395
65634
|
}
|
|
65396
65635
|
if (cond.null_values_are_equal) {
|
|
65397
65636
|
has_null_equal_conditions = true;
|
|
@@ -65428,8 +65667,17 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalComparison
|
|
|
65428
65667
|
op.estimated_cardinality, perfect_join_stats);
|
|
65429
65668
|
|
|
65430
65669
|
} else {
|
|
65431
|
-
|
|
65432
|
-
|
|
65670
|
+
bool can_merge = has_range;
|
|
65671
|
+
switch (op.join_type) {
|
|
65672
|
+
case JoinType::SEMI:
|
|
65673
|
+
case JoinType::ANTI:
|
|
65674
|
+
case JoinType::MARK:
|
|
65675
|
+
can_merge = can_merge && op.conditions.size() == 1;
|
|
65676
|
+
break;
|
|
65677
|
+
default:
|
|
65678
|
+
break;
|
|
65679
|
+
}
|
|
65680
|
+
if (can_merge) {
|
|
65433
65681
|
// range join: use piecewise merge join
|
|
65434
65682
|
plan = make_unique<PhysicalPiecewiseMergeJoin>(op, move(left), move(right), move(op.conditions),
|
|
65435
65683
|
op.join_type, op.estimated_cardinality);
|
package/src/duckdb.hpp
CHANGED
|
@@ -11,8 +11,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|
|
11
11
|
#pragma once
|
|
12
12
|
#define DUCKDB_AMALGAMATION 1
|
|
13
13
|
#define DUCKDB_AMALGAMATION_EXTENDED 1
|
|
14
|
-
#define DUCKDB_SOURCE_ID "
|
|
15
|
-
#define DUCKDB_VERSION "v0.3.3-
|
|
14
|
+
#define DUCKDB_SOURCE_ID "271ccd2bd"
|
|
15
|
+
#define DUCKDB_VERSION "v0.3.3-dev508"
|
|
16
16
|
//===----------------------------------------------------------------------===//
|
|
17
17
|
// DuckDB
|
|
18
18
|
//
|
|
@@ -4114,6 +4114,9 @@ public:
|
|
|
4114
4114
|
//! Splits the DataChunk in two
|
|
4115
4115
|
DUCKDB_API void Split(DataChunk &other, idx_t split_idx);
|
|
4116
4116
|
|
|
4117
|
+
//! Fuses a DataChunk onto the right of this one, and destroys the other. Inverse of Split.
|
|
4118
|
+
DUCKDB_API void Fuse(DataChunk &other);
|
|
4119
|
+
|
|
4117
4120
|
//! Turn all the vectors from the chunk into flat vectors
|
|
4118
4121
|
DUCKDB_API void Normalify();
|
|
4119
4122
|
|