Skip to content

Commit 8054b49

Browse files
authored
Merge pull request #267 from duckdb/jray/scalar-functions
core bindings for scalar functions
2 parents 1a63b4e + 1662ade commit 8054b49

File tree

3 files changed

+282
-7
lines changed

3 files changed

+282
-7
lines changed

bindings/pkgs/@duckdb/node-bindings/duckdb.d.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ export interface TimestampParts {
170170
time: TimeParts;
171171
}
172172

173+
export interface FunctionInfo {
174+
__duckdb_type: 'duckdb_function_info';
175+
}
176+
173177
export interface Vector {
174178
__duckdb_type: 'duckdb_vector';
175179
}
@@ -228,6 +232,10 @@ export interface Result {
228232
__duckdb_type: 'duckdb_result';
229233
}
230234

235+
export interface ScalarFunction {
236+
__duckdb_type: 'duckdb_scalar_function';
237+
}
238+
231239
// export interface SelectionVector {
232240
// __duckdb_type: 'duckdb_selection_vector';
233241
// }
@@ -248,6 +256,7 @@ export interface ExtractedStatementsAndCount {
248256
statement_count: number;
249257
}
250258

259+
export type ScalarFunctionMainFunction = (info: FunctionInfo, input: DataChunk, output: Vector) => void;
251260

252261
// Functions
253262

