duckdb 0.3.1-dev360.0 → 0.3.1-dev399.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.1-dev360.0",
4
+ "version": "0.3.1-dev399.0",
5
5
  "description": "DuckDB node.js API",
6
6
  "gypfile": true,
7
7
  "dependencies": {
package/src/duckdb.cpp CHANGED
@@ -4922,6 +4922,8 @@ public:
4922
4922
  void ExecuteExpression(idx_t expr_idx, Vector &result);
4923
4923
  //! Evaluate a scalar expression and fold it into a single value
4924
4924
  static Value EvaluateScalar(const Expression &expr);
4925
+ //! Try to evaluate a scalar expression and fold it into a single value, returns false if an exception is thrown
4926
+ static bool TryEvaluateScalar(const Expression &expr, Value &result);
4925
4927
 
4926
4928
  //! Initialize the state of a given expression
4927
4929
  static unique_ptr<ExpressionState> InitializeState(const Expression &expr, ExpressionExecutorState &state);
@@ -5005,6 +5007,8 @@ protected:
5005
5007
  //! Verify that the output of a step in the ExpressionExecutor is correct
5006
5008
  void Verify(const Expression &expr, Vector &result, idx_t count);
5007
5009
 
5010
+ void FillSwitch(Vector &vector, Vector &result, SelectionVector &sel, sel_t count);
5011
+
5008
5012
  private:
5009
5013
  //! The states of the expression executor; this holds any intermediates and temporary states of expressions
5010
5014
  vector<unique_ptr<ExpressionExecutorState>> states;
@@ -34023,10 +34027,11 @@ static void QuicksortInPlace(ChunkCollection *sort_by, vector<OrderType> &desc,
34023
34027
  }
34024
34028
 
34025
34029
  void ChunkCollection::Sort(vector<OrderType> &desc, vector<OrderByNullType> &null_order, idx_t result[]) {
34026
- D_ASSERT(result);
34027
34030
  if (count == 0) {
34028
34031
  return;
34029
34032
  }
34033
+ D_ASSERT(result);
34034
+
34030
34035
  // start off with an initial quicksort
34031
34036
  int64_t part = QuicksortInitial(this, desc, null_order, result);
34032
34037
 
@@ -48392,9 +48397,6 @@ idx_t ExpressionExecutor::Select(const BoundBetweenExpression &expr, ExpressionS
48392
48397
 
48393
48398
  namespace duckdb {
48394
48399
 
48395
- void Case(Vector &res_true, Vector &res_false, Vector &result, SelectionVector &tside, idx_t tcount,
48396
- SelectionVector &fside, idx_t fcount);
48397
-
48398
48400
  struct CaseExpressionState : public ExpressionState {
48399
48401
  CaseExpressionState(const Expression &expr, ExpressionExecutorState &root)
48400
48402
  : ExpressionState(expr, root), true_sel(STANDARD_VECTOR_SIZE), false_sel(STANDARD_VECTOR_SIZE) {
@@ -48442,7 +48444,8 @@ void ExpressionExecutor::Execute(const BoundCaseExpression &expr, ExpressionStat
48442
48444
  Execute(*expr.result_if_true, res_true_state, &true_sel, tcount, res_true);
48443
48445
  Execute(*expr.result_if_false, res_false_state, &false_sel, fcount, res_false);
48444
48446
 
48445
- Case(res_true, res_false, result, true_sel, tcount, false_sel, fcount);
48447
+ FillSwitch(res_true, result, true_sel, tcount);
48448
+ FillSwitch(res_false, result, false_sel, fcount);
48446
48449
  if (sel) {
48447
48450
  result.Slice(*sel, count);
48448
48451
  }
@@ -48500,111 +48503,77 @@ void ValidityFillLoop(Vector &vector, Vector &result, SelectionVector &sel, sel_
48500
48503
  }
48501
48504
  }
48502
48505
 
48503
- template <class T>
48504
- void TemplatedCaseLoop(Vector &res_true, Vector &res_false, Vector &result, SelectionVector &tside, idx_t tcount,
48505
- SelectionVector &fside, idx_t fcount) {
48506
- TemplatedFillLoop<T>(res_true, result, tside, tcount);
48507
- TemplatedFillLoop<T>(res_false, result, fside, fcount);
48508
- }
48509
-
48510
- void ValidityCaseLoop(Vector &res_true, Vector &res_false, Vector &result, SelectionVector &tside, idx_t tcount,
48511
- SelectionVector &fside, idx_t fcount) {
48512
- ValidityFillLoop(res_true, result, tside, tcount);
48513
- ValidityFillLoop(res_false, result, fside, fcount);
48514
- }
48515
-
48516
- void Case(Vector &res_true, Vector &res_false, Vector &result, SelectionVector &tside, idx_t tcount,
48517
- SelectionVector &fside, idx_t fcount) {
48518
- D_ASSERT(res_true.GetType() == res_false.GetType() && res_true.GetType() == result.GetType());
48519
-
48506
+ void ExpressionExecutor::FillSwitch(Vector &vector, Vector &result, SelectionVector &sel, sel_t count) {
48520
48507
  switch (result.GetType().InternalType()) {
48521
48508
  case PhysicalType::BOOL:
48522
48509
  case PhysicalType::INT8:
48523
- TemplatedCaseLoop<int8_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48510
+ TemplatedFillLoop<int8_t>(vector, result, sel, count);
48524
48511
  break;
48525
48512
  case PhysicalType::INT16:
48526
- TemplatedCaseLoop<int16_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48513
+ TemplatedFillLoop<int16_t>(vector, result, sel, count);
48527
48514
  break;
48528
48515
  case PhysicalType::INT32:
48529
- TemplatedCaseLoop<int32_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48516
+ TemplatedFillLoop<int32_t>(vector, result, sel, count);
48530
48517
  break;
48531
48518
  case PhysicalType::INT64:
48532
- TemplatedCaseLoop<int64_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48519
+ TemplatedFillLoop<int64_t>(vector, result, sel, count);
48533
48520
  break;
48534
48521
  case PhysicalType::UINT8:
48535
- TemplatedCaseLoop<uint8_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48522
+ TemplatedFillLoop<uint8_t>(vector, result, sel, count);
48536
48523
  break;
48537
48524
  case PhysicalType::UINT16:
48538
- TemplatedCaseLoop<uint16_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48525
+ TemplatedFillLoop<uint16_t>(vector, result, sel, count);
48539
48526
  break;
48540
48527
  case PhysicalType::UINT32:
48541
- TemplatedCaseLoop<uint32_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48528
+ TemplatedFillLoop<uint32_t>(vector, result, sel, count);
48542
48529
  break;
48543
48530
  case PhysicalType::UINT64:
48544
- TemplatedCaseLoop<uint64_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48531
+ TemplatedFillLoop<uint64_t>(vector, result, sel, count);
48545
48532
  break;
48546
48533
  case PhysicalType::INT128:
48547
- TemplatedCaseLoop<hugeint_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48534
+ TemplatedFillLoop<hugeint_t>(vector, result, sel, count);
48548
48535
  break;
48549
48536
  case PhysicalType::FLOAT:
48550
- TemplatedCaseLoop<float>(res_true, res_false, result, tside, tcount, fside, fcount);
48537
+ TemplatedFillLoop<float>(vector, result, sel, count);
48551
48538
  break;
48552
48539
  case PhysicalType::DOUBLE:
48553
- TemplatedCaseLoop<double>(res_true, res_false, result, tside, tcount, fside, fcount);
48540
+ TemplatedFillLoop<double>(vector, result, sel, count);
48554
48541
  break;
48555
48542
  case PhysicalType::INTERVAL:
48556
- TemplatedCaseLoop<interval_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48543
+ TemplatedFillLoop<interval_t>(vector, result, sel, count);
48557
48544
  break;
48558
48545
  case PhysicalType::VARCHAR:
48559
- TemplatedCaseLoop<string_t>(res_true, res_false, result, tside, tcount, fside, fcount);
48560
- StringVector::AddHeapReference(result, res_true);
48561
- StringVector::AddHeapReference(result, res_false);
48546
+ TemplatedFillLoop<string_t>(vector, result, sel, count);
48547
+ StringVector::AddHeapReference(result, vector);
48562
48548
  break;
48563
48549
  case PhysicalType::STRUCT: {
48564
- auto &res_true_entries = StructVector::GetEntries(res_true);
48565
- auto &res_false_entries = StructVector::GetEntries(res_false);
48550
+ auto &vector_entries = StructVector::GetEntries(vector);
48566
48551
  auto &result_entries = StructVector::GetEntries(result);
48567
- D_ASSERT(res_true_entries.size() == res_false_entries.size() &&
48568
- res_true_entries.size() == result_entries.size());
48569
- ValidityCaseLoop(res_true, res_false, result, tside, tcount, fside, fcount);
48570
- for (idx_t i = 0; i < res_true_entries.size(); i++) {
48571
- Case(*res_true_entries[i], *res_false_entries[i], *result_entries[i], tside, tcount, fside, fcount);
48552
+ ValidityFillLoop(vector, result, sel, count);
48553
+ D_ASSERT(vector_entries.size() == result_entries.size());
48554
+ for (idx_t i = 0; i < vector_entries.size(); i++) {
48555
+ FillSwitch(*vector_entries[i], *result_entries[i], sel, count);
48572
48556
  }
48573
48557
  break;
48574
48558
  }
48575
48559
  case PhysicalType::LIST: {
48576
- idx_t offset = 0;
48577
-
48578
- auto &true_child = ListVector::GetEntry(res_true);
48579
- offset += ListVector::GetListSize(res_true);
48580
- ListVector::Append(result, true_child, ListVector::GetListSize(res_true));
48581
-
48582
- auto &false_child = ListVector::GetEntry(res_false);
48583
- ListVector::Append(result, false_child, ListVector::GetListSize(res_false));
48560
+ idx_t offset = ListVector::GetListSize(result);
48561
+ auto &list_child = ListVector::GetEntry(vector);
48562
+ ListVector::Append(result, list_child, ListVector::GetListSize(vector));
48584
48563
 
48585
48564
  // all the false offsets need to be incremented by true_child.count
48586
- TemplatedFillLoop<list_entry_t>(res_true, result, tside, tcount);
48587
-
48588
- // FIXME the nullmask here is likely borked
48589
- // TODO uuugly
48590
- VectorData fdata;
48591
- res_false.Orrify(fcount, fdata);
48592
-
48593
- auto data = (list_entry_t *)fdata.data;
48594
- auto res = FlatVector::GetData<list_entry_t>(result);
48595
- auto &mask = FlatVector::Validity(result);
48565
+ TemplatedFillLoop<list_entry_t>(vector, result, sel, count);
48566
+ if (offset == 0) {
48567
+ break;
48568
+ }
48596
48569
 
48597
- for (idx_t i = 0; i < fcount; i++) {
48598
- auto fidx = fdata.sel->get_index(i);
48599
- auto res_idx = fside.get_index(i);
48600
- auto list_entry = data[fidx];
48601
- list_entry.offset += offset;
48602
- res[res_idx] = list_entry;
48603
- mask.Set(res_idx, fdata.validity.RowIsValid(fidx));
48570
+ auto result_data = FlatVector::GetData<list_entry_t>(result);
48571
+ for (idx_t i = 0; i < count; i++) {
48572
+ auto result_idx = sel.get_index(i);
48573
+ result_data[result_idx].offset += offset;
48604
48574
  }
48605
48575
 
48606
- result.Verify(tside, tcount);
48607
- result.Verify(fside, fcount);
48576
+ result.Verify(sel, count);
48608
48577
  break;
48609
48578
  }
48610
48579
  default:
@@ -49218,6 +49187,57 @@ void ExpressionExecutor::Execute(const BoundOperatorExpression &expr, Expression
49218
49187
  // directly use the result
49219
49188
  result.Reference(intermediate);
49220
49189
  }
49190
+ } else if (expr.type == ExpressionType::OPERATOR_COALESCE) {
49191
+ SelectionVector sel_a(count);
49192
+ SelectionVector sel_b(count);
49193
+ SelectionVector slice_sel(count);
49194
+ SelectionVector result_sel(count);
49195
+ SelectionVector *next_sel = &sel_a;
49196
+ const SelectionVector *current_sel = sel;
49197
+ idx_t remaining_count = count;
49198
+ idx_t next_count;
49199
+ for (idx_t child = 0; child < expr.children.size(); child++) {
49200
+ Vector vector_to_check(expr.children[child]->return_type);
49201
+ Execute(*expr.children[child], state->child_states[child].get(), current_sel, remaining_count,
49202
+ vector_to_check);
49203
+
49204
+ VectorData vdata;
49205
+ vector_to_check.Orrify(remaining_count, vdata);
49206
+
49207
+ idx_t result_count = 0;
49208
+ next_count = 0;
49209
+ for (idx_t i = 0; i < remaining_count; i++) {
49210
+ auto base_idx = current_sel ? current_sel->get_index(i) : i;
49211
+ auto idx = vdata.sel->get_index(i);
49212
+ if (vdata.validity.RowIsValid(idx)) {
49213
+ slice_sel.set_index(result_count, i);
49214
+ result_sel.set_index(result_count++, base_idx);
49215
+ } else {
49216
+ next_sel->set_index(next_count++, base_idx);
49217
+ }
49218
+ }
49219
+ if (result_count > 0) {
49220
+ vector_to_check.Slice(slice_sel, result_count);
49221
+ FillSwitch(vector_to_check, result, result_sel, result_count);
49222
+ }
49223
+ current_sel = next_sel;
49224
+ next_sel = next_sel == &sel_a ? &sel_b : &sel_a;
49225
+ remaining_count = next_count;
49226
+ if (next_count == 0) {
49227
+ break;
49228
+ }
49229
+ }
49230
+ if (remaining_count > 0) {
49231
+ auto &result_mask = FlatVector::Validity(result);
49232
+ for (idx_t i = 0; i < remaining_count; i++) {
49233
+ result_mask.SetInvalid(current_sel->get_index(i));
49234
+ }
49235
+ }
49236
+ if (sel) {
49237
+ result.Slice(*sel, count);
49238
+ } else if (count == 1) {
49239
+ result.SetVectorType(VectorType::CONSTANT_VECTOR);
49240
+ }
49221
49241
  } else if (expr.children.size() == 1) {
49222
49242
  state->intermediate_chunk.Reset();
49223
49243
  auto &child = state->intermediate_chunk.data[0];
@@ -49382,6 +49402,15 @@ Value ExpressionExecutor::EvaluateScalar(const Expression &expr) {
49382
49402
  return result_value;
49383
49403
  }
49384
49404
 
49405
+ bool ExpressionExecutor::TryEvaluateScalar(const Expression &expr, Value &result) {
49406
+ try {
49407
+ result = EvaluateScalar(expr);
49408
+ return true;
49409
+ } catch (...) {
49410
+ return false;
49411
+ }
49412
+ }
49413
+
49385
49414
  void ExpressionExecutor::Verify(const Expression &expr, Vector &vector, idx_t count) {
49386
49415
  D_ASSERT(expr.return_type.id() == vector.GetType().id());
49387
49416
  vector.Verify(count);
@@ -77156,9 +77185,11 @@ struct SortedAggregateFunction {
77156
77185
 
77157
77186
  // Apply the sort before delegating the chunks
77158
77187
  const auto agg_count = state->ordering.Count();
77159
- reordering.resize(agg_count);
77160
- state->ordering.Sort(order_bind->order_sense, order_bind->null_order, reordering.data());
77161
- state->arguments.Reorder(reordering.data());
77188
+ if (agg_count > 0) {
77189
+ reordering.resize(agg_count);
77190
+ state->ordering.Sort(order_bind->order_sense, order_bind->null_order, reordering.data());
77191
+ state->arguments.Reorder(reordering.data());
77192
+ }
77162
77193
 
77163
77194
  for (auto &chunk : state->arguments.Chunks()) {
77164
77195
  // These are all simple updates, so use it if available
@@ -87128,7 +87159,9 @@ struct ChrOperator {
87128
87159
  static inline TR Operation(const TA &input) {
87129
87160
  char c[5] = {'\0', '\0', '\0', '\0', '\0'};
87130
87161
  int utf8_bytes = 4;
87131
- Utf8Proc::CodepointToUtf8(input, utf8_bytes, &c[0]);
87162
+ if (input < 0 || !Utf8Proc::CodepointToUtf8(input, utf8_bytes, &c[0])) {
87163
+ throw InvalidInputException("Invalid UTF8 Codepoint %d", input);
87164
+ }
87132
87165
  return string_t(&c[0]);
87133
87166
  }
87134
87167
  };
@@ -88869,7 +88902,9 @@ unique_ptr<FunctionData> BindPrintfFunction(ClientContext &context, ScalarFuncti
88869
88902
  template <class FORMAT_FUN, class CTX>
88870
88903
  static void PrintfFunction(DataChunk &args, ExpressionState &state, Vector &result) {
88871
88904
  auto &format_string = args.data[0];
88905
+ auto &result_validity = FlatVector::Validity(result);
88872
88906
  result.SetVectorType(VectorType::CONSTANT_VECTOR);
88907
+ result_validity.Initialize(args.size());
88873
88908
  for (idx_t i = 0; i < args.ColumnCount(); i++) {
88874
88909
  switch (args.data[i].GetVectorType()) {
88875
88910
  case VectorType::CONSTANT_VECTOR:
@@ -88884,7 +88919,7 @@ static void PrintfFunction(DataChunk &args, ExpressionState &state, Vector &resu
88884
88919
  // FLAT VECTOR, we can directly OR the nullmask
88885
88920
  args.data[i].Normalify(args.size());
88886
88921
  result.SetVectorType(VectorType::FLAT_VECTOR);
88887
- FlatVector::Validity(result).Combine(FlatVector::Validity(args.data[i]), args.size());
88922
+ result_validity.Combine(FlatVector::Validity(args.data[i]), args.size());
88888
88923
  break;
88889
88924
  }
88890
88925
  }
@@ -108069,7 +108104,7 @@ unique_ptr<Expression> InClauseRewriter::VisitReplace(BoundOperatorExpression &e
108069
108104
  DataChunk chunk;
108070
108105
  chunk.Initialize(types);
108071
108106
  for (idx_t i = 1; i < expr.children.size(); i++) {
108072
- // reoslve this expression to a constant
108107
+ // resolve this expression to a constant
108073
108108
  auto value = ExpressionExecutor::EvaluateScalar(*expr.children[i]);
108074
108109
  idx_t index = chunk.size();
108075
108110
  chunk.SetCardinality(chunk.size() + 1);
@@ -111479,7 +111514,10 @@ unique_ptr<Expression> ComparisonSimplificationRule::Apply(LogicalOperator &op,
111479
111514
  // the constant_expr is a scalar expression that we have to fold
111480
111515
  // use an ExpressionExecutor to execute the expression
111481
111516
  D_ASSERT(constant_expr->IsFoldable());
111482
- auto constant_value = ExpressionExecutor::EvaluateScalar(*constant_expr);
111517
+ Value constant_value;
111518
+ if (!ExpressionExecutor::TryEvaluateScalar(*constant_expr, constant_value)) {
111519
+ return nullptr;
111520
+ }
111483
111521
  if (constant_value.is_null && !(expr->type == ExpressionType::COMPARE_NOT_DISTINCT_FROM ||
111484
111522
  expr->type == ExpressionType::COMPARE_DISTINCT_FROM)) {
111485
111523
  // comparison with constant NULL, return NULL
@@ -111549,7 +111587,11 @@ unique_ptr<Expression> ConjunctionSimplificationRule::Apply(LogicalOperator &op,
111549
111587
  // the constant_expr is a scalar expression that we have to fold
111550
111588
  // use an ExpressionExecutor to execute the expression
111551
111589
  D_ASSERT(constant_expr->IsFoldable());
111552
- auto constant_value = ExpressionExecutor::EvaluateScalar(*constant_expr).CastAs(LogicalType::BOOLEAN);
111590
+ Value constant_value;
111591
+ if (!ExpressionExecutor::TryEvaluateScalar(*constant_expr, constant_value)) {
111592
+ return nullptr;
111593
+ }
111594
+ constant_value = constant_value.CastAs(LogicalType::BOOLEAN);
111553
111595
  if (constant_value.is_null) {
111554
111596
  // we can't simplify conjunctions with a constant NULL
111555
111597
  return nullptr;
@@ -111608,7 +111650,11 @@ unique_ptr<Expression> ConstantFoldingRule::Apply(LogicalOperator &op, vector<Ex
111608
111650
  D_ASSERT(root->IsFoldable() && root->type != ExpressionType::VALUE_CONSTANT);
111609
111651
 
111610
111652
  // use an ExpressionExecutor to execute the expression
111611
- auto result_value = ExpressionExecutor::EvaluateScalar(*root);
111653
+
111654
+ Value result_value;
111655
+ if (!ExpressionExecutor::TryEvaluateScalar(*root, result_value)) {
111656
+ return nullptr;
111657
+ }
111612
111658
  D_ASSERT(result_value.type().InternalType() == root->return_type.InternalType());
111613
111659
  // now get the value from the result vector and insert it back into the plan as a constant expression
111614
111660
  return make_unique<BoundConstantExpression>(result_value);
@@ -112800,6 +112846,42 @@ unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(BoundOperat
112800
112846
  return nullptr;
112801
112847
  }
112802
112848
  switch (expr.type) {
112849
+ case ExpressionType::OPERATOR_COALESCE:
112850
+ // COALESCE, merge stats of all children
112851
+ for (idx_t i = 0; i < expr.children.size(); i++) {
112852
+ D_ASSERT(child_stats[i]);
112853
+ if (!child_stats[i]->CanHaveNoNull()) {
112854
+ // this child is always NULL, we can remove it from the coalesce
112855
+ // UNLESS there is only one node remaining
112856
+ if (expr.children.size() > 1) {
112857
+ expr.children.erase(expr.children.begin() + i);
112858
+ child_stats.erase(child_stats.begin() + i);
112859
+ i--;
112860
+ }
112861
+ } else if (!child_stats[i]->CanHaveNull()) {
112862
+ // coalesce child cannot have NULL entries
112863
+ // this is the last coalesce node that influences the result
112864
+ // we can erase any children after this node
112865
+ if (i + 1 < expr.children.size()) {
112866
+ expr.children.erase(expr.children.begin() + i + 1, expr.children.end());
112867
+ child_stats.erase(child_stats.begin() + i + 1, child_stats.end());
112868
+ }
112869
+ break;
112870
+ }
112871
+ }
112872
+ D_ASSERT(!expr.children.empty());
112873
+ D_ASSERT(expr.children.size() == child_stats.size());
112874
+ if (expr.children.size() == 1) {
112875
+ // coalesce of one entry: simply return that entry
112876
+ *expr_ptr = move(expr.children[0]);
112877
+ } else {
112878
+ // coalesce of multiple entries
112879
+ // merge the stats
112880
+ for (idx_t i = 1; i < expr.children.size(); i++) {
112881
+ child_stats[0]->Merge(*child_stats[i]);
112882
+ }
112883
+ }
112884
+ return move(child_stats[0]);
112803
112885
  case ExpressionType::OPERATOR_IS_NULL:
112804
112886
  if (!child_stats[0]->CanHaveNull()) {
112805
112887
  // child has no null values: x IS NULL will always be false
@@ -135334,7 +135416,7 @@ static LogicalType ResolveNotType(OperatorExpression &op, vector<BoundExpression
135334
135416
 
135335
135417
  static LogicalType ResolveInType(OperatorExpression &op, vector<BoundExpression *> &children) {
135336
135418
  if (children.empty()) {
135337
- return LogicalType::BOOLEAN;
135419
+ throw InternalException("IN requires at least a single child node");
135338
135420
  }
135339
135421
  // get the maximum type from the children
135340
135422
  LogicalType max_type = children[0]->expr->return_type;
@@ -135360,8 +135442,11 @@ static LogicalType ResolveOperatorType(OperatorExpression &op, vector<BoundExpre
135360
135442
  return LogicalType::BOOLEAN;
135361
135443
  case ExpressionType::COMPARE_IN:
135362
135444
  case ExpressionType::COMPARE_NOT_IN:
135363
- case ExpressionType::OPERATOR_COALESCE:
135364
135445
  return ResolveInType(op, children);
135446
+ case ExpressionType::OPERATOR_COALESCE: {
135447
+ ResolveInType(op, children);
135448
+ return children[0]->expr->return_type;
135449
+ }
135365
135450
  case ExpressionType::OPERATOR_NOT:
135366
135451
  return ResolveNotType(op, children);
135367
135452
  default:
@@ -135424,23 +135509,11 @@ BindResult ExpressionBinder::BindExpression(OperatorExpression &op, idx_t depth)
135424
135509
  LogicalType result_type = ResolveOperatorType(op, children);
135425
135510
  if (op.type == ExpressionType::OPERATOR_COALESCE) {
135426
135511
  if (children.empty()) {
135427
- return BindResult("COALESCE needs at least one child");
135428
- }
135429
- unique_ptr<Expression> current_node;
135430
- for (size_t i = children.size(); i > 0; i--) {
135431
- auto child = move(children[i - 1]->expr);
135432
- if (!current_node) {
135433
- // no node yet: simply move the child
135434
- current_node = move(child);
135435
- } else {
135436
- // create a case statement
135437
- auto check =
135438
- make_unique<BoundOperatorExpression>(ExpressionType::OPERATOR_IS_NOT_NULL, LogicalType::BOOLEAN);
135439
- check->children.push_back(child->Copy());
135440
- current_node = make_unique<BoundCaseExpression>(move(check), move(child), move(current_node));
135441
- }
135512
+ throw BinderException("COALESCE needs at least one child");
135513
+ }
135514
+ if (children.size() == 1) {
135515
+ return BindResult(move(children[0]->expr));
135442
135516
  }
135443
- return BindResult(move(current_node));
135444
135517
  }
135445
135518
 
135446
135519
  auto result = make_unique<BoundOperatorExpression>(op.type, result_type);
package/src/duckdb.hpp CHANGED
@@ -10,8 +10,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
10
10
 
11
11
  #pragma once
12
12
  #define DUCKDB_AMALGAMATION 1
13
- #define DUCKDB_SOURCE_ID "88f04111c"
14
- #define DUCKDB_VERSION "0.3.1-dev360"
13
+ #define DUCKDB_SOURCE_ID "a45a86a8a"
14
+ #define DUCKDB_VERSION "0.3.1-dev399"
15
15
  //===----------------------------------------------------------------------===//
16
16
  // DuckDB
17
17
  //
@@ -2132,6 +2132,9 @@ public:
2132
2132
  sel_t *data() {
2133
2133
  return sel_vector;
2134
2134
  }
2135
+ const sel_t *data() const {
2136
+ return sel_vector;
2137
+ }
2135
2138
  buffer_ptr<SelectionData> sel_data() {
2136
2139
  return selection_data;
2137
2140
  }