duckdb 0.3.3-dev477.0 → 0.3.3-dev513.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
- "version": "0.3.3-dev477.0",
4
+ "version": "0.3.3-dev513.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
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++) {
@@ -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) {
@@ -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
- // for now we only support one condition!
57838
- D_ASSERT(conditions.size() == 1);
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 NOT EQUAL not supported with merge join
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
- auto types = children[1]->types;
57898
- rhs_layout.Initialize(types);
57899
- auto state = make_unique<MergeJoinGlobalState>(BufferManager::GetBufferManager(context), rhs_orders, rhs_layout);
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
- // TODO: Sort any comparison NULLs to the end using an initial sort column
57986
- const auto count = join_keys.size();
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.SinkChunk(join_keys, input);
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 &cond : op.conditions) {
58119
- lhs_executor.AddExpression(*cond.left);
58120
- condition_types.push_back(cond.left->return_type);
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
- for (auto &key : lhs_keys.data) {
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, op.lhs_orders, lhs_layout);
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->SinkChunk(lhs_keys, input);
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 void SliceSortedPayload(DataChunk &payload, BlockMergeInfo &info, const idx_t result_count, const idx_t vcount,
58232
- const idx_t left_cols = 0) {
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
- read_state.SetIndices(info.block_idx, info.base_idx);
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, next);
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
- for (idx_t i = 0; i < next; ++i) {
58254
- data_pointers[i] = row_ptr;
58255
- row_ptr += row_width;
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
- RowOperations::Gather(addresses, info.result, payload.data[left_cols + col_idx],
58266
- *FlatVector::IncrementalSelectionVector(), result_count, col_offset, col_idx);
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
- // extract the sorted payload
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
- BlockMergeInfo left_info(*state.lhs_global_state, 0, 0, left_position, lhs_not_null);
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(input, chunk, state.lhs_found_match.get());
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 = state.right_base + right_info.base_idx;
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(children[1]->types);
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 = result.ColumnCount() - rhs_chunk.ColumnCount();
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
- for (idx_t col_idx = 0; col_idx < rhs_chunk.ColumnCount(); ++col_idx) {
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 (auto &cond : op.conditions) {
65388
- if (cond.comparison == ExpressionType::COMPARE_EQUAL ||
65389
- cond.comparison == ExpressionType::COMPARE_NOT_DISTINCT_FROM) {
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
- if (cond.comparison == ExpressionType::COMPARE_NOTEQUAL ||
65393
- cond.comparison == ExpressionType::COMPARE_DISTINCT_FROM) {
65394
- has_inequality = true;
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
- if (op.conditions.size() == 1 && !has_inequality) {
65432
- D_ASSERT(!has_null_equal_conditions); // we support this for this join for now
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);
@@ -77929,8 +78188,8 @@ string PragmaFunctionsQuery(ClientContext &context, const FunctionParameters &pa
77929
78188
  string PragmaShow(ClientContext &context, const FunctionParameters &parameters) {
77930
78189
  // PRAGMA table_info but with some aliases
77931
78190
  return StringUtil::Format(
77932
- "SELECT name AS \"Field\", type as \"Type\", CASE WHEN \"notnull\" THEN 'NO' ELSE 'YES' END AS \"Null\", "
77933
- "NULL AS \"Key\", dflt_value AS \"Default\", NULL AS \"Extra\" FROM pragma_table_info('%s')",
78191
+ "SELECT name AS \"column_name\", type as \"column_type\", CASE WHEN \"notnull\" THEN 'NO' ELSE 'YES' "
78192
+ "END AS \"null\", NULL AS \"key\", dflt_value AS \"default\", NULL AS \"extra\" FROM pragma_table_info('%s')",
77934
78193
  parameters.values[0].ToString());
77935
78194
  }
77936
78195
 
@@ -151790,7 +152049,7 @@ BoundStatement Binder::Bind(ShowStatement &stmt) {
151790
152049
 
151791
152050
  result.plan = move(show);
151792
152051
 
151793
- result.names = {"Field", "Type", "Null", "Key", "Default", "Extra"};
152052
+ result.names = {"column_name", "column_type", "null", "key", "default", "extra"};
151794
152053
  result.types = {LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR,
151795
152054
  LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR};
151796
152055
  return result;
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 "660ba3a6e"
15
- #define DUCKDB_VERSION "v0.3.3-dev477"
14
+ #define DUCKDB_SOURCE_ID "75fc1b014"
15
+ #define DUCKDB_VERSION "v0.3.3-dev513"
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