@@ -1013,23 +1022,39 @@ export function validity_set_row_invalid(validity: Uint8Array, row_index: number
10131022
export function validity_set_row_valid(validity: Uint8Array, row_index: number): void;
10141023

10151024
// DUCKDB_C_API duckdb_scalar_function duckdb_create_scalar_function();
1025+
export function create_scalar_function(): ScalarFunction;
1026+
10161027
// DUCKDB_C_API void duckdb_destroy_scalar_function(duckdb_scalar_function *scalar_function);
1028+
export function destroy_scalar_function_sync(scalar_function: ScalarFunction): void;
1029+
10171030
// DUCKDB_C_API void duckdb_scalar_function_set_name(duckdb_scalar_function scalar_function, const char *name);
1031+
export function scalar_function_set_name(scalar_function: ScalarFunction, name: string): void;
1032+
10181033
// DUCKDB_C_API void duckdb_scalar_function_set_varargs(duckdb_scalar_function scalar_function, duckdb_logical_type type);
10191034
// DUCKDB_C_API void duckdb_scalar_function_set_special_handling(duckdb_scalar_function scalar_function);
10201035
// DUCKDB_C_API void duckdb_scalar_function_set_volatile(duckdb_scalar_function scalar_function);
10211036
// DUCKDB_C_API void duckdb_scalar_function_add_parameter(duckdb_scalar_function scalar_function, duckdb_logical_type type);
1037+
10221038
// DUCKDB_C_API void duckdb_scalar_function_set_return_type(duckdb_scalar_function scalar_function, duckdb_logical_type type);
1039+
export function scalar_function_set_return_type(scalar_function: ScalarFunction, logical_type: LogicalType): void;
1040+
10231041
// DUCKDB_C_API void duckdb_scalar_function_set_extra_info(duckdb_scalar_function scalar_function, void *extra_info, duckdb_delete_callback_t destroy);
10241042
// DUCKDB_C_API void duckdb_scalar_function_set_bind(duckdb_scalar_function scalar_function, duckdb_scalar_function_bind_t bind);
10251043
// DUCKDB_C_API void duckdb_scalar_function_set_bind_data(duckdb_bind_info info, void *bind_data, duckdb_delete_callback_t destroy);
10261044
// DUCKDB_C_API void duckdb_scalar_function_bind_set_error(duckdb_bind_info info, const char *error);
1045+
10271046
// DUCKDB_C_API void duckdb_scalar_function_set_function(duckdb_scalar_function scalar_function, duckdb_scalar_function_t function);
1047+
export function scalar_function_set_function(scalar_function: ScalarFunction, func: ScalarFunctionMainFunction): void;
1048+
10281049
// DUCKDB_C_API duckdb_state duckdb_register_scalar_function(duckdb_connection con, duckdb_scalar_function scalar_function);
1050+
export function register_scalar_function(connection: Connection, scalar_function: ScalarFunction): void;
1051+
10291052
// DUCKDB_C_API void *duckdb_scalar_function_get_extra_info(duckdb_function_info info);
10301053
// DUCKDB_C_API void *duckdb_scalar_function_get_bind_data(duckdb_function_info info);
10311054
// DUCKDB_C_API void duckdb_scalar_function_get_client_context(duckdb_bind_info info, duckdb_client_context *out_context);
1055+
10321056
// DUCKDB_C_API void duckdb_scalar_function_set_error(duckdb_function_info info, const char *error);
1057+
export function scalar_function_set_error(function_info: FunctionInfo, error: string): void;
10331058

10341059
// DUCKDB_C_API duckdb_scalar_function_set duckdb_create_scalar_function_set(const char *name);
10351060
// DUCKDB_C_API void duckdb_destroy_scalar_function_set(duckdb_scalar_function_set *scalar_function_set);

bindings/src/duckdb_node_bindings.cpp

Lines changed: 208 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
#define NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
44
#include "napi.h"
55

6+
#include <condition_variable>
7+
#include <cstddef>
8+
#include <mutex>
69
#include <optional>
710
#include <string>
811
#include <vector>
@@ -462,6 +465,10 @@ Napi::External<_duckdb_data_chunk> CreateExternalForDataChunk(Napi::Env env, duc
462465
return CreateExternal<_duckdb_data_chunk>(env, DataChunkTypeTag, chunk, FinalizeDataChunk);
463466
}
464467

468+
Napi::External<_duckdb_data_chunk> CreateExternalForDataChunkWithoutFinalizer(Napi::Env env, duckdb_data_chunk chunk) {
469+
return CreateExternalWithoutFinalizer<_duckdb_data_chunk>(env, DataChunkTypeTag, chunk);
470+
}
471+
465472
duckdb_data_chunk GetDataChunkFromExternal(Napi::Env env, Napi::Value value) {
466473
return GetDataFromExternal<_duckdb_data_chunk>(env, DataChunkTypeTag, value, "Invalid data chunk argument");
467474
}
@@ -485,6 +492,21 @@ duckdb_extracted_statements GetExtractedStatementsFromExternal(Napi::Env env, Na
485492
return GetDataFromExternal<_duckdb_extracted_statements>(env, ExtractedStatementsTypeTag, value, "Invalid extracted statements argument");
486493
}
487494

495+
static const napi_type_tag FunctionInfoTypeTag = {
496+
0xB0E6739D698048EA, 0x9E79734E3E137AC3
497+
};
498+
499+
Napi::External<_duckdb_function_info> CreateExternalForFunctionInfoWithoutFinalizer(Napi::Env env, duckdb_function_info function_info) {
500+
// FunctionInfo objects are never explicitly created; they are passed in to function callbacks.
501+
return CreateExternalWithoutFinalizer<_duckdb_function_info>(env, FunctionInfoTypeTag, function_info);
502+
}
503+
504+
duckdb_function_info GetFunctionInfoFromExternal(Napi::Env env, Napi::Value value) {
505+
return GetDataFromExternal<_duckdb_function_info>(env, FunctionInfoTypeTag, value, "Invalid function info argument");
506+
}
507+
508+
509+
488510
static const napi_type_tag InstanceCacheTypeTag = {
489511
0x2F3346E30FB5457C, 0xB9201EE5112EEF9F
490512
};
@@ -592,6 +614,38 @@ duckdb_result *GetResultFromExternal(Napi::Env env, Napi::Value value) {
592614
return GetDataFromExternal<duckdb_result>(env, ResultTypeTag, value, "Invalid result argument");
593615
}
594616

617+
static const napi_type_tag ScalarFunctionTypeTag = {
618+
0x95D48B7051D14994, 0x9F883D7DF5DEA86D
619+
};
620+
621+
typedef struct {
622+
duckdb_scalar_function scalar_function;
623+
} duckdb_scalar_function_holder;
624+
625+
duckdb_scalar_function_holder *CreateScalarFunctionHolder(duckdb_scalar_function scalar_function) {
626+
auto scalar_function_holder_ptr = reinterpret_cast<duckdb_scalar_function_holder*>(duckdb_malloc(sizeof(duckdb_scalar_function_holder)));
627+
scalar_function_holder_ptr->scalar_function = scalar_function;
628+
return scalar_function_holder_ptr;
629+
}
630+
631+
void FinalizeScalarFunctionHolder(Napi::BasicEnv, duckdb_scalar_function_holder *scalar_function_holder_ptr) {
632+
// duckdb_destroy_scalar_function is a no-op if already closed
633+
duckdb_destroy_scalar_function(&scalar_function_holder_ptr->scalar_function);
634+
duckdb_free(scalar_function_holder_ptr);
635+
}
636+
637+
Napi::External<duckdb_scalar_function_holder> CreateExternalForScalarFunction(Napi::Env env, duckdb_scalar_function scalar_function) {
638+
return CreateExternal<duckdb_scalar_function_holder>(env, ScalarFunctionTypeTag, CreateScalarFunctionHolder(scalar_function), FinalizeScalarFunctionHolder);
639+
}
640+
641+
duckdb_scalar_function_holder *GetScalarFunctionHolderFromExternal(Napi::Env env, Napi::Value value) {
642+
return GetDataFromExternal<duckdb_scalar_function_holder>(env, ScalarFunctionTypeTag, value, "Invalid scalar function argument");
643+
}
644+
645+
duckdb_scalar_function GetScalarFunctionFromExternal(Napi::Env env, Napi::Value value) {
646+
return GetScalarFunctionHolderFromExternal(env, value)->scalar_function;
647+
}
648+
595649
static const napi_type_tag ValueTypeTag = {
596650
0xC60F36613BF14E93, 0xBAA92848936FAA25
597651
};
@@ -615,7 +669,7 @@ static const napi_type_tag VectorTypeTag = {
615669
0x9FE56DE8E3124D07, 0x9ABF31145EDE1C9E
616670
};
617671

618-
Napi::External<_duckdb_vector> CreateExternalForVector(Napi::Env env, duckdb_vector vector) {
672+
Napi::External<_duckdb_vector> CreateExternalForVectorWithoutFinalizer(Napi::Env env, duckdb_vector vector) {
619673
// Vectors live as long as their containing data chunk; they cannot be explicitly destroyed.
620674
return CreateExternalWithoutFinalizer<_duckdb_vector>(env, VectorTypeTag, vector);
621675
}
@@ -624,6 +678,78 @@ duckdb_vector GetVectorFromExternal(Napi::Env env, Napi::Value value) {
624678
return GetDataFromExternal<_duckdb_vector>(env, VectorTypeTag, value, "Invalid vector argument");
625679
}
626680

681+
// Scalar functions
682+
683+
using ScalarFunctionMainContext = std::nullptr_t;
684+
struct ScalarFunctionMainData {
685+
duckdb_function_info info;
686+
duckdb_data_chunk input;
687+
duckdb_vector output;
688+
std::condition_variable *cv;
689+
std::mutex *cv_mutex;
690+
bool done;
691+
};
692+
void ScalarFunctionMainCallback(Napi::Env env, Napi::Function callback, ScalarFunctionMainContext *context, ScalarFunctionMainData *data) {
693+
if (env != nullptr) {
694+
if (callback != nullptr) {
695+
callback.Call(
696+
env.Undefined(),
697+
{
698+
CreateExternalForFunctionInfoWithoutFinalizer(env, data->info),
699+
CreateExternalForDataChunkWithoutFinalizer(env, data->input),
700+
CreateExternalForVectorWithoutFinalizer(env, data->output)
701+
}
702+
);
703+
}
704+
}
705+
{
706+
std::lock_guard lk(*data->cv_mutex);
707+
data->done = true;
708+
}
709+
data->cv->notify_one();
710+
}
711+
using ScalarFunctionMainTSFN = Napi::TypedThreadSafeFunction<ScalarFunctionMainContext, ScalarFunctionMainData, ScalarFunctionMainCallback>;
712+
713+
struct ScalarFunctionMainExtraInfo {
714+
ScalarFunctionMainTSFN tsfn;
715+
// TODO: user extra info
716+
};
717+
718+
ScalarFunctionMainExtraInfo *CreateScalarFunctionMainExtraInfo(Napi::Env env, Napi::Function func) {
719+
auto extra_info = reinterpret_cast<ScalarFunctionMainExtraInfo*>(duckdb_malloc(sizeof(ScalarFunctionMainExtraInfo)));
720+
extra_info->tsfn = ScalarFunctionMainTSFN::New(env, func, "ScalarFunctionMain", 0, 1);
721+
return extra_info;
722+
}
723+
724+
void DeleteScalarFunctionMainExtraInfo(ScalarFunctionMainExtraInfo *extra_info) {
725+
extra_info->tsfn.Release();
726+
duckdb_free(extra_info);
727+
}
728+
729+
void ScalarFunctionMainFunction(duckdb_function_info info, duckdb_data_chunk input, duckdb_vector output) {
730+
auto extra_info = reinterpret_cast<ScalarFunctionMainExtraInfo*>(duckdb_scalar_function_get_extra_info(info));
731+
auto data = reinterpret_cast<ScalarFunctionMainData*>(duckdb_malloc(sizeof(ScalarFunctionMainData)));
732+
data->info = info;
733+
data->input = input;
734+
data->output = output;
735+
data->cv = new std::condition_variable;
736+
data->cv_mutex = new std::mutex;
737+
data->done = false;
738+
// The "blocking" part of this call only waits for queue space, not for the JS function call to complete.
739+
// Since we specify no limit to the queue space, it in fact never blocks.
740+
auto status = extra_info->tsfn.BlockingCall(data);
741+
if (status == napi_ok) {
742+
// Wait for the JS function call to complete.
743+
std::unique_lock<std::mutex> lk(*data->cv_mutex);
744+
data->cv->wait(lk, [&]{ return data->done; });
745+
} else {
746+
duckdb_scalar_function_set_error(info, "BlockingCall returned not ok");
747+
}
748+
delete data->cv;
749+
delete data->cv_mutex;
750+
duckdb_free(data);
751+
}
752+
627753
// Promise workers
628754

629755
class PromiseWorker : public Napi::AsyncWorker {
@@ -1421,6 +1547,14 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
14211547
InstanceMethod("validity_set_row_invalid", &DuckDBNodeAddon::validity_set_row_invalid),
14221548
InstanceMethod("validity_set_row_valid", &DuckDBNodeAddon::validity_set_row_valid),
14231549

1550+
InstanceMethod("create_scalar_function", &DuckDBNodeAddon::create_scalar_function),
1551+
InstanceMethod("destroy_scalar_function_sync", &DuckDBNodeAddon::destroy_scalar_function_sync),
1552+
InstanceMethod("scalar_function_set_name", &DuckDBNodeAddon::scalar_function_set_name),
1553+
InstanceMethod("scalar_function_set_return_type", &DuckDBNodeAddon::scalar_function_set_return_type),
1554+
InstanceMethod("scalar_function_set_function", &DuckDBNodeAddon::scalar_function_set_function),
1555+
InstanceMethod("register_scalar_function", &DuckDBNodeAddon::register_scalar_function),
1556+
InstanceMethod("scalar_function_set_error", &DuckDBNodeAddon::scalar_function_set_error),
1557+
14241558
InstanceMethod("appender_create", &DuckDBNodeAddon::appender_create),
14251559
InstanceMethod("appender_create_ext", &DuckDBNodeAddon::appender_create_ext),
14261560
InstanceMethod("appender_column_count", &DuckDBNodeAddon::appender_column_count),
@@ -3680,7 +3814,7 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
36803814
auto chunk = GetDataChunkFromExternal(env, info[0]);
36813815
auto column_index = info[1].As<Napi::Number>().Uint32Value();
36823816
auto vector = duckdb_data_chunk_get_vector(chunk, column_index);
3683-
return CreateExternalForVector(env, vector);
3817+
return CreateExternalForVectorWithoutFinalizer(env, vector);
36843818
}
36853819

36863820
// DUCKDB_C_API idx_t duckdb_data_chunk_get_size(duckdb_data_chunk chunk);
@@ -3779,7 +3913,7 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
37793913
auto env = info.Env();
37803914
auto vector = GetVectorFromExternal(env, info[0]);
37813915
auto child = duckdb_list_vector_get_child(vector);
3782-
return CreateExternalForVector(env, child);
3916+
return CreateExternalForVectorWithoutFinalizer(env, child);
37833917
}
37843918

37853919
// DUCKDB_C_API idx_t duckdb_list_vector_get_size(duckdb_vector vector);
@@ -3818,7 +3952,7 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
38183952
auto vector = GetVectorFromExternal(env, info[0]);
38193953
auto index = info[1].As<Napi::Number>().Uint32Value();
38203954
auto child = duckdb_struct_vector_get_child(vector, index);
3821-
return CreateExternalForVector(env, child);
3955+
return CreateExternalForVectorWithoutFinalizer(env, child);
38223956
}
38233957

