Skip to content

Commit f977dd5

Browse files
committed
destroy prepared statements on connection close
1 parent f07df1a commit f977dd5

File tree

5 files changed

+45
-4
lines changed

5 files changed

+45
-4
lines changed

api/src/DuckDBConnection.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ import { DuckDBInstance } from './DuckDBInstance';
55
import { DuckDBMaterializedResult } from './DuckDBMaterializedResult';
66
import { DuckDBPendingResult } from './DuckDBPendingResult';
77
import { DuckDBPreparedStatement } from './DuckDBPreparedStatement';
8+
import { DuckDBPreparedStatementWeakRefCollection } from './DuckDBPreparedStatementWeakRefCollection';
89
import { DuckDBResult } from './DuckDBResult';
910
import { DuckDBResultReader } from './DuckDBResultReader';
1011
import { DuckDBType } from './DuckDBType';
1112
import { DuckDBValue } from './values';
1213

1314
export class DuckDBConnection {
1415
private readonly connection: duckdb.Connection;
16+
private readonly preparedStatements: DuckDBPreparedStatementWeakRefCollection;
1517
constructor(connection: duckdb.Connection) {
1618
this.connection = connection;
19+
this.preparedStatements = new DuckDBPreparedStatementWeakRefCollection();
1720
}
1821
public static async create(
1922
instance?: DuckDBInstance
@@ -28,6 +31,7 @@ export class DuckDBConnection {
2831
return this.disconnectSync();
2932
}
3033
public disconnectSync() {
34+
this.preparedStatements.destroySync();
3135
return duckdb.disconnect_sync(this.connection);
3236
}
3337
public interrupt() {
@@ -141,9 +145,11 @@ export class DuckDBConnection {
141145
return prepared.startStream();
142146
}
143147
public async prepare(sql: string): Promise<DuckDBPreparedStatement> {
144-
return new DuckDBPreparedStatement(
148+
const prepared = new DuckDBPreparedStatement(
145149
await duckdb.prepare(this.connection, sql)
146150
);
151+
this.preparedStatements.add(prepared);
152+
return prepared;
147153
}
148154
public async extractStatements(
149155
sql: string
@@ -160,7 +166,8 @@ export class DuckDBConnection {
160166
return new DuckDBExtractedStatements(
161167
this.connection,
162168
extracted_statements,
163-
statement_count
169+
statement_count,
170+
this.preparedStatements
164171
);
165172
}
166173
public async createAppender(

api/src/DuckDBExtractedStatements.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,37 @@
11
import duckdb from '@duckdb/node-bindings';
22
import { DuckDBPreparedStatement } from './DuckDBPreparedStatement';
3+
import { DuckDBPreparedStatementCollection } from './DuckDBPreparedStatementCollection';
34

45
export class DuckDBExtractedStatements {
56
private readonly connection: duckdb.Connection;
67
private readonly extracted_statements: duckdb.ExtractedStatements;
78
private readonly statement_count: number;
9+
private readonly preparedStatements?: DuckDBPreparedStatementCollection;
810
constructor(
911
connection: duckdb.Connection,
1012
extracted_statements: duckdb.ExtractedStatements,
11-
statement_count: number
13+
statement_count: number,
14+
preparedStatements?: DuckDBPreparedStatementCollection
1215
) {
1316
this.connection = connection;
1417
this.extracted_statements = extracted_statements;
1518
this.statement_count = statement_count;
19+
this.preparedStatements = preparedStatements;
1620
}
1721
public get count(): number {
1822
return this.statement_count;
1923
}
2024
public async prepare(index: number): Promise<DuckDBPreparedStatement> {
21-
return new DuckDBPreparedStatement(
25+
const prepared = new DuckDBPreparedStatement(
2226
await duckdb.prepare_extracted_statement(
2327
this.connection,
2428
this.extracted_statements,
2529
index
2630
)
2731
);
32+
if (this.preparedStatements) {
33+
this.preparedStatements.add(prepared);
34+
}
35+
return prepared;
2836
}
2937
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { DuckDBPreparedStatement } from './DuckDBPreparedStatement';
2+
3+
export interface DuckDBPreparedStatementCollection {
4+
add(prepared: DuckDBPreparedStatement): void;
5+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { DuckDBPreparedStatement } from './DuckDBPreparedStatement';
2+
import { DuckDBPreparedStatementCollection } from './DuckDBPreparedStatementCollection';
3+
4+
export class DuckDBPreparedStatementWeakRefCollection
5+
implements DuckDBPreparedStatementCollection
6+
{
7+
preparedStatements: WeakRef<DuckDBPreparedStatement>[] = [];
8+
public add(prepared: DuckDBPreparedStatement) {
9+
this.preparedStatements.push(new WeakRef(prepared));
10+
}
11+
public destroySync() {
12+
for (const preparedRef of this.preparedStatements) {
13+
const prepared = preparedRef.deref();
14+
if (prepared) {
15+
prepared.destroySync();
16+
}
17+
}
18+
this.preparedStatements = [];
19+
}
20+
}

api/src/duckdb.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export * from './DuckDBLogicalType';
1515
export * from './DuckDBMaterializedResult';
1616
export * from './DuckDBPendingResult';
1717
export * from './DuckDBPreparedStatement';
18+
export * from './DuckDBPreparedStatementCollection';
1819
export * from './DuckDBResult';
1920
export * from './DuckDBType';
2021
export * from './DuckDBTypeId';

0 commit comments

Comments
 (0)