duckdb 0.6.1-dev86.0 → 0.6.2-dev6.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-dev86.0",
5
+ "version": "0.6.2-dev6.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