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 +1 -1
- package/src/connection.cpp +100 -99
- package/src/duckdb.cpp +1528 -810
- package/src/duckdb.hpp +92 -35
- package/src/duckdb_node.hpp +0 -1
- package/src/parquet-amalgamation.cpp +31961 -31951
- package/test/arrow.test.js +36 -45
package/package.json
CHANGED
package/src/connection.cpp
CHANGED
|
@@ -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
|