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 +1 -1
- package/src/duckdb.cpp +171 -98
- package/src/duckdb.hpp +5 -2
package/package.json
CHANGED
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
48510
|
+
TemplatedFillLoop<int8_t>(vector, result, sel, count);
|
|
48524
48511
|
break;
|
|
48525
48512
|
case PhysicalType::INT16:
|
|
48526
|
-
|
|
48513
|
+
TemplatedFillLoop<int16_t>(vector, result, sel, count);
|
|
48527
48514
|
break;
|
|
48528
48515
|
case PhysicalType::INT32:
|
|
48529
|
-
|
|
48516
|
+
TemplatedFillLoop<int32_t>(vector, result, sel, count);
|
|
48530
48517
|
break;
|
|
48531
48518
|
case PhysicalType::INT64:
|
|
48532
|
-
|
|
48519
|
+
TemplatedFillLoop<int64_t>(vector, result, sel, count);
|
|
48533
48520
|
break;
|
|
48534
48521
|
case PhysicalType::UINT8:
|
|
48535
|
-
|
|
48522
|
+
TemplatedFillLoop<uint8_t>(vector, result, sel, count);
|
|
48536
48523
|
break;
|
|
48537
48524
|
case PhysicalType::UINT16:
|
|
48538
|
-
|
|
48525
|
+
TemplatedFillLoop<uint16_t>(vector, result, sel, count);
|
|
48539
48526
|
break;
|
|
48540
48527
|
case PhysicalType::UINT32:
|
|
48541
|
-
|
|
48528
|
+
TemplatedFillLoop<uint32_t>(vector, result, sel, count);
|
|
48542
48529
|
break;
|
|
48543
48530
|
case PhysicalType::UINT64:
|
|
48544
|
-
|
|
48531
|
+
TemplatedFillLoop<uint64_t>(vector, result, sel, count);
|
|
48545
48532
|
break;
|
|
48546
48533
|
case PhysicalType::INT128:
|
|
48547
|
-
|
|
48534
|
+
TemplatedFillLoop<hugeint_t>(vector, result, sel, count);
|
|
48548
48535
|
break;
|
|
48549
48536
|
case PhysicalType::FLOAT:
|
|
48550
|
-
|
|
48537
|
+
TemplatedFillLoop<float>(vector, result, sel, count);
|
|
48551
48538
|
break;
|
|
48552
48539
|
case PhysicalType::DOUBLE:
|
|
48553
|
-
|
|
48540
|
+
TemplatedFillLoop<double>(vector, result, sel, count);
|
|
48554
48541
|
break;
|
|
48555
48542
|
case PhysicalType::INTERVAL:
|
|
48556
|
-
|
|
48543
|
+
TemplatedFillLoop<interval_t>(vector, result, sel, count);
|
|
48557
48544
|
break;
|
|
48558
48545
|
case PhysicalType::VARCHAR:
|
|
48559
|
-
|
|
48560
|
-
StringVector::AddHeapReference(result,
|
|
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 &
|
|
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
|
-
|
|
48568
|
-
|
|
48569
|
-
|
|
48570
|
-
|
|
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 =
|
|
48577
|
-
|
|
48578
|
-
|
|
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>(
|
|
48587
|
-
|
|
48588
|
-
|
|
48589
|
-
|
|
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
|
-
|
|
48598
|
-
|
|
48599
|
-
auto
|
|
48600
|
-
|
|
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(
|
|
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
|
-
|
|
77160
|
-
|
|
77161
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
135428
|
-
}
|
|
135429
|
-
|
|
135430
|
-
|
|
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 "
|
|
14
|
-
#define DUCKDB_VERSION "0.3.1-
|
|
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
|
}
|