Skip to content

add destroySync to DuckDBPreparedStatement #212

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/src/DuckDBPreparedStatement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export class DuckDBPreparedStatement {
constructor(prepared_statement: duckdb.PreparedStatement) {
this.prepared_statement = prepared_statement;
}
public destroySync() {
return duckdb.destroy_prepare_sync(this.prepared_statement);
}
public get statementType(): StatementType {
return duckdb.prepared_statement_type(this.prepared_statement);
}
Expand Down
1 change: 1 addition & 0 deletions api/test/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ describe('api', () => {
const connection = await instance.connect();
const prepared1 = await connection.prepare('select 1');
assert.isDefined(prepared1);
prepared1.destroySync();
connection.disconnectSync();
try {
await connection.prepare('select 2');
Expand Down
2 changes: 1 addition & 1 deletion bindings/pkgs/@duckdb/node-bindings/duckdb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ export function decimal_to_double(decimal: Decimal): number;
export function prepare(connection: Connection, query: string): Promise<PreparedStatement>;

// DUCKDB_API void duckdb_destroy_prepare(duckdb_prepared_statement *prepared_statement);
// not exposed: destroyed in finalizer
export function destroy_prepare_sync(prepared_statement: PreparedStatement): void;

// DUCKDB_API const char *duckdb_prepare_error(duckdb_prepared_statement prepared_statement);
// not exposed: prepare rejects promise with error
Expand Down
43 changes: 32 additions & 11 deletions bindings/src/duckdb_node_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,19 +544,32 @@ static const napi_type_tag PreparedStatementTypeTag = {
0xA8B03DAD16D34416, 0x9735A7E1F2A1240C
};

void FinalizePreparedStatement(Napi::BasicEnv, duckdb_prepared_statement prepared_statement) {
if (prepared_statement) {
duckdb_destroy_prepare(&prepared_statement);
prepared_statement = nullptr;
}
typedef struct {
duckdb_prepared_statement prepared;
} duckdb_prepared_statement_holder;

duckdb_prepared_statement_holder *CreatePreparedStatementHolder(duckdb_prepared_statement prepared) {
auto prepared_statement_holder_ptr = reinterpret_cast<duckdb_prepared_statement_holder*>(duckdb_malloc(sizeof(duckdb_prepared_statement_holder)));
prepared_statement_holder_ptr->prepared = prepared;
return prepared_statement_holder_ptr;
}

Napi::External<_duckdb_prepared_statement> CreateExternalForPreparedStatement(Napi::Env env, duckdb_prepared_statement prepared_statement) {
return CreateExternal<_duckdb_prepared_statement>(env, PreparedStatementTypeTag, prepared_statement, FinalizePreparedStatement);
void FinalizePreparedStatementHolder(Napi::BasicEnv, duckdb_prepared_statement_holder *prepared_statement_holder_ptr) {
// duckdb_destroy_prepare is a no-op if already destroyed
duckdb_destroy_prepare(&prepared_statement_holder_ptr->prepared);
duckdb_free(prepared_statement_holder_ptr);
}

Napi::External<duckdb_prepared_statement_holder> CreateExternalForPreparedStatement(Napi::Env env, duckdb_prepared_statement prepared_statement) {
return CreateExternal<duckdb_prepared_statement_holder>(env, PreparedStatementTypeTag, CreatePreparedStatementHolder(prepared_statement), FinalizePreparedStatementHolder);
}

duckdb_prepared_statement_holder *GetPreparedStatementHolderFromExternal(Napi::Env env, Napi::Value value) {
return GetDataFromExternal<duckdb_prepared_statement_holder>(env, PreparedStatementTypeTag, value, "Invalid prepared statement argument");
}

duckdb_prepared_statement GetPreparedStatementFromExternal(Napi::Env env, Napi::Value value) {
return GetDataFromExternal<_duckdb_prepared_statement>(env, PreparedStatementTypeTag, value, "Invalid prepared statement argument");
return GetPreparedStatementHolderFromExternal(env, value)->prepared;
}

static const napi_type_tag ResultTypeTag = {
Expand Down Expand Up @@ -1232,6 +1245,7 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
InstanceMethod("decimal_to_double", &DuckDBNodeAddon::decimal_to_double),

InstanceMethod("prepare", &DuckDBNodeAddon::prepare),
InstanceMethod("destroy_prepare_sync", &DuckDBNodeAddon::destroy_prepare_sync),
InstanceMethod("nparams", &DuckDBNodeAddon::nparams),
InstanceMethod("parameter_name", &DuckDBNodeAddon::parameter_name),
InstanceMethod("param_type", &DuckDBNodeAddon::param_type),
Expand Down Expand Up @@ -1996,7 +2010,14 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
}

// DUCKDB_API void duckdb_destroy_prepare(duckdb_prepared_statement *prepared_statement);
// not exposed: destroyed in finalizer
// function destroy_prepare_sync(prepared_statement: PreparedStatement): void
Napi::Value destroy_prepare_sync(const Napi::CallbackInfo& info) {
auto env = info.Env();
auto prepared_statement_holder_ptr = GetPreparedStatementHolderFromExternal(env, info[0]);
// duckdb_destroy_prepare is a no-op if already destroyed
duckdb_destroy_prepare(&prepared_statement_holder_ptr->prepared);
return env.Undefined();
}

// DUCKDB_API const char *duckdb_prepare_error(duckdb_prepared_statement prepared_statement);
// not exposed: prepare rejects promise with error
Expand Down Expand Up @@ -4391,7 +4412,7 @@ NODE_API_ADDON(DuckDBNodeAddon)
---
411 total functions

242 instance methods
243 instance methods
1 unimplemented logical type function
13 unimplemented scalar function functions
4 unimplemented scalar function set functions
Expand All @@ -4407,7 +4428,7 @@ NODE_API_ADDON(DuckDBNodeAddon)
6 unimplemented table description functions
8 unimplemented tasks functions
12 unimplemented cast function functions
24 functions not exposed
23 functions not exposed
+ 41 unimplemented deprecated functions (of 47)
---
411 functions accounted for
Expand Down
6 changes: 6 additions & 0 deletions bindings/test/prepared_statements.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,4 +448,10 @@ suite('prepared statements', () => {
}
});
});
test('destroy_prepare_sync', async () => {
await withConnection(async (connection) => {
const prepared = await duckdb.prepare(connection, 'select 1');
duckdb.destroy_prepare_sync(prepared);
});
});
});