duckdb 0.8.2-dev3007.0 → 0.8.2-dev3079.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
@@ -2,7 +2,7 @@
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
4
  "types": "./lib/duckdb.d.ts",
5
- "version": "0.8.2-dev3007.0",
5
+ "version": "0.8.2-dev3079.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
@@ -468,11 +468,12 @@ struct SortedAggregateFunction {
468
468
 
469
469
  // These are all simple updates, so use it if available
470
470
  if (simple_update) {
471
- simple_update(sliced.data.data(), aggr_bind_info, 1, agg_state.data(), sliced.size());
471
+ simple_update(sliced.data.data(), aggr_bind_info, sliced.data.size(), agg_state.data(),
472
+ sliced.size());
472
473
  } else {
473
474
  // We are only updating a constant state
474
475
  agg_state_vec.SetVectorType(VectorType::CONSTANT_VECTOR);
475
- update(sliced.data.data(), aggr_bind_info, 1, agg_state_vec, sliced.size());
476
+ update(sliced.data.data(), aggr_bind_info, sliced.data.size(), agg_state_vec, sliced.size());
476
477
  }
477
478
 
478
479
  consumed += input_count;
@@ -1,8 +1,8 @@
1
1
  #ifndef DUCKDB_VERSION
2
- #define DUCKDB_VERSION "0.8.2-dev3007"
2
+ #define DUCKDB_VERSION "0.8.2-dev3079"
3
3
  #endif
4
4
  #ifndef DUCKDB_SOURCE_ID
5
- #define DUCKDB_SOURCE_ID "dd7f0c0870"
5
+ #define DUCKDB_SOURCE_ID "3cc87593cf"
6
6
  #endif
7
7
  #include "duckdb/function/table/system_functions.hpp"
8
8
  #include "duckdb/main/database.hpp"
@@ -23,6 +23,10 @@ public:
23
23
  DUCKDB_API static void RegisterFunction(DatabaseInstance &db, ScalarFunction function);
24
24
  //! Register a new scalar function set - throw an exception if the function already exists
25
25
  DUCKDB_API static void RegisterFunction(DatabaseInstance &db, ScalarFunctionSet function);
26
+ //! Register a new aggregate function - throw an exception if the function already exists
27
+ DUCKDB_API static void RegisterFunction(DatabaseInstance &db, AggregateFunction function);
28
+ //! Register a new aggregate function set - throw an exception if the function already exists
29
+ DUCKDB_API static void RegisterFunction(DatabaseInstance &db, AggregateFunctionSet function);
26
30
  //! Register a new table function - throw an exception if the function already exists
27
31
  DUCKDB_API static void RegisterFunction(DatabaseInstance &db, TableFunction function);
28
32
  //! Register a new table function set - throw an exception if the function already exists
@@ -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
@@ -1,5 +1,6 @@
1
1
  #include "duckdb/main/extension_util.hpp"
2
2
  #include "duckdb/function/scalar_function.hpp"
3
+ #include "duckdb/parser/parsed_data/create_aggregate_function_info.hpp"
3
4
  #include "duckdb/parser/parsed_data/create_type_info.hpp"
4
5
  #include "duckdb/parser/parsed_data/create_copy_function_info.hpp"
5
6
  #include "duckdb/parser/parsed_data/create_pragma_function_info.hpp"
@@ -26,6 +27,21 @@ void ExtensionUtil::RegisterFunction(DatabaseInstance &db, ScalarFunction functi
26
27
  RegisterFunction(db, std::move(set));
27
28
  }
28
29
 
30
+ void ExtensionUtil::RegisterFunction(DatabaseInstance &db, AggregateFunction function) {
31
+ D_ASSERT(!function.name.empty());
32
+ AggregateFunctionSet set(function.name);
33
+ set.AddFunction(std::move(function));
34
+ RegisterFunction(db, std::move(set));
35
+ }
36
+
37
+ void ExtensionUtil::RegisterFunction(DatabaseInstance &db, AggregateFunctionSet set) {
38
+ D_ASSERT(!set.name.empty());
39
+ CreateAggregateFunctionInfo info(std::move(set));
40
+ auto &system_catalog = Catalog::GetSystemCatalog(db);
41
+ auto data = CatalogTransaction::GetSystemTransaction(db);
42
+ system_catalog.CreateFunction(data, info);
43
+ }
44
+
29
45
  void ExtensionUtil::RegisterFunction(DatabaseInstance &db, TableFunction function) {
30
46
  D_ASSERT(!function.name.empty());
31
47
  TableFunctionSet set(function.name);
@@ -116,19 +116,27 @@ void FilterPushdown::GenerateFilters() {
116
116
  });
117
117
  }
118
118
 
119
- unique_ptr<LogicalOperator> FilterPushdown::PushFinalFilters(unique_ptr<LogicalOperator> op) {
120
- if (filters.empty()) {
121
- // no filters to push
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
- for (auto &f : filters) {
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
- // rewrite the bindings within this subquery
34
- f.filter = ReplaceProjectionBindings(proj, std::move(f.filter));
35
- // add the filter to the child pushdown
36
- if (child_pushdown.AddFilter(std::move(f.filter)) == FilterResult::UNSATISFIABLE) {
37
- // filter statically evaluates to false, strip tree
38
- return make_uniq<LogicalEmptyResult>(std::move(op));
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
@@ -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/cwida/duckdb/master/data/parquet-testing/userdata1.parquet') LIMIT 3;", function (err: null | Error, rows: TableData) {
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");