duckdb 1.2.0 → 1.2.1-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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/connection.cpp +73 -24
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": "1.2.0",
5
+ "version": "1.2.1-dev6.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
@@ -4,6 +4,10 @@
4
4
  #include "duckdb/parser/parser.hpp"
5
5
  #include "duckdb/parser/parsed_data/drop_info.hpp"
6
6
  #include "duckdb/parser/expression/cast_expression.hpp"
7
+ #include "duckdb/common/types/value.hpp"
8
+ #include "duckdb/main/relation/table_function_relation.hpp"
9
+
10
+
7
11
  #include <iostream>
8
12
  #include <thread>
9
13
 
@@ -13,12 +17,12 @@ Napi::FunctionReference Connection::Init(Napi::Env env, Napi::Object exports) {
13
17
  Napi::HandleScope scope(env);
14
18
 
15
19
  Napi::Function t = DefineClass(
16
- env, "Connection",
17
- {InstanceMethod("prepare", &Connection::Prepare), InstanceMethod("exec", &Connection::Exec),
18
- InstanceMethod("register_udf_bulk", &Connection::RegisterUdf),
19
- InstanceMethod("register_buffer", &Connection::RegisterBuffer),
20
- InstanceMethod("unregister_udf", &Connection::UnregisterUdf), InstanceMethod("close", &Connection::Close),
21
- InstanceMethod("unregister_buffer", &Connection::UnRegisterBuffer)});
20
+ env, "Connection",
21
+ {InstanceMethod("prepare", &Connection::Prepare), InstanceMethod("exec", &Connection::Exec),
22
+ InstanceMethod("register_udf_bulk", &Connection::RegisterUdf),
23
+ InstanceMethod("register_buffer", &Connection::RegisterBuffer),
24
+ InstanceMethod("unregister_udf", &Connection::UnregisterUdf), InstanceMethod("close", &Connection::Close),
25
+ InstanceMethod("unregister_buffer", &Connection::UnRegisterBuffer)});
22
26
 
23
27
  exports.Set("Connection", t);
24
28
 
