duckdb 0.6.1-dev131.0 → 0.6.1-dev140.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.6.1-dev131.0",
5
+ "version": "0.6.1-dev140.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
@@ -63,41 +63,6 @@ struct NodeReplacementScanData : duckdb::ReplacementScanData {
63
63
  Connection *connection_ref;
64
64
  };
65
65
 
66
- static duckdb::unique_ptr<duckdb::TableFunctionRef>
67
- ScanReplacement(duckdb::ClientContext &context, const std::string &table_name, duckdb::ReplacementScanData *data) {
68
- auto &buffers = ((NodeReplacementScanData *)data)->connection_ref->buffers;
69
- // Lookup buffer
70
- auto lookup = buffers.find(table_name);
71
- if (lookup == buffers.end()) {
72
- return nullptr;
73
- }
74
-
75
- // Create table scan on ipc buffers
76
- auto name = lookup->first;
77
- auto ipc_buffer_array = lookup->second;
78
-
79
- auto table_function = duckdb::make_unique<duckdb::TableFunctionRef>();
80
- std::vector<duckdb::unique_ptr<duckdb::ParsedExpression>> table_fun_children;
81
-
82
- duckdb::vector<duckdb::Value> list_children;
83
-
84
- for (uint64_t ipc_idx = 0; ipc_idx < ipc_buffer_array.size(); ipc_idx++) {
85
- auto &v = ipc_buffer_array[ipc_idx];
86
- duckdb::child_list_t<duckdb::Value> struct_children;
87
- struct_children.push_back(make_pair("ptr", duckdb::Value::UBIGINT(v.first)));
88
- struct_children.push_back(make_pair("size", duckdb::Value::UBIGINT(v.second)));
89
-
90
- // Push struct into table fun
91
- list_children.push_back(duckdb::Value::STRUCT(move(struct_children)));
92
- }
93
-
94
- table_fun_children.push_back(
95
- duckdb::make_unique<duckdb::ConstantExpression>(duckdb::Value::LIST(move(list_children))));
96
- table_function->function =
97
- duckdb::make_unique<duckdb::FunctionExpression>("scan_arrow_ipc", move(table_fun_children));
98
- return table_function;
99
- }
100
-
101
66
  Connection::Connection(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Connection>(info) {
102
67
  Napi::Env env = info.Env();
103
68
  int length = info.Length();
@@ -339,70 +304,6 @@ Napi::Value Connection::RegisterUdf(const Napi::CallbackInfo &info) {
339
304
  return Value();
340
305
  }
341
306
 
342
- // Register Arrow IPC buffers for scanning from DuckDB
343
- Napi::Value Connection::RegisterBuffer(const Napi::CallbackInfo &info) {
344
- auto env = info.Env();
345
-
346
- Napi::TypeError::New(env, "Register buffer currently not implemented").ThrowAsJavaScriptException();
347
- return env.Null();
348
-
349
- if (info.Length() < 2 || !info[0].IsString() || !info[1].IsObject()) {
350
- Napi::TypeError::New(env, "Incorrect params").ThrowAsJavaScriptException();
351
- return env.Null();
352
- }
353
-
354
- std::string name = info[0].As<Napi::String>();
355
- Napi::Array array = info[1].As<Napi::Array>();
356
- bool force_register = false;
357
-
358
- if (info.Length() > 2) {
359
- if (!info[2].IsBoolean()) {
360
- Napi::TypeError::New(env, "Incorrect params").ThrowAsJavaScriptException();
361
- return env.Null();
362
- }
363
- force_register = info[2].As<Napi::Boolean>().Value();
364
- }
365
-
366
- array_references[name] = Napi::Persistent(array);
367
-
368
- if (!force_register && buffers.find(name) != buffers.end()) {
369
- Napi::TypeError::New(env, "Buffer with this name already exists").ThrowAsJavaScriptException();
370
- return env.Null();
371
- }
372
-
373
- buffers[name] = std::vector<std::pair<uint64_t, uint64_t>>();
374
-
375
- for (uint64_t ipc_idx = 0; ipc_idx < array.Length(); ipc_idx++) {
376
- Napi::Value v = array[ipc_idx];
377
- if (!v.IsObject()) {
378
- Napi::TypeError::New(env, "Incorrect params").ThrowAsJavaScriptException();
379
- return env.Null();
380
- }
381
- Napi::Uint8Array arr = v.As<Napi::Uint8Array>();
382
- auto raw_ptr = reinterpret_cast<uint64_t>(arr.ArrayBuffer().Data());
383
- auto length = (uint64_t)arr.ElementLength();
384
-
385
- buffers[name].push_back(std::pair<uint64_t, uint64_t>({raw_ptr, length}));
386
- }
387
-
388
- return Value();
389
- }
390
-
391
- Napi::Value Connection::UnRegisterBuffer(const Napi::CallbackInfo &info) {
392
- auto env = info.Env();
393
-
394
- Napi::TypeError::New(env, "Register buffer currently not implemented").ThrowAsJavaScriptException();
395
- return env.Null();
396
-
397
- if (info.Length() != 1 || !info[0].IsString()) {
398
- Napi::TypeError::New(env, "Holding it wrong").ThrowAsJavaScriptException();
399
- return env.Null();
400
- }
401
- std::string name = info[0].As<Napi::String>();
402
- buffers.erase(name);
403
- return Value();
404
- }
405
-
406
307
  struct UnregisterUdfTask : public Task {
407
308
  UnregisterUdfTask(Connection &connection, std::string name, Napi::Function callback)
408
309
  : Task(connection, callback), name(std::move(name)) {
@@ -487,6 +388,20 @@ struct ExecTask : public Task {
487
388
  duckdb::PreservedError error;
488
389
  };
489
390
 
391
+ struct ExecTaskWithCallback : public ExecTask {
392
+ ExecTaskWithCallback(Connection &connection, std::string sql, Napi::Function js_callback,
393
+ std::function<void(void)> cpp_callback)
394
+ : ExecTask(connection, sql, js_callback), cpp_callback(cpp_callback) {
395
+ }
396
+
397
+ void Callback() override {
398
+ cpp_callback();
399
+ ExecTask::Callback();
400
+ };
401
+
402
+ std::function<void(void)> cpp_callback;
403
+ };
404
+
490
405
  Napi::Value Connection::Exec(const Napi::CallbackInfo &info) {
491
406
  auto env = info.Env();
492
407
 
@@ -506,4 +421,90 @@ Napi::Value Connection::Exec(const Napi::CallbackInfo &info) {
506
421
  return Value();
507
422
  }
508
423
 
424
+ // Register Arrow IPC buffers for scanning from DuckDB
425
+ Napi::Value Connection::RegisterBuffer(const Napi::CallbackInfo &info) {
426
+ auto env = info.Env();
427
+
428
+ if (info.Length() < 2 || !info[0].IsString() || !info[1].IsObject()) {
429
+ Napi::TypeError::New(env, "Incorrect params").ThrowAsJavaScriptException();
430
+ return env.Null();
431
+ }
432
+
433
+ std::string name = info[0].As<Napi::String>();
434
+ Napi::Array array = info[1].As<Napi::Array>();
435
+ bool force_register = false;
436
+
437
+ if (info.Length() > 2) {
438
+ if (!info[2].IsBoolean()) {
439
+ Napi::TypeError::New(env, "Parameter 3 is of unexpected type. Expected boolean")
440
+ .ThrowAsJavaScriptException();
441
+ return env.Null();
442
+ }
443
+ force_register = info[2].As<Napi::Boolean>().Value();
444
+ }
445
+
446
+ if (!force_register && array_references.find(name) != array_references.end()) {
447
+ Napi::TypeError::New(env, "Buffer with this name already exists and force_register is not enabled")
448
+ .ThrowAsJavaScriptException();
449
+ return env.Null();
450
+ }
451
+
452
+ array_references[name] = Napi::Persistent(array);
453
+
454
+ std::string arrow_scan_function = "scan_arrow_ipc([";
455
+
456
+ for (uint64_t ipc_idx = 0; ipc_idx < array.Length(); ipc_idx++) {
457
+ Napi::Value v = array[ipc_idx];
458
+ if (!v.IsObject()) {
459
+ Napi::TypeError::New(env, "Parameter 2 contains unexpected type at index " + std::to_string(ipc_idx))
460
+ .ThrowAsJavaScriptException();
461
+ return env.Null();
462
+ }
463
+ Napi::Uint8Array arr = v.As<Napi::Uint8Array>();
464
+ auto raw_ptr = reinterpret_cast<uint64_t>(arr.ArrayBuffer().Data());
465
+ auto length = (uint64_t)arr.ElementLength();
466
+
467
+ arrow_scan_function += "{'ptr': " + std::to_string(raw_ptr) + ", 'size': " + std::to_string(length) + "},";
468
+ }
469
+ arrow_scan_function += "])";
470
+
471
+ std::string final_query = "CREATE OR REPLACE TEMPORARY VIEW " + name + " AS SELECT * FROM " + arrow_scan_function;
472
+
473
+ Napi::Function callback;
474
+ if (info.Length() > 3 && info[3].IsFunction()) {
475
+ callback = info[3].As<Napi::Function>();
476
+ }
477
+
478
+ database_ref->Schedule(info.Env(), duckdb::make_unique<ExecTask>(*this, final_query, callback));
479
+
480
+ return Value();
481
+ }
482
+
483
+ Napi::Value Connection::UnRegisterBuffer(const Napi::CallbackInfo &info) {
484
+ auto env = info.Env();
485
+
486
+ if (info.Length() < 1 || !info[0].IsString()) {
487
+ Napi::TypeError::New(env, "Incorrect params").ThrowAsJavaScriptException();
488
+ return env.Null();
489
+ }
490
+ std::string name = info[0].As<Napi::String>();
491
+
492
+ std::string final_query = "DROP VIEW IF EXISTS " + name;
493
+
494
+ Napi::Function callback;
495
+ if (info.Length() > 1 && info[1].IsFunction()) {
496
+ callback = info[1].As<Napi::Function>();
497
+ }
498
+
499
+ // When query succeeds we can safely delete the ref
500
+ std::function<void(void)> cpp_callback = [&, name]() {
501
+ array_references.erase(name);
502
+ };
503
+
504
+ database_ref->Schedule(info.Env(),
505
+ duckdb::make_unique<ExecTaskWithCallback>(*this, final_query, callback, cpp_callback));
506
+
507
+ return Value();
508
+ }
509
+
509
510
  } // namespace node_duckdb
package/src/duckdb.cpp CHANGED
@@ -193749,6 +193749,33 @@ unique_ptr<BoundTableRef> Binder::Bind(SubqueryRef &ref, CommonTableExpressionIn
193749
193749
 
193750
193750
 
193751
193751
 
193752
+ //===----------------------------------------------------------------------===//
193753
+ // DuckDB
193754
+ //
193755
+ // duckdb/planner/expression_binder/table_function_binder.hpp
193756
+ //
193757
+ //
193758
+ //===----------------------------------------------------------------------===//
193759
+
193760
+
193761
+
193762
+
193763
+
193764
+ namespace duckdb {
193765
+
193766
+ //! The Table function binder can bind standard table function parameters (i.e. non-table-in-out functions)
193767
+ class TableFunctionBinder : public ExpressionBinder {
193768
+ public:
193769
+ TableFunctionBinder(Binder &binder, ClientContext &context);
193770
+
193771
+ protected:
193772
+ BindResult BindColumnReference(ColumnRefExpression &expr);
193773
+ BindResult BindExpression(unique_ptr<ParsedExpression> *expr, idx_t depth, bool root_expression = false) override;
193774
+
193775
+ string UnsupportedAggregateMessage() override;
193776
+ };
193777
+
193778
+ } // namespace duckdb
193752
193779
 
193753
193780
 
193754
193781
 
@@ -193825,7 +193852,7 @@ bool Binder::BindTableFunctionParameters(TableFunctionCatalogEntry &table_functi
193825
193852
  continue;
193826
193853
  }
193827
193854
 
193828
- ConstantBinder binder(*this, context, "TABLE FUNCTION parameter");
193855
+ TableFunctionBinder binder(*this, context);
193829
193856
  LogicalType sql_type;
193830
193857
  auto expr = binder.Bind(child, &sql_type);
193831
193858
  if (expr->HasParameter()) {
@@ -197291,6 +197318,42 @@ BindResult SelectBinder::BindGroup(ParsedExpression &expr, idx_t depth, idx_t gr
197291
197318
  } // namespace duckdb
197292
197319
 
197293
197320
 
197321
+
197322
+
197323
+ namespace duckdb {
197324
+
197325
+ TableFunctionBinder::TableFunctionBinder(Binder &binder, ClientContext &context) : ExpressionBinder(binder, context) {
197326
+ }
197327
+
197328
+ BindResult TableFunctionBinder::BindColumnReference(ColumnRefExpression &expr) {
197329
+ auto result_name = StringUtil::Join(expr.column_names, ".");
197330
+ return BindResult(make_unique<BoundConstantExpression>(Value(result_name)));
197331
+ }
197332
+
197333
+ BindResult TableFunctionBinder::BindExpression(unique_ptr<ParsedExpression> *expr_ptr, idx_t depth,
197334
+ bool root_expression) {
197335
+ auto &expr = **expr_ptr;
197336
+ switch (expr.GetExpressionClass()) {
197337
+ case ExpressionClass::COLUMN_REF:
197338
+ return BindColumnReference((ColumnRefExpression &)expr);
197339
+ case ExpressionClass::SUBQUERY:
197340
+ throw BinderException("Table function cannot contain subqueries");
197341
+ case ExpressionClass::DEFAULT:
197342
+ return BindResult("Table function cannot contain DEFAULT clause");
197343
+ case ExpressionClass::WINDOW:
197344
+ return BindResult("Table function cannot contain window functions!");
197345
+ default:
197346
+ return ExpressionBinder::BindExpression(expr_ptr, depth);
197347
+ }
197348
+ }
197349
+
197350
+ string TableFunctionBinder::UnsupportedAggregateMessage() {
197351
+ return "Table function cannot contain aggregates!";
197352
+ }
197353
+
197354
+ } // namespace duckdb
197355
+
197356
+
197294
197357
  namespace duckdb {
197295
197358
 
197296
197359
  UpdateBinder::UpdateBinder(Binder &binder, ClientContext &context) : ExpressionBinder(binder, context) {
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 "799db99fc3"
15
- #define DUCKDB_VERSION "v0.6.1-dev131"
14
+ #define DUCKDB_SOURCE_ID "dd5dcd5722"
15
+ #define DUCKDB_VERSION "v0.6.1-dev140"
16
16
  //===----------------------------------------------------------------------===//
17
17
  // DuckDB
18
18
  //
@@ -133,7 +133,6 @@ public:
133
133
  std::unique_ptr<duckdb::Connection> connection;
134
134
  Database *database_ref;
135
135
  std::unordered_map<std::string, duckdb_node_udf_function_t> udfs;
136
- std::unordered_map<std::string, std::vector<std::pair<uint64_t, uint64_t>>> buffers;
137
136
  std::unordered_map<std::string, Napi::Reference<Napi::Array>> array_references;
138
137
  };
139
138