66#include " include/node_query_result.h"
77#include " include/node_util.h"
88#include " main/lbug.h"
9+ #include " storage/table/arrow_table_support.h"
10+
11+ namespace {
12+
13+ template <typename T>
14+ T* GetPointerArgument (const Napi::Value& value, const char * name) {
15+ if (value.IsBigInt ()) {
16+ bool lossless = false ;
17+ auto address = value.As <Napi::BigInt>().Uint64Value (&lossless);
18+ if (!lossless || address == 0 ) {
19+ throw std::runtime_error (std::string (name) + " must be a non-zero pointer BigInt." );
20+ }
21+ return reinterpret_cast <T*>(static_cast <uintptr_t >(address));
22+ }
23+ if (value.IsExternal ()) {
24+ return value.As <Napi::External<T>>().Data ();
25+ }
26+ throw std::runtime_error (std::string (name) + " must be a pointer BigInt or N-API External." );
27+ }
28+
29+ ArrowSchemaWrapper TakeArrowSchema (ArrowSchema* schema) {
30+ ArrowSchemaWrapper wrapper;
31+ static_cast <ArrowSchema&>(wrapper) = *schema;
32+ schema->release = nullptr ;
33+ return wrapper;
34+ }
35+
36+ ArrowArrayWrapper TakeArrowArray (ArrowArray* array) {
37+ ArrowArrayWrapper wrapper;
38+ static_cast <ArrowArray&>(wrapper) = *array;
39+ array->release = nullptr ;
40+ return wrapper;
41+ }
42+
43+ std::vector<ArrowArrayWrapper> TakeArrowArrays (const Napi::Value& value, uint64_t numArrays) {
44+ std::vector<ArrowArrayWrapper> wrappers;
45+ if (value.IsArray ()) {
46+ auto arrayPointers = value.As <Napi::Array>();
47+ wrappers.reserve (arrayPointers.Length ());
48+ for (auto i = 0u ; i < arrayPointers.Length (); ++i) {
49+ wrappers.push_back (TakeArrowArray (
50+ GetPointerArgument<ArrowArray>(arrayPointers.Get (i), " ArrowArray" )));
51+ }
52+ return wrappers;
53+ }
54+ auto * arrays = GetPointerArgument<ArrowArray>(value, " arrays" );
55+ wrappers.reserve (numArrays);
56+ for (auto i = 0u ; i < numArrays; ++i) {
57+ wrappers.push_back (TakeArrowArray (&arrays[i]));
58+ }
59+ return wrappers;
60+ }
61+
62+ void AdoptArrowQueryResult (Napi::Env env, NodeQueryResult* nodeQueryResult,
63+ std::unique_ptr<QueryResult> result, std::shared_ptr<Connection> connection,
64+ std::shared_ptr<Database> database) {
65+ if (result == nullptr ) {
66+ throw std::runtime_error (" Arrow table registration did not return a query result." );
67+ }
68+ if (!result->isSuccess ()) {
69+ Napi::Error::New (env, result->getErrorMessage ()).ThrowAsJavaScriptException ();
70+ return ;
71+ }
72+ nodeQueryResult->AdoptQueryResult (std::move (result), std::move (connection), std::move (database));
73+ }
74+
75+ } // namespace
976
1077Napi::Object NodeConnection::Init (Napi::Env env, Napi::Object exports) {
1178 Napi::HandleScope scope (env);
@@ -17,6 +84,9 @@ Napi::Object NodeConnection::Init(Napi::Env env, Napi::Object exports) {
1784 InstanceMethod (" queryAsync" , &NodeConnection::QueryAsync),
1885 InstanceMethod (" executeSync" , &NodeConnection::ExecuteSync),
1986 InstanceMethod (" querySync" , &NodeConnection::QuerySync),
87+ InstanceMethod (" createArrowTableSync" , &NodeConnection::CreateArrowTableSync),
88+ InstanceMethod (" createArrowRelTableSync" , &NodeConnection::CreateArrowRelTableSync),
89+ InstanceMethod (" dropArrowTableSync" , &NodeConnection::DropArrowTableSync),
2090 InstanceMethod (" setMaxNumThreadForExec" , &NodeConnection::SetMaxNumThreadForExec),
2191 InstanceMethod (" setQueryTimeout" , &NodeConnection::SetQueryTimeout),
2292 InstanceMethod (" close" , &NodeConnection::Close)});
@@ -155,3 +225,55 @@ Napi::Value NodeConnection::QueryAsync(const Napi::CallbackInfo& info) {
155225 asyncWorker->Queue ();
156226 return info.Env ().Undefined ();
157227}
228+
229+ Napi::Value NodeConnection::CreateArrowTableSync (const Napi::CallbackInfo& info) {
230+ Napi::Env env = info.Env ();
231+ Napi::HandleScope scope (env);
232+ auto tableName = info[0 ].As <Napi::String>().Utf8Value ();
233+ auto * schema = GetPointerArgument<ArrowSchema>(info[1 ], " schema" );
234+ auto numArrays = info[3 ].As <Napi::Number>().Int64Value ();
235+ auto nodeQueryResult = Napi::ObjectWrap<NodeQueryResult>::Unwrap (info[4 ].As <Napi::Object>());
236+ try {
237+ auto result = lbug::ArrowTableSupport::createViewFromArrowTable (*connection, tableName,
238+ TakeArrowSchema (schema), TakeArrowArrays (info[2 ], numArrays));
239+ AdoptArrowQueryResult (
240+ env, nodeQueryResult, std::move (result.queryResult ), connection, database);
241+ } catch (const std::exception& exc) {
242+ Napi::Error::New (env, std::string (exc.what ())).ThrowAsJavaScriptException ();
243+ }
244+ return env.Undefined ();
245+ }
246+
247+ Napi::Value NodeConnection::CreateArrowRelTableSync (const Napi::CallbackInfo& info) {
248+ Napi::Env env = info.Env ();
249+ Napi::HandleScope scope (env);
250+ auto tableName = info[0 ].As <Napi::String>().Utf8Value ();
251+ auto srcTableName = info[1 ].As <Napi::String>().Utf8Value ();
252+ auto dstTableName = info[2 ].As <Napi::String>().Utf8Value ();
253+ auto * schema = GetPointerArgument<ArrowSchema>(info[3 ], " schema" );
254+ auto numArrays = info[5 ].As <Napi::Number>().Int64Value ();
255+ auto nodeQueryResult = Napi::ObjectWrap<NodeQueryResult>::Unwrap (info[6 ].As <Napi::Object>());
256+ try {
257+ auto result = lbug::ArrowTableSupport::createRelTableFromArrowTable (*connection, tableName,
258+ srcTableName, dstTableName, TakeArrowSchema (schema), TakeArrowArrays (info[4 ], numArrays));
259+ AdoptArrowQueryResult (
260+ env, nodeQueryResult, std::move (result.queryResult ), connection, database);
261+ } catch (const std::exception& exc) {
262+ Napi::Error::New (env, std::string (exc.what ())).ThrowAsJavaScriptException ();
263+ }
264+ return env.Undefined ();
265+ }
266+
267+ Napi::Value NodeConnection::DropArrowTableSync (const Napi::CallbackInfo& info) {
268+ Napi::Env env = info.Env ();
269+ Napi::HandleScope scope (env);
270+ auto tableName = info[0 ].As <Napi::String>().Utf8Value ();
271+ auto nodeQueryResult = Napi::ObjectWrap<NodeQueryResult>::Unwrap (info[1 ].As <Napi::Object>());
272+ try {
273+ auto result = lbug::ArrowTableSupport::unregisterArrowTable (*connection, tableName);
274+ AdoptArrowQueryResult (env, nodeQueryResult, std::move (result), connection, database);
275+ } catch (const std::exception& exc) {
276+ Napi::Error::New (env, std::string (exc.what ())).ThrowAsJavaScriptException ();
277+ }
278+ return env.Undefined ();
279+ }
0 commit comments