@@ -230,14 +234,14 @@ void DuckDBNodeUDFLauncher(Napi::Env env, Napi::Function jsudf, std::nullptr_t *
230
234
 
231
235
  struct RegisterUdfTask : public Task {
232
236
  RegisterUdfTask(Connection &connection, std::string name, std::string return_type_name, Napi::Function callback)
233
- : Task(connection, callback), name(std::move(name)), return_type_name(std::move(return_type_name)) {
237
+ : Task(connection, callback), name(std::move(name)), return_type_name(std::move(return_type_name)) {
234
238
  }
235
239
 
236
240
  void DoWork() override {
237
241
  auto &connection = Get<Connection>();
238
242
  auto &udf_ptr = connection.udfs[name];
239
243
  duckdb::scalar_function_t udf_function = [&udf_ptr](duckdb::DataChunk &args, duckdb::ExpressionState &state,
240
- duckdb::Vector &result) -> void {
244
+ duckdb::Vector &result) -> void {
241
245
  // here we can do only DuckDB stuff because we do not have a functioning env
242
246
 
243
247
  // Flatten all args to simplify udfs
@@ -267,7 +271,7 @@ struct RegisterUdfTask : public Task {
267
271
  auto return_type = cast.cast_type;
268
272
 
269
273
  connection.connection->CreateVectorizedFunction(name, vector<duckdb::LogicalType> {}, return_type, udf_function,
270
- duckdb::LogicalType::ANY);
274
+ duckdb::LogicalType::ANY);
271
275
  }
272
276
  std::string name;
273
277
  std::string return_type_name;
@@ -292,7 +296,7 @@ Napi::Value Connection::RegisterUdf(const Napi::CallbackInfo &info) {
292
296
  }
293
297
 
294
298
  auto udf = duckdb_node_udf_function_t::New(env, udf_callback, "duckdb_node_udf" + name, 0, 1, nullptr,
295
- [](Napi::Env, void *, std::nullptr_t *ctx) {});
299
+ [](Napi::Env, void *, std::nullptr_t *ctx) {});
296
300
 
297
301
  // we have to unref the udf because otherwise there is a circular ref with the connection somehow(?)
298
302
  // this took far too long to figure out
@@ -300,14 +304,14 @@ Napi::Value Connection::RegisterUdf(const Napi::CallbackInfo &info) {
300
304
  udfs[name] = udf;
301
305
 
302
306
  database_ref->Schedule(info.Env(),
303
- duckdb::make_uniq<RegisterUdfTask>(*this, name, return_type_name, completion_callback));
307
+ duckdb::make_uniq<RegisterUdfTask>(*this, name, return_type_name, completion_callback));
304
308
 
305
309
  return Value();
306
310
  }
307
311
 
308
312
  struct UnregisterUdfTask : public Task {
309
313
  UnregisterUdfTask(Connection &connection, std::string name, Napi::Function callback)
310
- : Task(connection, callback), name(std::move(name)) {
314
+ : Task(connection, callback), name(std::move(name)) {
311
315
  }
312
316
 
313
317
  void DoWork() override {
@@ -350,7 +354,7 @@ Napi::Value Connection::UnregisterUdf(const Napi::CallbackInfo &info) {
350
354
 
351
355
  struct ExecTask : public Task {
352
356
  ExecTask(Connection &connection, std::string sql, Napi::Function callback)
353
- : Task(connection, callback), sql(std::move(sql)) {
357
+ : Task(connection, callback), sql(std::move(sql)) {
354
358
  }
355
359
 
356
360
  void DoWork() override {
@@ -391,8 +395,8 @@ struct ExecTask : public Task {
391
395
 
392
396
  struct ExecTaskWithCallback : public ExecTask {
393
397
  ExecTaskWithCallback(Connection &connection, std::string sql, Napi::Function js_callback,
394
- std::function<void(void)> cpp_callback)
395
- : ExecTask(connection, sql, js_callback), cpp_callback(cpp_callback) {
398
+ std::function<void(void)> cpp_callback)
399
+ : ExecTask(connection, sql, js_callback), cpp_callback(cpp_callback) {
396
400
  }
397
401
 
398
402
  void Callback() override {
@@ -451,6 +455,44 @@ Napi::Value Connection::Exec(const Napi::CallbackInfo &info) {
451
455
  return Value();
452
456
  }
453
457
 
458
+ struct CreateArrowViewTask : public Task {
459
+ CreateArrowViewTask(Connection &connection, duckdb::vector<duckdb::Value>& parameters, std::string &view_name, Napi::Function callback)
460
+ : Task(connection, callback), parameters(parameters), view_name(view_name) {
461
+ }
462
+
463
+ void DoWork() override {
464
+ auto &connection = Get<Connection>();
465
+ success = true;
466
+ try {
467
+ auto &con = *connection.connection;
468
+ // Now we create a table function relation
469
+ auto table_function_relation = duckdb::make_shared_ptr<duckdb::TableFunctionRelation>(con.context,"scan_arrow_ipc",parameters);
470
+ // Creates a relation for a temporary view that does replace
471
+ auto view_relation = table_function_relation->CreateView(view_name,true,true);
472
+ auto res = view_relation->Execute();
473
+ if (res->HasError()) {
474
+ success = false;
475
+ error = res->GetErrorObject();
476
+ }
477
+ } catch (duckdb::Exception &e) {
478
+ success = false;
479
+ error = duckdb::ErrorData(e);
480
+ return;
481
+ }
482
+ }
483
+
484
+ void Callback() override {
485
+ auto env = object.Env();
486
+ Napi::HandleScope scope(env);
487
+ callback.Value().MakeCallback(object.Value(), {success ? env.Null() : Utils::CreateError(env, error)});
488
+ };
489
+
490
+ duckdb::vector<duckdb::Value> parameters;
491
+ std::string view_name;
492
+ bool success;
493
+ duckdb::ErrorData error;
494
+ };
495
+
454
496
  // Register Arrow IPC buffers for scanning from DuckDB
455
497
  Napi::Value Connection::RegisterBuffer(const Napi::CallbackInfo &info) {
456
498
  auto env = info.Env();
@@ -475,9 +517,10 @@ Napi::Value Connection::RegisterBuffer(const Napi::CallbackInfo &info) {
475
517
  }
476
518
 
477
519
  array_references[name] = Napi::Persistent(array);
520
+ auto &db = *connection->context->db;
478
521
 
479
- std::string arrow_scan_function = "scan_arrow_ipc([";
480
-
522
+ vector<duckdb::Value> values;
523
+
481
524
  for (uint64_t ipc_idx = 0; ipc_idx < array.Length(); ipc_idx++) {
482
525
  Napi::Value v = array[ipc_idx];
483
526
  if (!v.IsObject()) {
@@ -486,19 +529,25 @@ Napi::Value Connection::RegisterBuffer(const Napi::CallbackInfo &info) {
486
529
  Napi::Uint8Array arr = v.As<Napi::Uint8Array>();
487
530
  auto raw_ptr = reinterpret_cast<uint64_t>(arr.ArrayBuffer().Data());
488
531
  auto length = (uint64_t)arr.ElementLength();
489
-
490
- arrow_scan_function += "{'ptr': " + std::to_string(raw_ptr) + "::UBIGINT, 'size': " + std::to_string(length) + "::UBIGINT},";
532
+ duckdb::child_list_t<duckdb::Value> buffer_values;
533
+ // This is a little bit evil, but allows us to support both libraries in between 1.2 and 1.3
534
+ if (db.ExtensionIsLoaded("nanoarrow")){
535
+ buffer_values.push_back({"ptr", duckdb::Value::POINTER(raw_ptr)});
536
+ } else {
537
+ buffer_values.push_back({"ptr", duckdb::Value::UBIGINT(raw_ptr)});
538
+ }
539
+ buffer_values.push_back({"size", duckdb::Value::UBIGINT(length)});
540
+ values.push_back(duckdb::Value::STRUCT(buffer_values));
491
541
  }
492
- arrow_scan_function += "])";
493
-
494
- std::string final_query = "CREATE OR REPLACE TEMPORARY VIEW " + name + " AS SELECT * FROM " + arrow_scan_function;
542
+ duckdb::vector<duckdb::Value> list_value;
543
+ list_value.push_back(duckdb::Value::LIST(values));
495
544
 
496
545
  Napi::Function callback;
497
546
  if (info.Length() > 3 && info[3].IsFunction()) {
498
547
  callback = info[3].As<Napi::Function>();
499
548
  }
500
549
 
501
- database_ref->Schedule(info.Env(), duckdb::make_uniq<ExecTask>(*this, final_query, callback));
550
+ database_ref->Schedule(info.Env(), duckdb::make_uniq<CreateArrowViewTask>(*this, list_value, name, callback));
502
551
 
503
552
  return Value();
504
553
  }
@@ -524,7 +573,7 @@ Napi::Value Connection::UnRegisterBuffer(const Napi::CallbackInfo &info) {
524
573
  };
525
574
 
526
575
  database_ref->Schedule(info.Env(),
527
- duckdb::make_uniq<ExecTaskWithCallback>(*this, final_query, callback, cpp_callback));
576
+ duckdb::make_uniq<ExecTaskWithCallback>(*this, final_query, callback, cpp_callback));
528
577
 
529
578
  return Value();
530
579
  }