duckdb 0.8.2-dev3055.0 → 0.8.2-dev3092.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/src/function/scalar/operators/add.cpp +9 -0
- package/src/duckdb/src/function/scalar/operators/arithmetic.cpp +6 -3
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/operator/add.hpp +5 -2
- package/src/duckdb/src/include/duckdb/common/operator/multiply.hpp +3 -2
- package/src/duckdb/src/include/duckdb/common/operator/subtract.hpp +3 -2
- package/src/duckdb/src/include/duckdb/optimizer/filter_pushdown.hpp +4 -0
- package/src/duckdb/src/optimizer/filter_pushdown.cpp +14 -6
- package/src/duckdb/src/optimizer/pushdown/pushdown_projection.cpp +34 -7
- package/test/extension.test.ts +1 -1
package/package.json
CHANGED
@@ -160,6 +160,15 @@ bool TryAddOperator::Operation(int64_t left, int64_t right, int64_t &result) {
|
|
160
160
|
return true;
|
161
161
|
}
|
162
162
|
|
163
|
+
template <>
|
164
|
+
bool TryAddOperator::Operation(hugeint_t left, hugeint_t right, hugeint_t &result) {
|
165
|
+
if (!Hugeint::AddInPlace(left, right)) {
|
166
|
+
return false;
|
167
|
+
}
|
168
|
+
result = left;
|
169
|
+
return true;
|
170
|
+
}
|
171
|
+
|
163
172
|
//===--------------------------------------------------------------------===//
|
164
173
|
// add decimal with overflow check
|
165
174
|
//===--------------------------------------------------------------------===//
|
@@ -35,6 +35,9 @@ static scalar_function_t GetScalarIntegerFunction(PhysicalType type) {
|
|
35
35
|
case PhysicalType::INT64:
|
36
36
|
function = &ScalarFunction::BinaryFunction<int64_t, int64_t, int64_t, OP>;
|
37
37
|
break;
|
38
|
+
case PhysicalType::INT128:
|
39
|
+
function = &ScalarFunction::BinaryFunction<hugeint_t, hugeint_t, hugeint_t, OP>;
|
40
|
+
break;
|
38
41
|
case PhysicalType::UINT8:
|
39
42
|
function = &ScalarFunction::BinaryFunction<uint8_t, uint8_t, uint8_t, OP>;
|
40
43
|
break;
|
@@ -302,7 +305,7 @@ ScalarFunction AddFun::GetFunction(const LogicalType &left_type, const LogicalTy
|
|
302
305
|
function.serialize = SerializeDecimalArithmetic;
|
303
306
|
function.deserialize = DeserializeDecimalArithmetic<AddOperator, DecimalAddOverflowCheck>;
|
304
307
|
return function;
|
305
|
-
} else if (left_type.IsIntegral()
|
308
|
+
} else if (left_type.IsIntegral()) {
|
306
309
|
return ScalarFunction("+", {left_type, right_type}, left_type,
|
307
310
|
GetScalarIntegerFunction<AddOperatorOverflowCheck>(left_type.InternalType()), nullptr,
|
308
311
|
nullptr, PropagateNumericStats<TryAddOperator, AddPropagateStatistics, AddOperator>);
|
@@ -564,7 +567,7 @@ ScalarFunction SubtractFun::GetFunction(const LogicalType &left_type, const Logi
|
|
564
567
|
function.serialize = SerializeDecimalArithmetic;
|
565
568
|
function.deserialize = DeserializeDecimalArithmetic<SubtractOperator, DecimalSubtractOverflowCheck>;
|
566
569
|
return function;
|
567
|
-
} else if (left_type.IsIntegral()
|
570
|
+
} else if (left_type.IsIntegral()) {
|
568
571
|
return ScalarFunction(
|
569
572
|
"-", {left_type, right_type}, left_type,
|
570
573
|
GetScalarIntegerFunction<SubtractOperatorOverflowCheck>(left_type.InternalType()), nullptr, nullptr,
|
@@ -768,7 +771,7 @@ void MultiplyFun::RegisterFunction(BuiltinFunctions &set) {
|
|
768
771
|
function.serialize = SerializeDecimalArithmetic;
|
769
772
|
function.deserialize = DeserializeDecimalArithmetic<MultiplyOperator, DecimalMultiplyOverflowCheck>;
|
770
773
|
functions.AddFunction(function);
|
771
|
-
} else if (TypeIsIntegral(type.InternalType())
|
774
|
+
} else if (TypeIsIntegral(type.InternalType())) {
|
772
775
|
functions.AddFunction(ScalarFunction(
|
773
776
|
{type, type}, type, GetScalarIntegerFunction<MultiplyOperatorOverflowCheck>(type.InternalType()),
|
774
777
|
nullptr, nullptr,
|
@@ -1,8 +1,8 @@
|
|
1
1
|
#ifndef DUCKDB_VERSION
|
2
|
-
#define DUCKDB_VERSION "0.8.2-
|
2
|
+
#define DUCKDB_VERSION "0.8.2-dev3092"
|
3
3
|
#endif
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
5
|
+
#define DUCKDB_SOURCE_ID "1f17e1cec6"
|
6
6
|
#endif
|
7
7
|
#include "duckdb/function/table/system_functions.hpp"
|
8
8
|
#include "duckdb/main/database.hpp"
|
@@ -11,6 +11,7 @@
|
|
11
11
|
#include "duckdb/common/types.hpp"
|
12
12
|
#include "duckdb/common/type_util.hpp"
|
13
13
|
#include "duckdb/common/exception.hpp"
|
14
|
+
#include "duckdb/common/types/cast_helpers.hpp"
|
14
15
|
|
15
16
|
namespace duckdb {
|
16
17
|
|
@@ -68,14 +69,16 @@ template <>
|
|
68
69
|
bool TryAddOperator::Operation(int32_t left, int32_t right, int32_t &result);
|
69
70
|
template <>
|
70
71
|
DUCKDB_API bool TryAddOperator::Operation(int64_t left, int64_t right, int64_t &result);
|
72
|
+
template <>
|
73
|
+
bool TryAddOperator::Operation(hugeint_t left, hugeint_t right, hugeint_t &result);
|
71
74
|
|
72
75
|
struct AddOperatorOverflowCheck {
|
73
76
|
template <class TA, class TB, class TR>
|
74
77
|
static inline TR Operation(TA left, TB right) {
|
75
78
|
TR result;
|
76
79
|
if (!TryAddOperator::Operation(left, right, result)) {
|
77
|
-
throw OutOfRangeException("Overflow in addition of %s (%
|
78
|
-
right);
|
80
|
+
throw OutOfRangeException("Overflow in addition of %s (%s + %s)!", TypeIdToString(GetTypeId<TA>()),
|
81
|
+
NumericHelper::ToString(left), NumericHelper::ToString(right));
|
79
82
|
}
|
80
83
|
return result;
|
81
84
|
}
|
@@ -11,6 +11,7 @@
|
|
11
11
|
#include "duckdb/common/types.hpp"
|
12
12
|
#include "duckdb/common/exception.hpp"
|
13
13
|
#include "duckdb/common/type_util.hpp"
|
14
|
+
#include "duckdb/common/types/cast_helpers.hpp"
|
14
15
|
|
15
16
|
namespace duckdb {
|
16
17
|
|
@@ -64,8 +65,8 @@ struct MultiplyOperatorOverflowCheck {
|
|
64
65
|
static inline TR Operation(TA left, TB right) {
|
65
66
|
TR result;
|
66
67
|
if (!TryMultiplyOperator::Operation(left, right, result)) {
|
67
|
-
throw OutOfRangeException("Overflow in multiplication of %s (%
|
68
|
-
left, right);
|
68
|
+
throw OutOfRangeException("Overflow in multiplication of %s (%s * %s)!", TypeIdToString(GetTypeId<TA>()),
|
69
|
+
NumericHelper::ToString(left), NumericHelper::ToString(right));
|
69
70
|
}
|
70
71
|
return result;
|
71
72
|
}
|
@@ -11,6 +11,7 @@
|
|
11
11
|
#include "duckdb/common/types.hpp"
|
12
12
|
#include "duckdb/common/exception.hpp"
|
13
13
|
#include "duckdb/common/type_util.hpp"
|
14
|
+
#include "duckdb/common/types/cast_helpers.hpp"
|
14
15
|
|
15
16
|
namespace duckdb {
|
16
17
|
|
@@ -75,8 +76,8 @@ struct SubtractOperatorOverflowCheck {
|
|
75
76
|
static inline TR Operation(TA left, TB right) {
|
76
77
|
TR result;
|
77
78
|
if (!TrySubtractOperator::Operation(left, right, result)) {
|
78
|
-
throw OutOfRangeException("Overflow in subtraction of %s (%
|
79
|
-
right);
|
79
|
+
throw OutOfRangeException("Overflow in subtraction of %s (%s - %s)!", TypeIdToString(GetTypeId<TA>()),
|
80
|
+
NumericHelper::ToString(left), NumericHelper::ToString(right));
|
80
81
|
}
|
81
82
|
return result;
|
82
83
|
}
|
@@ -70,6 +70,10 @@ private:
|
|
70
70
|
unique_ptr<LogicalOperator> PushdownSingleJoin(unique_ptr<LogicalOperator> op, unordered_set<idx_t> &left_bindings,
|
71
71
|
unordered_set<idx_t> &right_bindings);
|
72
72
|
|
73
|
+
// AddLogicalFilter used to add an extra LogicalFilter at this level,
|
74
|
+
// because in some cases, some expressions can not be pushed down.
|
75
|
+
unique_ptr<LogicalOperator> AddLogicalFilter(unique_ptr<LogicalOperator> op,
|
76
|
+
vector<unique_ptr<Expression>> expressions);
|
73
77
|
//! Push any remaining filters into a LogicalFilter at this level
|
74
78
|
unique_ptr<LogicalOperator> PushFinalFilters(unique_ptr<LogicalOperator> op);
|
75
79
|
// Finish pushing down at this operator, creating a LogicalFilter to store any of the stored filters and recursively
|
@@ -116,19 +116,27 @@ void FilterPushdown::GenerateFilters() {
|
|
116
116
|
});
|
117
117
|
}
|
118
118
|
|
119
|
-
unique_ptr<LogicalOperator> FilterPushdown::
|
120
|
-
|
121
|
-
|
119
|
+
unique_ptr<LogicalOperator> FilterPushdown::AddLogicalFilter(unique_ptr<LogicalOperator> op,
|
120
|
+
vector<unique_ptr<Expression>> expressions) {
|
121
|
+
if (expressions.empty()) {
|
122
|
+
// No left expressions, so needn't to add an extra filter operator.
|
122
123
|
return op;
|
123
124
|
}
|
124
125
|
auto filter = make_uniq<LogicalFilter>();
|
125
|
-
|
126
|
-
filter->expressions.push_back(std::move(f->filter));
|
127
|
-
}
|
126
|
+
filter->expressions = std::move(expressions);
|
128
127
|
filter->children.push_back(std::move(op));
|
129
128
|
return std::move(filter);
|
130
129
|
}
|
131
130
|
|
131
|
+
unique_ptr<LogicalOperator> FilterPushdown::PushFinalFilters(unique_ptr<LogicalOperator> op) {
|
132
|
+
vector<unique_ptr<Expression>> expressions;
|
133
|
+
for (auto &f : filters) {
|
134
|
+
expressions.push_back(std::move(f->filter));
|
135
|
+
}
|
136
|
+
|
137
|
+
return AddLogicalFilter(std::move(op), std::move(expressions));
|
138
|
+
}
|
139
|
+
|
132
140
|
unique_ptr<LogicalOperator> FilterPushdown::FinishPushdown(unique_ptr<LogicalOperator> op) {
|
133
141
|
// unhandled type, first perform filter pushdown in its children
|
134
142
|
for (auto &child : op->children) {
|
@@ -6,6 +6,23 @@
|
|
6
6
|
|
7
7
|
namespace duckdb {
|
8
8
|
|
9
|
+
static bool HasSideEffects(LogicalProjection &proj, const unique_ptr<Expression> &expr) {
|
10
|
+
if (expr->type == ExpressionType::BOUND_COLUMN_REF) {
|
11
|
+
auto &colref = expr->Cast<BoundColumnRefExpression>();
|
12
|
+
D_ASSERT(colref.binding.table_index == proj.table_index);
|
13
|
+
D_ASSERT(colref.binding.column_index < proj.expressions.size());
|
14
|
+
D_ASSERT(colref.depth == 0);
|
15
|
+
if (proj.expressions[colref.binding.column_index]->HasSideEffects()) {
|
16
|
+
return true;
|
17
|
+
}
|
18
|
+
return false;
|
19
|
+
}
|
20
|
+
bool has_side_effects = false;
|
21
|
+
ExpressionIterator::EnumerateChildren(
|
22
|
+
*expr, [&](unique_ptr<Expression> &child) { has_side_effects |= HasSideEffects(proj, child); });
|
23
|
+
return has_side_effects;
|
24
|
+
}
|
25
|
+
|
9
26
|
static unique_ptr<Expression> ReplaceProjectionBindings(LogicalProjection &proj, unique_ptr<Expression> expr) {
|
10
27
|
if (expr->type == ExpressionType::BOUND_COLUMN_REF) {
|
11
28
|
auto &colref = expr->Cast<BoundColumnRefExpression>();
|
@@ -27,15 +44,25 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownProjection(unique_ptr<Logica
|
|
27
44
|
// all the BoundColumnRefExpressions in the filter should refer to the LogicalProjection
|
28
45
|
// we can rewrite them by replacing those references with the expression of the LogicalProjection node
|
29
46
|
FilterPushdown child_pushdown(optimizer);
|
47
|
+
// There are some expressions can not be pushed down. We should keep them
|
48
|
+
// and add an extra filter operator.
|
49
|
+
vector<unique_ptr<Expression>> remain_expressions;
|
30
50
|
for (auto &filter : filters) {
|
31
51
|
auto &f = *filter;
|
32
52
|
D_ASSERT(f.bindings.size() <= 1);
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
53
|
+
bool has_side_effects = HasSideEffects(proj, f.filter);
|
54
|
+
if (has_side_effects) {
|
55
|
+
// We can't push down related expressions if the column in the
|
56
|
+
// expression is generated by the functions which have side effects
|
57
|
+
remain_expressions.push_back(std::move(f.filter));
|
58
|
+
} else {
|
59
|
+
// rewrite the bindings within this subquery
|
60
|
+
f.filter = ReplaceProjectionBindings(proj, std::move(f.filter));
|
61
|
+
// add the filter to the child pushdown
|
62
|
+
if (child_pushdown.AddFilter(std::move(f.filter)) == FilterResult::UNSATISFIABLE) {
|
63
|
+
// filter statically evaluates to false, strip tree
|
64
|
+
return make_uniq<LogicalEmptyResult>(std::move(op));
|
65
|
+
}
|
39
66
|
}
|
40
67
|
}
|
41
68
|
child_pushdown.GenerateFilters();
|
@@ -45,7 +72,7 @@ unique_ptr<LogicalOperator> FilterPushdown::PushdownProjection(unique_ptr<Logica
|
|
45
72
|
// child returns an empty result: generate an empty result here too
|
46
73
|
return make_uniq<LogicalEmptyResult>(std::move(op));
|
47
74
|
}
|
48
|
-
return op;
|
75
|
+
return AddLogicalFilter(std::move(op), std::move(remain_expressions));
|
49
76
|
}
|
50
77
|
|
51
78
|
} // namespace duckdb
|
package/test/extension.test.ts
CHANGED
@@ -37,7 +37,7 @@ const test_httpfs = async function (db: duckdb.Database) {
|
|
37
37
|
}));
|
38
38
|
await chai.assert.isRejected(promise, 'IO Error: Connection error for HTTP HEAD');
|
39
39
|
|
40
|
-
await new Promise<void>((resolve, reject) => db.all("SELECT id, first_name, last_name FROM PARQUET_SCAN('https://raw.githubusercontent.com/
|
40
|
+
await new Promise<void>((resolve, reject) => db.all("SELECT id, first_name, last_name FROM PARQUET_SCAN('https://raw.githubusercontent.com/duckdb/duckdb/main/data/parquet-testing/userdata1.parquet') LIMIT 3;", function (err: null | Error, rows: TableData) {
|
41
41
|
if (err) {
|
42
42
|
if (err.message.startsWith("Unable to connect to URL")) {
|
43
43
|
console.warn("Warning: HTTP request failed in extension.test.js");
|