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.
- package/package.json +1 -1
- package/src/connection.cpp +73 -24
package/package.json
CHANGED
package/src/connection.cpp
CHANGED
@@ -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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
395
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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<
|
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
|
-
|
576
|
+
duckdb::make_uniq<ExecTaskWithCallback>(*this, final_query, callback, cpp_callback));
|
528
577
|
|
529
578
|
return Value();
|
530
579
|
}
|