duckdb 0.3.3-dev482.0 → 0.3.3-dev516.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 +328 -69
- package/src/duckdb.hpp +7 -3
- package/src/parquet-amalgamation.cpp +30831 -30831
package/package.json
CHANGED
package/src/duckdb.cpp
CHANGED
|
@@ -2639,6 +2639,8 @@ protected:
|
|
|
2639
2639
|
|
|
2640
2640
|
|
|
2641
2641
|
|
|
2642
|
+
|
|
2643
|
+
|
|
2642
2644
|
#include <algorithm>
|
|
2643
2645
|
#include <sstream>
|
|
2644
2646
|
|
|
@@ -2929,6 +2931,15 @@ unique_ptr<CatalogEntry> TableCatalogEntry::SetDefault(ClientContext &context, S
|
|
|
2929
2931
|
}
|
|
2930
2932
|
|
|
2931
2933
|
unique_ptr<CatalogEntry> TableCatalogEntry::ChangeColumnType(ClientContext &context, ChangeColumnTypeInfo &info) {
|
|
2934
|
+
if (info.target_type.id() == LogicalTypeId::USER) {
|
|
2935
|
+
auto &user_type_name = UserType::GetTypeName(info.target_type);
|
|
2936
|
+
auto user_type_catalog = (TypeCatalogEntry *)context.db->GetCatalog().GetEntry(
|
|
2937
|
+
context, CatalogType::TYPE_ENTRY, schema->name, user_type_name, true);
|
|
2938
|
+
if (!user_type_catalog) {
|
|
2939
|
+
throw NotImplementedException("DataType %s not supported yet...\n", user_type_name);
|
|
2940
|
+
}
|
|
2941
|
+
info.target_type = user_type_catalog->user_type;
|
|
2942
|
+
}
|
|
2932
2943
|
auto create_info = make_unique<CreateTableInfo>(schema->name, name);
|
|
2933
2944
|
idx_t change_idx = GetColumnIndex(info.column_name);
|
|
2934
2945
|
for (idx_t i = 0; i < columns.size(); i++) {
|
|
@@ -13646,7 +13657,7 @@ void FileSystem::RemoveDirectory(const string &directory) {
|
|
|
13646
13657
|
throw NotImplementedException("%s: RemoveDirectory is not implemented!", GetName());
|
|
13647
13658
|
}
|
|
13648
13659
|
|
|
13649
|
-
bool FileSystem::ListFiles(const string &directory, const std::function<void(string
|
|
13660
|
+
bool FileSystem::ListFiles(const string &directory, const std::function<void(const string &, bool)> &callback) {
|
|
13650
13661
|
throw NotImplementedException("%s: ListFiles is not implemented!", GetName());
|
|
13651
13662
|
}
|
|
13652
13663
|
|
|
@@ -15771,7 +15782,7 @@ public:
|
|
|
15771
15782
|
//! Recursively remove a directory and all files in it
|
|
15772
15783
|
void RemoveDirectory(const string &directory) override;
|
|
15773
15784
|
//! List files in a directory, invoking the callback method for each one with (filename, is_dir)
|
|
15774
|
-
bool ListFiles(const string &directory, const std::function<void(string
|
|
15785
|
+
bool ListFiles(const string &directory, const std::function<void(const string &, bool)> &callback) override;
|
|
15775
15786
|
//! Move a file from source path to the target, StorageManager relies on this being an atomic action for ACID
|
|
15776
15787
|
//! properties
|
|
15777
15788
|
void MoveFile(const string &source, const string &target) override;
|
|
@@ -16283,7 +16294,7 @@ void LocalFileSystem::RemoveFile(const string &filename) {
|
|
|
16283
16294
|
}
|
|
16284
16295
|
}
|
|
16285
16296
|
|
|
16286
|
-
bool LocalFileSystem::ListFiles(const string &directory, const std::function<void(string
|
|
16297
|
+
bool LocalFileSystem::ListFiles(const string &directory, const std::function<void(const string &, bool)> &callback) {
|
|
16287
16298
|
if (!DirectoryExists(directory)) {
|
|
16288
16299
|
return false;
|
|
16289
16300
|
}
|
|
@@ -16597,7 +16608,7 @@ void LocalFileSystem::RemoveFile(const string &filename) {
|
|
|
16597
16608
|
DeleteFileW(unicode_path.c_str());
|
|
16598
16609
|
}
|
|
16599
16610
|
|
|
16600
|
-
bool LocalFileSystem::ListFiles(const string &directory, const std::function<void(string
|
|
16611
|
+
bool LocalFileSystem::ListFiles(const string &directory, const std::function<void(const string &, bool)> &callback) {
|
|
16601
16612
|
string search_dir = JoinPath(directory, "*");
|
|
16602
16613
|
|
|
16603
16614
|
auto unicode_path = WindowsUtil::UTF8ToUnicode(search_dir.c_str());
|
|
@@ -32766,6 +32777,16 @@ void DataChunk::Split(DataChunk &other, idx_t split_idx) {
|
|
|
32766
32777
|
other.SetCardinality(*this);
|
|
32767
32778
|
}
|
|
32768
32779
|
|
|
32780
|
+
void DataChunk::Fuse(DataChunk &other) {
|
|
32781
|
+
D_ASSERT(other.size() == size());
|
|
32782
|
+
const idx_t num_cols = other.data.size();
|
|
32783
|
+
for (idx_t col_idx = 0; col_idx < num_cols; ++col_idx) {
|
|
32784
|
+
data.emplace_back(move(other.data[col_idx]));
|
|
32785
|
+
vector_caches.emplace_back(move(other.vector_caches[col_idx]));
|
|
32786
|
+
}
|
|
32787
|
+
other.Destroy();
|
|
32788
|
+
}
|
|
32789
|
+
|
|
32769
32790
|
void DataChunk::Append(const DataChunk &other, bool resize, SelectionVector *sel, idx_t sel_count) {
|
|
32770
32791
|
idx_t new_size = sel ? size() + sel_count : size() + other.size();
|
|
32771
32792
|
if (other.size() == 0) {
|
|
@@ -45541,7 +45562,7 @@ public:
|
|
|
45541
45562
|
FindFileSystem(directory)->RemoveDirectory(directory);
|
|
45542
45563
|
}
|
|
45543
45564
|
|
|
45544
|
-
bool ListFiles(const string &directory, const std::function<void(string
|
|
45565
|
+
bool ListFiles(const string &directory, const std::function<void(const string &, bool)> &callback) override {
|
|
45545
45566
|
return FindFileSystem(directory)->ListFiles(directory, callback);
|
|
45546
45567
|
}
|
|
45547
45568
|
|
|
@@ -57834,8 +57855,28 @@ PhysicalPiecewiseMergeJoin::PhysicalPiecewiseMergeJoin(LogicalOperator &op, uniq
|
|
|
57834
57855
|
JoinType join_type, idx_t estimated_cardinality)
|
|
57835
57856
|
: PhysicalComparisonJoin(op, PhysicalOperatorType::PIECEWISE_MERGE_JOIN, move(cond), join_type,
|
|
57836
57857
|
estimated_cardinality) {
|
|
57837
|
-
//
|
|
57838
|
-
|
|
57858
|
+
// Reorder the conditions so that ranges are at the front.
|
|
57859
|
+
// TODO: use stats to improve the choice?
|
|
57860
|
+
if (conditions.size() > 1) {
|
|
57861
|
+
auto conditions_p = std::move(conditions);
|
|
57862
|
+
conditions.resize(conditions_p.size());
|
|
57863
|
+
idx_t range_position = 0;
|
|
57864
|
+
idx_t other_position = conditions_p.size();
|
|
57865
|
+
for (idx_t i = 0; i < conditions_p.size(); ++i) {
|
|
57866
|
+
switch (conditions_p[i].comparison) {
|
|
57867
|
+
case ExpressionType::COMPARE_LESSTHAN:
|
|
57868
|
+
case ExpressionType::COMPARE_LESSTHANOREQUALTO:
|
|
57869
|
+
case ExpressionType::COMPARE_GREATERTHAN:
|
|
57870
|
+
case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
|
|
57871
|
+
conditions[range_position++] = std::move(conditions_p[i]);
|
|
57872
|
+
break;
|
|
57873
|
+
default:
|
|
57874
|
+
conditions[--other_position] = std::move(conditions_p[i]);
|
|
57875
|
+
break;
|
|
57876
|
+
}
|
|
57877
|
+
}
|
|
57878
|
+
}
|
|
57879
|
+
|
|
57839
57880
|
for (auto &cond : conditions) {
|
|
57840
57881
|
D_ASSERT(cond.left->return_type == cond.right->return_type);
|
|
57841
57882
|
join_key_types.push_back(cond.left->return_type);
|
|
@@ -57854,8 +57895,16 @@ PhysicalPiecewiseMergeJoin::PhysicalPiecewiseMergeJoin(LogicalOperator &op, uniq
|
|
|
57854
57895
|
lhs_orders.emplace_back(BoundOrderByNode(OrderType::DESCENDING, OrderByNullType::NULLS_LAST, move(left)));
|
|
57855
57896
|
rhs_orders.emplace_back(BoundOrderByNode(OrderType::DESCENDING, OrderByNullType::NULLS_LAST, move(right)));
|
|
57856
57897
|
break;
|
|
57898
|
+
case ExpressionType::COMPARE_NOTEQUAL:
|
|
57899
|
+
case ExpressionType::COMPARE_DISTINCT_FROM:
|
|
57900
|
+
// Allowed in multi-predicate joins, but can't be first/sort.
|
|
57901
|
+
D_ASSERT(!lhs_orders.empty());
|
|
57902
|
+
lhs_orders.emplace_back(BoundOrderByNode(OrderType::INVALID, OrderByNullType::NULLS_LAST, move(left)));
|
|
57903
|
+
rhs_orders.emplace_back(BoundOrderByNode(OrderType::INVALID, OrderByNullType::NULLS_LAST, move(right)));
|
|
57904
|
+
break;
|
|
57905
|
+
|
|
57857
57906
|
default:
|
|
57858
|
-
// COMPARE
|
|
57907
|
+
// COMPARE EQUAL not supported with merge join
|
|
57859
57908
|
throw NotImplementedException("Unimplemented join type for merge join");
|
|
57860
57909
|
}
|
|
57861
57910
|
}
|
|
@@ -57871,6 +57920,7 @@ public:
|
|
|
57871
57920
|
MergeJoinGlobalState(BufferManager &buffer_manager, const vector<BoundOrderByNode> &orders, RowLayout &rhs_layout)
|
|
57872
57921
|
: rhs_global_sort_state(buffer_manager, orders, rhs_layout), rhs_has_null(0), rhs_count(0),
|
|
57873
57922
|
memory_per_thread(0) {
|
|
57923
|
+
D_ASSERT(orders.size() == 1);
|
|
57874
57924
|
}
|
|
57875
57925
|
|
|
57876
57926
|
inline idx_t Count() const {
|
|
@@ -57892,11 +57942,12 @@ public:
|
|
|
57892
57942
|
};
|
|
57893
57943
|
|
|
57894
57944
|
unique_ptr<GlobalSinkState> PhysicalPiecewiseMergeJoin::GetGlobalSinkState(ClientContext &context) const {
|
|
57895
|
-
// Get the payload layout from the rhs types
|
|
57945
|
+
// Get the payload layout from the rhs types and tail predicates
|
|
57896
57946
|
RowLayout rhs_layout;
|
|
57897
|
-
|
|
57898
|
-
|
|
57899
|
-
|
|
57947
|
+
rhs_layout.Initialize(children[1]->types);
|
|
57948
|
+
vector<BoundOrderByNode> rhs_order;
|
|
57949
|
+
rhs_order.emplace_back(rhs_orders[0].Copy());
|
|
57950
|
+
auto state = make_unique<MergeJoinGlobalState>(BufferManager::GetBufferManager(context), rhs_order, rhs_layout);
|
|
57900
57951
|
// Set external (can be force with the PRAGMA)
|
|
57901
57952
|
auto &config = ClientConfig::GetConfig(context);
|
|
57902
57953
|
state->rhs_global_sort_state.external = config.force_external;
|
|
@@ -57963,6 +58014,94 @@ unique_ptr<LocalSinkState> PhysicalPiecewiseMergeJoin::GetLocalSinkState(Executi
|
|
|
57963
58014
|
return move(result);
|
|
57964
58015
|
}
|
|
57965
58016
|
|
|
58017
|
+
static idx_t PiecewiseMergeNulls(DataChunk &keys, const vector<JoinCondition> &conditions) {
|
|
58018
|
+
// Merge the validity masks of the comparison keys into the primary
|
|
58019
|
+
// Return the number of NULLs in the resulting chunk
|
|
58020
|
+
D_ASSERT(keys.ColumnCount() > 0);
|
|
58021
|
+
const auto count = keys.size();
|
|
58022
|
+
|
|
58023
|
+
size_t all_constant = 0;
|
|
58024
|
+
for (auto &v : keys.data) {
|
|
58025
|
+
if (v.GetVectorType() == VectorType::CONSTANT_VECTOR) {
|
|
58026
|
+
++all_constant;
|
|
58027
|
+
}
|
|
58028
|
+
}
|
|
58029
|
+
|
|
58030
|
+
auto &primary = keys.data[0];
|
|
58031
|
+
if (all_constant == keys.data.size()) {
|
|
58032
|
+
// Either all NULL or no NULLs
|
|
58033
|
+
for (auto &v : keys.data) {
|
|
58034
|
+
if (ConstantVector::IsNull(v)) {
|
|
58035
|
+
ConstantVector::SetNull(primary, true);
|
|
58036
|
+
return count;
|
|
58037
|
+
}
|
|
58038
|
+
}
|
|
58039
|
+
return 0;
|
|
58040
|
+
} else if (keys.ColumnCount() > 1) {
|
|
58041
|
+
// Normalify the primary, as it will need to merge arbitrary validity masks
|
|
58042
|
+
primary.Normalify(count);
|
|
58043
|
+
auto &pvalidity = FlatVector::Validity(primary);
|
|
58044
|
+
for (size_t c = 1; c < keys.data.size(); ++c) {
|
|
58045
|
+
// Skip comparisons that accept NULLs
|
|
58046
|
+
if (conditions[c].comparison == ExpressionType::COMPARE_DISTINCT_FROM) {
|
|
58047
|
+
continue;
|
|
58048
|
+
}
|
|
58049
|
+
// Orrify the rest, as the sort code will do this anyway.
|
|
58050
|
+
auto &v = keys.data[c];
|
|
58051
|
+
VectorData vdata;
|
|
58052
|
+
v.Orrify(count, vdata);
|
|
58053
|
+
auto &vvalidity = vdata.validity;
|
|
58054
|
+
if (vvalidity.AllValid()) {
|
|
58055
|
+
continue;
|
|
58056
|
+
}
|
|
58057
|
+
pvalidity.EnsureWritable();
|
|
58058
|
+
switch (v.GetVectorType()) {
|
|
58059
|
+
case VectorType::FLAT_VECTOR: {
|
|
58060
|
+
// Merge entire entries
|
|
58061
|
+
auto pmask = pvalidity.GetData();
|
|
58062
|
+
const auto entry_count = pvalidity.EntryCount(count);
|
|
58063
|
+
for (idx_t entry_idx = 0; entry_idx < entry_count; ++entry_idx) {
|
|
58064
|
+
pmask[entry_idx] &= vvalidity.GetValidityEntry(entry_idx);
|
|
58065
|
+
}
|
|
58066
|
+
break;
|
|
58067
|
+
}
|
|
58068
|
+
case VectorType::CONSTANT_VECTOR:
|
|
58069
|
+
// All or nothing
|
|
58070
|
+
if (ConstantVector::IsNull(v)) {
|
|
58071
|
+
pvalidity.SetAllInvalid(count);
|
|
58072
|
+
return count;
|
|
58073
|
+
}
|
|
58074
|
+
break;
|
|
58075
|
+
default:
|
|
58076
|
+
// One by one
|
|
58077
|
+
for (idx_t i = 0; i < count; ++i) {
|
|
58078
|
+
const auto idx = vdata.sel->get_index(i);
|
|
58079
|
+
if (!vvalidity.RowIsValidUnsafe(idx)) {
|
|
58080
|
+
pvalidity.SetInvalidUnsafe(i);
|
|
58081
|
+
}
|
|
58082
|
+
}
|
|
58083
|
+
break;
|
|
58084
|
+
}
|
|
58085
|
+
}
|
|
58086
|
+
return count - pvalidity.CountValid(count);
|
|
58087
|
+
} else {
|
|
58088
|
+
return count - CountValid(primary, count);
|
|
58089
|
+
}
|
|
58090
|
+
}
|
|
58091
|
+
|
|
58092
|
+
static inline void SinkPiecewiseMergeChunk(LocalSortState &sort_state, DataChunk &join_keys, DataChunk &input) {
|
|
58093
|
+
if (join_keys.ColumnCount() > 1) {
|
|
58094
|
+
// Only sort the first key
|
|
58095
|
+
DataChunk join_head;
|
|
58096
|
+
join_head.data.emplace_back(Vector(join_keys.data[0]));
|
|
58097
|
+
join_head.SetCardinality(join_keys.size());
|
|
58098
|
+
|
|
58099
|
+
sort_state.SinkChunk(join_head, input);
|
|
58100
|
+
} else {
|
|
58101
|
+
sort_state.SinkChunk(join_keys, input);
|
|
58102
|
+
}
|
|
58103
|
+
}
|
|
58104
|
+
|
|
57966
58105
|
SinkResultType PhysicalPiecewiseMergeJoin::Sink(ExecutionContext &context, GlobalSinkState &gstate_p,
|
|
57967
58106
|
LocalSinkState &lstate_p, DataChunk &input) const {
|
|
57968
58107
|
auto &gstate = (MergeJoinGlobalState &)gstate_p;
|
|
@@ -57982,15 +58121,11 @@ SinkResultType PhysicalPiecewiseMergeJoin::Sink(ExecutionContext &context, Globa
|
|
|
57982
58121
|
lstate.rhs_executor.Execute(input, join_keys);
|
|
57983
58122
|
|
|
57984
58123
|
// 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;
|
|
58124
|
+
lstate.rhs_has_null += PiecewiseMergeNulls(join_keys, conditions);
|
|
58125
|
+
lstate.rhs_count += join_keys.size();
|
|
57991
58126
|
|
|
57992
58127
|
// Sink the data into the local sort state
|
|
57993
|
-
local_sort_state
|
|
58128
|
+
SinkPiecewiseMergeChunk(local_sort_state, join_keys, input);
|
|
57994
58129
|
|
|
57995
58130
|
// When sorting data reaches a certain size, we sort it
|
|
57996
58131
|
if (local_sort_state.SizeInBytes() >= gstate.memory_per_thread) {
|
|
@@ -58115,9 +58250,9 @@ public:
|
|
|
58115
58250
|
: op(op), buffer_manager(buffer_manager), force_external(force_external), left_position(0), first_fetch(true),
|
|
58116
58251
|
finished(true), right_position(0), right_chunk_index(0) {
|
|
58117
58252
|
vector<LogicalType> condition_types;
|
|
58118
|
-
for (auto &
|
|
58119
|
-
lhs_executor.AddExpression(*
|
|
58120
|
-
condition_types.push_back(
|
|
58253
|
+
for (auto &order : op.lhs_orders) {
|
|
58254
|
+
lhs_executor.AddExpression(*order.expression);
|
|
58255
|
+
condition_types.push_back(order.expression->return_type);
|
|
58121
58256
|
}
|
|
58122
58257
|
lhs_keys.Initialize(condition_types);
|
|
58123
58258
|
if (IsLeftOuterJoin(op.join_type)) {
|
|
@@ -58125,6 +58260,18 @@ public:
|
|
|
58125
58260
|
memset(lhs_found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE);
|
|
58126
58261
|
}
|
|
58127
58262
|
lhs_layout.Initialize(op.children[0]->types);
|
|
58263
|
+
lhs_payload.Initialize(op.children[0]->types);
|
|
58264
|
+
|
|
58265
|
+
lhs_order.emplace_back(op.lhs_orders[0].Copy());
|
|
58266
|
+
|
|
58267
|
+
// Set up shared data for multiple predicates
|
|
58268
|
+
sel.Initialize(STANDARD_VECTOR_SIZE);
|
|
58269
|
+
condition_types.clear();
|
|
58270
|
+
for (auto &order : op.rhs_orders) {
|
|
58271
|
+
rhs_executor.AddExpression(*order.expression);
|
|
58272
|
+
condition_types.push_back(order.expression->return_type);
|
|
58273
|
+
}
|
|
58274
|
+
rhs_keys.Initialize(condition_types);
|
|
58128
58275
|
}
|
|
58129
58276
|
|
|
58130
58277
|
const PhysicalPiecewiseMergeJoin &op;
|
|
@@ -58133,8 +58280,10 @@ public:
|
|
|
58133
58280
|
|
|
58134
58281
|
// Block sorting
|
|
58135
58282
|
DataChunk lhs_keys;
|
|
58283
|
+
DataChunk lhs_payload;
|
|
58136
58284
|
ExpressionExecutor lhs_executor;
|
|
58137
58285
|
unique_ptr<bool[]> lhs_found_match;
|
|
58286
|
+
vector<BoundOrderByNode> lhs_order;
|
|
58138
58287
|
RowLayout lhs_layout;
|
|
58139
58288
|
unique_ptr<LocalSortState> lhs_local_state;
|
|
58140
58289
|
unique_ptr<GlobalSortState> lhs_global_state;
|
|
@@ -58151,6 +58300,12 @@ public:
|
|
|
58151
58300
|
idx_t right_chunk_index;
|
|
58152
58301
|
idx_t right_base;
|
|
58153
58302
|
|
|
58303
|
+
// Secondary predicate shared data
|
|
58304
|
+
SelectionVector sel;
|
|
58305
|
+
DataChunk rhs_keys;
|
|
58306
|
+
DataChunk rhs_input;
|
|
58307
|
+
ExpressionExecutor rhs_executor;
|
|
58308
|
+
|
|
58154
58309
|
public:
|
|
58155
58310
|
void ResolveJoinKeys(DataChunk &input) {
|
|
58156
58311
|
// resolve the join keys for the input
|
|
@@ -58158,18 +58313,14 @@ public:
|
|
|
58158
58313
|
lhs_executor.Execute(input, lhs_keys);
|
|
58159
58314
|
|
|
58160
58315
|
// 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
58316
|
lhs_count = lhs_keys.size();
|
|
58163
|
-
|
|
58164
|
-
lhs_has_null = lhs_count - CountValid(key, lhs_count);
|
|
58165
|
-
break;
|
|
58166
|
-
}
|
|
58317
|
+
lhs_has_null = PiecewiseMergeNulls(lhs_keys, op.conditions);
|
|
58167
58318
|
|
|
58168
58319
|
// sort by join key
|
|
58169
|
-
lhs_global_state = make_unique<GlobalSortState>(buffer_manager,
|
|
58320
|
+
lhs_global_state = make_unique<GlobalSortState>(buffer_manager, lhs_order, lhs_layout);
|
|
58170
58321
|
lhs_local_state = make_unique<LocalSortState>();
|
|
58171
58322
|
lhs_local_state->Initialize(*lhs_global_state, buffer_manager);
|
|
58172
|
-
lhs_local_state
|
|
58323
|
+
SinkPiecewiseMergeChunk(*lhs_local_state, lhs_keys, input);
|
|
58173
58324
|
|
|
58174
58325
|
// Set external (can be force with the PRAGMA)
|
|
58175
58326
|
lhs_global_state->external = force_external;
|
|
@@ -58180,6 +58331,17 @@ public:
|
|
|
58180
58331
|
merge_sorter.PerformInMergeRound();
|
|
58181
58332
|
lhs_global_state->CompleteMergeRound();
|
|
58182
58333
|
}
|
|
58334
|
+
|
|
58335
|
+
// Scan the sorted payload
|
|
58336
|
+
D_ASSERT(lhs_global_state->sorted_blocks.size() == 1);
|
|
58337
|
+
|
|
58338
|
+
PayloadScanner scanner(*lhs_global_state->sorted_blocks[0]->payload_data, *lhs_global_state);
|
|
58339
|
+
lhs_payload.Reset();
|
|
58340
|
+
scanner.Scan(lhs_payload);
|
|
58341
|
+
|
|
58342
|
+
// Recompute the sorted keys from the sorted input
|
|
58343
|
+
lhs_keys.Reset();
|
|
58344
|
+
lhs_executor.Execute(lhs_payload, lhs_keys);
|
|
58183
58345
|
}
|
|
58184
58346
|
|
|
58185
58347
|
void Finalize(PhysicalOperator *op, ExecutionContext &context) override {
|
|
@@ -58228,8 +58390,8 @@ struct BlockMergeInfo {
|
|
|
58228
58390
|
}
|
|
58229
58391
|
};
|
|
58230
58392
|
|
|
58231
|
-
static
|
|
58232
|
-
|
|
58393
|
+
static idx_t SliceSortedPayload(DataChunk &payload, BlockMergeInfo &info, const idx_t result_count,
|
|
58394
|
+
const idx_t left_cols = 0) {
|
|
58233
58395
|
// There should only be one sorted block if they have been sorted
|
|
58234
58396
|
D_ASSERT(info.state.sorted_blocks.size() == 1);
|
|
58235
58397
|
SBScanState read_state(info.state.buffer_manager, info.state);
|
|
@@ -58238,33 +58400,50 @@ static void SliceSortedPayload(DataChunk &payload, BlockMergeInfo &info, const i
|
|
|
58238
58400
|
|
|
58239
58401
|
// We have to create pointers for the entire block
|
|
58240
58402
|
// because unswizzle works on ranges not selections.
|
|
58241
|
-
|
|
58403
|
+
const auto first_idx = info.result.get_index(0);
|
|
58404
|
+
read_state.SetIndices(info.block_idx, info.base_idx + first_idx);
|
|
58242
58405
|
read_state.PinData(sorted_data);
|
|
58243
58406
|
const auto data_ptr = read_state.DataPtr(sorted_data);
|
|
58244
|
-
const auto next = vcount - info.base_idx;
|
|
58245
58407
|
|
|
58246
58408
|
// Set up a batch of pointers to scan data from
|
|
58247
|
-
Vector addresses(LogicalType::POINTER,
|
|
58409
|
+
Vector addresses(LogicalType::POINTER, result_count);
|
|
58248
58410
|
auto data_pointers = FlatVector::GetData<data_ptr_t>(addresses);
|
|
58249
58411
|
|
|
58250
|
-
// Set up the data pointers
|
|
58412
|
+
// Set up the data pointers for the values that are actually referenced
|
|
58413
|
+
// and normalise the selection vector to zero
|
|
58251
58414
|
data_ptr_t row_ptr = data_ptr;
|
|
58252
58415
|
const idx_t &row_width = sorted_data.layout.GetRowWidth();
|
|
58253
|
-
|
|
58254
|
-
|
|
58255
|
-
|
|
58416
|
+
|
|
58417
|
+
auto prev_idx = first_idx;
|
|
58418
|
+
info.result.set_index(0, 0);
|
|
58419
|
+
idx_t addr_count = 0;
|
|
58420
|
+
data_pointers[addr_count++] = row_ptr;
|
|
58421
|
+
for (idx_t i = 1; i < result_count; ++i) {
|
|
58422
|
+
const auto row_idx = info.result.get_index(i);
|
|
58423
|
+
info.result.set_index(i, row_idx - first_idx);
|
|
58424
|
+
if (row_idx == prev_idx) {
|
|
58425
|
+
continue;
|
|
58426
|
+
}
|
|
58427
|
+
row_ptr += (row_idx - prev_idx) * row_width;
|
|
58428
|
+
data_pointers[addr_count++] = row_ptr;
|
|
58429
|
+
prev_idx = row_idx;
|
|
58256
58430
|
}
|
|
58257
58431
|
// Unswizzle the offsets back to pointers (if needed)
|
|
58258
58432
|
if (!sorted_data.layout.AllConstant() && info.state.external) {
|
|
58433
|
+
const auto next = prev_idx + 1;
|
|
58259
58434
|
RowOperations::UnswizzlePointers(sorted_data.layout, data_ptr, read_state.payload_heap_handle->Ptr(), next);
|
|
58260
58435
|
}
|
|
58261
58436
|
|
|
58262
58437
|
// Deserialize the payload data
|
|
58438
|
+
auto sel = FlatVector::IncrementalSelectionVector();
|
|
58263
58439
|
for (idx_t col_idx = 0; col_idx < sorted_data.layout.ColumnCount(); col_idx++) {
|
|
58264
58440
|
const auto col_offset = sorted_data.layout.GetOffsets()[col_idx];
|
|
58265
|
-
|
|
58266
|
-
|
|
58441
|
+
auto &col = payload.data[left_cols + col_idx];
|
|
58442
|
+
RowOperations::Gather(addresses, *sel, col, *sel, addr_count, col_offset, col_idx);
|
|
58443
|
+
col.Slice(info.result, result_count);
|
|
58267
58444
|
}
|
|
58445
|
+
|
|
58446
|
+
return first_idx;
|
|
58268
58447
|
}
|
|
58269
58448
|
|
|
58270
58449
|
static void MergeJoinPinSortingBlock(SBScanState &scan, const idx_t block_idx) {
|
|
@@ -58372,16 +58551,9 @@ void PhysicalPiecewiseMergeJoin::ResolveSimpleJoin(ExecutionContext &context, Da
|
|
|
58372
58551
|
memset(found_match, 0, sizeof(found_match));
|
|
58373
58552
|
MergeJoinSimpleBlocks(state, gstate, found_match, conditions[0].comparison);
|
|
58374
58553
|
|
|
58375
|
-
//
|
|
58376
|
-
idx_t left_position = 0;
|
|
58554
|
+
// use the sorted payload
|
|
58377
58555
|
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);
|
|
58556
|
+
auto &payload = state.lhs_payload;
|
|
58385
58557
|
|
|
58386
58558
|
// now construct the result based on the join result
|
|
58387
58559
|
switch (join_type) {
|
|
@@ -58488,11 +58660,37 @@ static idx_t MergeJoinComplexBlocks(BlockMergeInfo &l, BlockMergeInfo &r, const
|
|
|
58488
58660
|
return result_count;
|
|
58489
58661
|
}
|
|
58490
58662
|
|
|
58663
|
+
static idx_t SelectJoinTail(const ExpressionType &condition, Vector &left, Vector &right, const SelectionVector *sel,
|
|
58664
|
+
idx_t count, SelectionVector *true_sel) {
|
|
58665
|
+
switch (condition) {
|
|
58666
|
+
case ExpressionType::COMPARE_NOTEQUAL:
|
|
58667
|
+
return VectorOperations::NotEquals(left, right, sel, count, true_sel, nullptr);
|
|
58668
|
+
case ExpressionType::COMPARE_LESSTHAN:
|
|
58669
|
+
return VectorOperations::LessThan(left, right, sel, count, true_sel, nullptr);
|
|
58670
|
+
case ExpressionType::COMPARE_GREATERTHAN:
|
|
58671
|
+
return VectorOperations::GreaterThan(left, right, sel, count, true_sel, nullptr);
|
|
58672
|
+
case ExpressionType::COMPARE_LESSTHANOREQUALTO:
|
|
58673
|
+
return VectorOperations::LessThanEquals(left, right, sel, count, true_sel, nullptr);
|
|
58674
|
+
case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
|
|
58675
|
+
return VectorOperations::GreaterThanEquals(left, right, sel, count, true_sel, nullptr);
|
|
58676
|
+
case ExpressionType::COMPARE_DISTINCT_FROM:
|
|
58677
|
+
return VectorOperations::DistinctFrom(left, right, sel, count, true_sel, nullptr);
|
|
58678
|
+
case ExpressionType::COMPARE_NOT_DISTINCT_FROM:
|
|
58679
|
+
case ExpressionType::COMPARE_EQUAL:
|
|
58680
|
+
default:
|
|
58681
|
+
throw InternalException("Unsupported comparison type for PhysicalPiecewiseMergeJoin");
|
|
58682
|
+
}
|
|
58683
|
+
|
|
58684
|
+
return count;
|
|
58685
|
+
}
|
|
58686
|
+
|
|
58491
58687
|
OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionContext &context, DataChunk &input,
|
|
58492
58688
|
DataChunk &chunk, OperatorState &state_p) const {
|
|
58493
58689
|
auto &state = (PiecewiseMergeJoinState &)state_p;
|
|
58494
58690
|
auto &gstate = (MergeJoinGlobalState &)*sink_state;
|
|
58495
58691
|
auto &rsorted = *gstate.rhs_global_sort_state.sorted_blocks[0];
|
|
58692
|
+
const auto left_cols = input.ColumnCount();
|
|
58693
|
+
const auto tail_cols = conditions.size() - 1;
|
|
58496
58694
|
do {
|
|
58497
58695
|
if (state.first_fetch) {
|
|
58498
58696
|
state.ResolveJoinKeys(input);
|
|
@@ -58508,7 +58706,7 @@ OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionConte
|
|
|
58508
58706
|
if (IsLeftOuterJoin(join_type)) {
|
|
58509
58707
|
// left join: before we move to the next chunk, see if we need to output any vectors that didn't
|
|
58510
58708
|
// have a match found
|
|
58511
|
-
PhysicalJoin::ConstructLeftJoinResult(
|
|
58709
|
+
PhysicalJoin::ConstructLeftJoinResult(state.lhs_payload, chunk, state.lhs_found_match.get());
|
|
58512
58710
|
memset(state.lhs_found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE);
|
|
58513
58711
|
}
|
|
58514
58712
|
state.first_fetch = true;
|
|
@@ -58537,22 +58735,60 @@ OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionConte
|
|
|
58537
58735
|
state.finished = true;
|
|
58538
58736
|
}
|
|
58539
58737
|
} else {
|
|
58738
|
+
// found matches: extract them
|
|
58739
|
+
chunk.Reset();
|
|
58740
|
+
for (idx_t c = 0; c < state.lhs_payload.ColumnCount(); ++c) {
|
|
58741
|
+
chunk.data[c].Slice(state.lhs_payload.data[c], left_info.result, result_count);
|
|
58742
|
+
}
|
|
58743
|
+
const auto first_idx = SliceSortedPayload(chunk, right_info, result_count, left_cols);
|
|
58744
|
+
chunk.SetCardinality(result_count);
|
|
58745
|
+
|
|
58746
|
+
auto sel = FlatVector::IncrementalSelectionVector();
|
|
58747
|
+
if (tail_cols) {
|
|
58748
|
+
// If there are more expressions to compute,
|
|
58749
|
+
// split the result chunk into the left and right halves
|
|
58750
|
+
// so we can compute the values for comparison.
|
|
58751
|
+
chunk.Split(state.rhs_input, left_cols);
|
|
58752
|
+
state.rhs_executor.SetChunk(state.rhs_input);
|
|
58753
|
+
state.rhs_keys.Reset();
|
|
58754
|
+
|
|
58755
|
+
auto tail_count = result_count;
|
|
58756
|
+
for (size_t cmp_idx = 1; cmp_idx < conditions.size(); ++cmp_idx) {
|
|
58757
|
+
Vector left(state.lhs_keys.data[cmp_idx]);
|
|
58758
|
+
left.Slice(left_info.result, result_count);
|
|
58759
|
+
|
|
58760
|
+
auto &right = state.rhs_keys.data[cmp_idx];
|
|
58761
|
+
state.rhs_executor.ExecuteExpression(cmp_idx, right);
|
|
58762
|
+
|
|
58763
|
+
if (tail_count < result_count) {
|
|
58764
|
+
left.Slice(*sel, tail_count);
|
|
58765
|
+
right.Slice(*sel, tail_count);
|
|
58766
|
+
}
|
|
58767
|
+
tail_count =
|
|
58768
|
+
SelectJoinTail(conditions[cmp_idx].comparison, left, right, sel, tail_count, &state.sel);
|
|
58769
|
+
sel = &state.sel;
|
|
58770
|
+
}
|
|
58771
|
+
chunk.Fuse(state.rhs_input);
|
|
58772
|
+
|
|
58773
|
+
if (tail_count < result_count) {
|
|
58774
|
+
result_count = tail_count;
|
|
58775
|
+
chunk.Slice(*sel, result_count);
|
|
58776
|
+
}
|
|
58777
|
+
}
|
|
58778
|
+
|
|
58540
58779
|
// found matches: mark the found matches if required
|
|
58541
58780
|
if (state.lhs_found_match) {
|
|
58542
58781
|
for (idx_t i = 0; i < result_count; i++) {
|
|
58543
|
-
state.lhs_found_match[left_info.result[i]] = true;
|
|
58782
|
+
state.lhs_found_match[left_info.result[sel->get_index(i)]] = true;
|
|
58544
58783
|
}
|
|
58545
58784
|
}
|
|
58546
58785
|
if (gstate.rhs_found_match) {
|
|
58547
58786
|
// Absolute position of the block + start position inside that block
|
|
58548
|
-
const idx_t base_index =
|
|
58787
|
+
const idx_t base_index = right_info.base_idx + first_idx;
|
|
58549
58788
|
for (idx_t i = 0; i < result_count; i++) {
|
|
58550
|
-
gstate.rhs_found_match[base_index + right_info.result[i]] = true;
|
|
58789
|
+
gstate.rhs_found_match[base_index + right_info.result[sel->get_index(i)]] = true;
|
|
58551
58790
|
}
|
|
58552
58791
|
}
|
|
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
58792
|
chunk.SetCardinality(result_count);
|
|
58557
58793
|
chunk.Verify();
|
|
58558
58794
|
}
|
|
@@ -58638,7 +58874,7 @@ void PhysicalPiecewiseMergeJoin::GetData(ExecutionContext &context, DataChunk &r
|
|
|
58638
58874
|
|
|
58639
58875
|
// ConstructFullOuterJoinResult(sink.rhs_found_match.get(), sink.right_chunks, chunk, state.right_outer_position);
|
|
58640
58876
|
DataChunk rhs_chunk;
|
|
58641
|
-
rhs_chunk.Initialize(
|
|
58877
|
+
rhs_chunk.Initialize(sink.rhs_global_sort_state.payload_layout.GetTypes());
|
|
58642
58878
|
SelectionVector rsel(STANDARD_VECTOR_SIZE);
|
|
58643
58879
|
for (;;) {
|
|
58644
58880
|
// Read the next sorted chunk
|
|
@@ -58660,12 +58896,14 @@ void PhysicalPiecewiseMergeJoin::GetData(ExecutionContext &context, DataChunk &r
|
|
|
58660
58896
|
|
|
58661
58897
|
if (result_count > 0) {
|
|
58662
58898
|
// if there were any tuples that didn't find a match, output them
|
|
58663
|
-
const idx_t left_column_count =
|
|
58899
|
+
const idx_t left_column_count = children[0]->types.size();
|
|
58664
58900
|
for (idx_t col_idx = 0; col_idx < left_column_count; ++col_idx) {
|
|
58665
58901
|
result.data[col_idx].SetVectorType(VectorType::CONSTANT_VECTOR);
|
|
58666
58902
|
ConstantVector::SetNull(result.data[col_idx], true);
|
|
58667
58903
|
}
|
|
58668
|
-
|
|
58904
|
+
const idx_t right_column_count = children[1]->types.size();
|
|
58905
|
+
;
|
|
58906
|
+
for (idx_t col_idx = 0; col_idx < right_column_count; ++col_idx) {
|
|
58669
58907
|
result.data[left_column_count + col_idx].Slice(rhs_chunk.data[col_idx], rsel, result_count);
|
|
58670
58908
|
}
|
|
58671
58909
|
result.SetCardinality(result_count);
|
|
@@ -65382,16 +65620,28 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalComparison
|
|
|
65382
65620
|
}
|
|
65383
65621
|
|
|
65384
65622
|
bool has_equality = false;
|
|
65385
|
-
bool has_inequality = false;
|
|
65623
|
+
// bool has_inequality = false;
|
|
65624
|
+
bool has_range = false;
|
|
65386
65625
|
bool has_null_equal_conditions = false;
|
|
65387
|
-
for (
|
|
65388
|
-
|
|
65389
|
-
|
|
65626
|
+
for (size_t c = 0; c < op.conditions.size(); ++c) {
|
|
65627
|
+
auto &cond = op.conditions[c];
|
|
65628
|
+
switch (cond.comparison) {
|
|
65629
|
+
case ExpressionType::COMPARE_EQUAL:
|
|
65630
|
+
case ExpressionType::COMPARE_NOT_DISTINCT_FROM:
|
|
65390
65631
|
has_equality = true;
|
|
65391
|
-
|
|
65392
|
-
|
|
65393
|
-
|
|
65394
|
-
|
|
65632
|
+
break;
|
|
65633
|
+
case ExpressionType::COMPARE_LESSTHAN:
|
|
65634
|
+
case ExpressionType::COMPARE_GREATERTHAN:
|
|
65635
|
+
case ExpressionType::COMPARE_LESSTHANOREQUALTO:
|
|
65636
|
+
case ExpressionType::COMPARE_GREATERTHANOREQUALTO:
|
|
65637
|
+
has_range = true;
|
|
65638
|
+
break;
|
|
65639
|
+
case ExpressionType::COMPARE_NOTEQUAL:
|
|
65640
|
+
case ExpressionType::COMPARE_DISTINCT_FROM:
|
|
65641
|
+
// has_inequality = true;
|
|
65642
|
+
break;
|
|
65643
|
+
default:
|
|
65644
|
+
throw NotImplementedException("Unimplemented comparison join");
|
|
65395
65645
|
}
|
|
65396
65646
|
if (cond.null_values_are_equal) {
|
|
65397
65647
|
has_null_equal_conditions = true;
|
|
@@ -65428,8 +65678,17 @@ unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalComparison
|
|
|
65428
65678
|
op.estimated_cardinality, perfect_join_stats);
|
|
65429
65679
|
|
|
65430
65680
|
} else {
|
|
65431
|
-
|
|
65432
|
-
|
|
65681
|
+
bool can_merge = has_range;
|
|
65682
|
+
switch (op.join_type) {
|
|
65683
|
+
case JoinType::SEMI:
|
|
65684
|
+
case JoinType::ANTI:
|
|
65685
|
+
case JoinType::MARK:
|
|
65686
|
+
can_merge = can_merge && op.conditions.size() == 1;
|
|
65687
|
+
break;
|
|
65688
|
+
default:
|
|
65689
|
+
break;
|
|
65690
|
+
}
|
|
65691
|
+
if (can_merge) {
|
|
65433
65692
|
// range join: use piecewise merge join
|
|
65434
65693
|
plan = make_unique<PhysicalPiecewiseMergeJoin>(op, move(left), move(right), move(op.conditions),
|
|
65435
65694
|
op.join_type, op.estimated_cardinality);
|