Skip to content

Commit 561ad92

Browse files
authored
Merge pull request #154 from pdet/arrow_ipc_2
Creating Arrow Table Function and View with the Relational API
2 parents cdd22fc + eb26aae commit 561ad92

File tree

1 file changed

+42
-15
lines changed

1 file changed

+42
-15
lines changed

src/connection.cpp

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
#include "duckdb/parser/parser.hpp"
55
#include "duckdb/parser/parsed_data/drop_info.hpp"
66
#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+
711
#include <iostream>
812
#include <thread>
913

@@ -451,6 +455,27 @@ Napi::Value Connection::Exec(const Napi::CallbackInfo &info) {
451455
return Value();
452456
}
453457

458+
struct CreateArrowViewTask : public Task {
459+
CreateArrowViewTask(Connection &connection, duckdb::vector<duckdb::Value>& parameters, std::string &view_name)
460+
: Task(connection), parameters(parameters), view_name(view_name) {
461+
}
462+
463+
void DoWork() override {
464+
auto &connection = Get<Connection>();
465+
auto &con = *connection.connection;
466+
// Now we create a table function relation
467+
auto table_function_relation = duckdb::make_shared_ptr<duckdb::TableFunctionRelation>(con.context,"scan_arrow_ipc",parameters);
468+
// Creates a relation for a temporary view that does replace
469+
auto view_relation = table_function_relation->CreateView(view_name,true,true);
470+
471+
view_relation->Execute();
472+
473+
}
474+
475+
duckdb::vector<duckdb::Value> parameters;
476+
std::string view_name;
477+
};
478+
454479
// Register Arrow IPC buffers for scanning from DuckDB
455480
Napi::Value Connection::RegisterBuffer(const Napi::CallbackInfo &info) {
456481
auto env = info.Env();
@@ -475,9 +500,10 @@ Napi::Value Connection::RegisterBuffer(const Napi::CallbackInfo &info) {
475500
}
476501

477502
array_references[name] = Napi::Persistent(array);
503+
auto &db = *connection->context->db;
478504

479-
std::string arrow_scan_function = "scan_arrow_ipc([";
480-
505+
vector<duckdb::Value> values;
506+
481507
for (uint64_t ipc_idx = 0; ipc_idx < array.Length(); ipc_idx++) {
482508
Napi::Value v = array[ipc_idx];
483509
if (!v.IsObject()) {
@@ -486,19 +512,20 @@ Napi::Value Connection::RegisterBuffer(const Napi::CallbackInfo &info) {
486512
Napi::Uint8Array arr = v.As<Napi::Uint8Array>();
487513
auto raw_ptr = reinterpret_cast<uint64_t>(arr.ArrayBuffer().Data());
488514
auto length = (uint64_t)arr.ElementLength();
489-
490-
arrow_scan_function += "{'ptr': " + std::to_string(raw_ptr) + "::UBIGINT, 'size': " + std::to_string(length) + "::UBIGINT},";
491-
}
492-
arrow_scan_function += "])";
493-
494-
std::string final_query = "CREATE OR REPLACE TEMPORARY VIEW " + name + " AS SELECT * FROM " + arrow_scan_function;
495-
496-
Napi::Function callback;
497-
if (info.Length() > 3 && info[3].IsFunction()) {
498-
callback = info[3].As<Napi::Function>();
499-
}
500-
501-
database_ref->Schedule(info.Env(), duckdb::make_uniq<ExecTask>(*this, final_query, callback));
515+
duckdb::child_list_t<duckdb::Value> buffer_values;
516+
// This is a little bit evil, but allows us to support both libraries in between 1.2 and 1.3
517+
if (db.ExtensionIsLoaded("nanoarrow")){
518+
buffer_values.push_back({"ptr", duckdb::Value::POINTER(raw_ptr)});
519+
} else {
520+
buffer_values.push_back({"ptr", duckdb::Value::UBIGINT(raw_ptr)});
521+
}
522+
buffer_values.push_back({"size", duckdb::Value::UBIGINT(length)});
523+
values.push_back(duckdb::Value::STRUCT(buffer_values));
524+
}
525+
duckdb::vector<duckdb::Value> list_value;
526+
list_value.push_back(duckdb::Value::LIST(values));
527+
528+
database_ref->Schedule(info.Env(), duckdb::make_uniq<CreateArrowViewTask>(*this, list_value, name));
502529

503530
return Value();
504531
}

0 commit comments

Comments
 (0)