38243958
// DUCKDB_C_API duckdb_vector duckdb_array_vector_get_child(duckdb_vector vector);
@@ -3827,7 +3961,7 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
38273961
auto env = info.Env();
38283962
auto vector = GetVectorFromExternal(env, info[0]);
38293963
auto child = duckdb_array_vector_get_child(vector);
3830-
return CreateExternalForVector(env, child);
3964+
return CreateExternalForVectorWithoutFinalizer(env, child);
38313965
}
38323966

38333967
// DUCKDB_C_API void duckdb_slice_vector(duckdb_vector vector, duckdb_selection_vector selection, idx_t len);
@@ -3878,23 +4012,90 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
38784012
}
38794013

38804014
// DUCKDB_C_API duckdb_scalar_function duckdb_create_scalar_function();
4015+
// function create_scalar_function(): ScalarFunction
4016+
Napi::Value create_scalar_function(const Napi::CallbackInfo& info) {
4017+
auto env = info.Env();
4018+
auto scalar_function = duckdb_create_scalar_function();
4019+
return CreateExternalForScalarFunction(env, scalar_function);
4020+
}
4021+
38814022
// DUCKDB_C_API void duckdb_destroy_scalar_function(duckdb_scalar_function *scalar_function);
4023+
// function destroy_scalar_function_sync(scalar_function: ScalarFunction): void
4024+
Napi::Value destroy_scalar_function_sync(const Napi::CallbackInfo& info) {
4025+
auto env = info.Env();
4026+
auto scalar_function_holder_ptr = GetScalarFunctionHolderFromExternal(env, info[0]);
4027+
// duckdb_destroy_scalar_function is a no-op if already closed
4028+
duckdb_destroy_scalar_function(&scalar_function_holder_ptr->scalar_function);
4029+
return env.Undefined();
4030+
}
4031+
38824032
// DUCKDB_C_API void duckdb_scalar_function_set_name(duckdb_scalar_function scalar_function, const char *name);
4033+
// function scalar_function_set_name(scalar_function: ScalarFunction, name: string): void
4034+
Napi::Value scalar_function_set_name(const Napi::CallbackInfo& info) {
4035+
auto env = info.Env();
4036+
auto scalar_function = GetScalarFunctionFromExternal(env, info[0]);
4037+
std::string name = info[1].As<Napi::String>();
4038+
duckdb_scalar_function_set_name(scalar_function, name.c_str());
4039+
return env.Undefined();
4040+
}
4041+
38834042
// DUCKDB_C_API void duckdb_scalar_function_set_varargs(duckdb_scalar_function scalar_function, duckdb_logical_type type);
38844043
// DUCKDB_C_API void duckdb_scalar_function_set_special_handling(duckdb_scalar_function scalar_function);
38854044
// DUCKDB_C_API void duckdb_scalar_function_set_volatile(duckdb_scalar_function scalar_function);
38864045
// DUCKDB_C_API void duckdb_scalar_function_add_parameter(duckdb_scalar_function scalar_function, duckdb_logical_type type);
4046+
38874047
// DUCKDB_C_API void duckdb_scalar_function_set_return_type(duckdb_scalar_function scalar_function, duckdb_logical_type type);
4048+
// function scalar_function_set_return_type(scalar_function: ScalarFunction, logical_type: LogicalType): void
4049+
Napi::Value scalar_function_set_return_type(const Napi::CallbackInfo& info) {
4050+
auto env = info.Env();
4051+
auto scalar_function = GetScalarFunctionFromExternal(env, info[0]);
4052+
auto logical_type = GetLogicalTypeFromExternal(env, info[1]);
4053+
duckdb_scalar_function_set_return_type(scalar_function, logical_type);
4054+
return env.Undefined();
4055+
}
4056+
38884057
// DUCKDB_C_API void duckdb_scalar_function_set_extra_info(duckdb_scalar_function scalar_function, void *extra_info, duckdb_delete_callback_t destroy);
38894058
// DUCKDB_C_API void duckdb_scalar_function_set_bind(duckdb_scalar_function scalar_function, duckdb_scalar_function_bind_t bind);
38904059
// DUCKDB_C_API void duckdb_scalar_function_set_bind_data(duckdb_bind_info info, void *bind_data, duckdb_delete_callback_t destroy);
38914060
// DUCKDB_C_API void duckdb_scalar_function_bind_set_error(duckdb_bind_info info, const char *error);
4061+
38924062
// DUCKDB_C_API void duckdb_scalar_function_set_function(duckdb_scalar_function scalar_function, duckdb_scalar_function_t function);
4063+
// function scalar_function_set_function(scalar_function: ScalarFunction, func: ScalarFunctionMainFunction): void
4064+
Napi::Value scalar_function_set_function(const Napi::CallbackInfo& info) {
4065+
auto env = info.Env();
4066+
auto scalar_function = GetScalarFunctionFromExternal(env, info[0]);
4067+
auto func = info[1].As<Napi::Function>();
4068+
auto extra_info = CreateScalarFunctionMainExtraInfo(env, func);
4069+
duckdb_scalar_function_set_extra_info(scalar_function, extra_info, reinterpret_cast<duckdb_delete_callback_t>(DeleteScalarFunctionMainExtraInfo));
4070+
duckdb_scalar_function_set_function(scalar_function, &ScalarFunctionMainFunction);
4071+
return env.Undefined();
4072+
}
4073+
38934074
// DUCKDB_C_API duckdb_state duckdb_register_scalar_function(duckdb_connection con, duckdb_scalar_function scalar_function);
4075+
// function register_scalar_function(connection: Connection, scalar_function: ScalarFunction): void
4076+
Napi::Value register_scalar_function(const Napi::CallbackInfo& info) {
4077+
auto env = info.Env();
4078+
auto connection = GetConnectionFromExternal(env, info[0]);
4079+
auto scalar_function = GetScalarFunctionFromExternal(env, info[1]);
4080+
if (duckdb_register_scalar_function(connection, scalar_function)) {
4081+
throw Napi::Error::New(env, "Failed to register scalar function");
4082+
}
4083+
return env.Undefined();
4084+
}
4085+
38944086
// DUCKDB_C_API void *duckdb_scalar_function_get_extra_info(duckdb_function_info info);
38954087
// DUCKDB_C_API void *duckdb_scalar_function_get_bind_data(duckdb_function_info info);
38964088
// DUCKDB_C_API void duckdb_scalar_function_get_client_context(duckdb_bind_info info, duckdb_client_context *out_context);
4089+
38974090
// DUCKDB_C_API void duckdb_scalar_function_set_error(duckdb_function_info info, const char *error);
4091+
// function scalar_function_set_error(function_info: FunctionInfo, error: string): void
4092+
Napi::Value scalar_function_set_error(const Napi::CallbackInfo& info) {
4093+
auto env = info.Env();
4094+
auto function_info = GetFunctionInfoFromExternal(env, info[0]);
4095+
std::string error = info[1].As<Napi::String>();
4096+
duckdb_scalar_function_set_error(function_info, error.c_str());
4097+
return env.Undefined();
4098+
}
38984099

38994100
// DUCKDB_C_API duckdb_scalar_function_set duckdb_create_scalar_function_set(const char *name);
39004101
// DUCKDB_C_API void duckdb_destroy_scalar_function_set(duckdb_scalar_function_set *scalar_function_set);
@@ -4490,14 +4691,14 @@ NODE_API_ADDON(DuckDBNodeAddon)
44904691
---
44914692
431 total functions
44924693
4493-
245 instance methods
4694+
252 instance methods
44944695
3 unimplemented client context functions
44954696
1 unimplemented table names function
44964697
1 unimplemented value to string function
44974698
1 unimplemented logical type function
44984699
2 unimplemented vector creation functions
44994700
3 unimplemented vector manipulation functions
4500-
18 unimplemented scalar function functions
4701+
11 unimplemented scalar function functions
45014702
4 unimplemented scalar function set functions
45024703
3 unimplemented selection vector functions
45034704
12 unimplemented aggregate function functions

0 commit comments

Comments
 (0)