@@ -48,6 +48,9 @@ function splitBindParameters(bindParameters) {
4848 return { params : bindParameters . length === 1 ? bindParameters [ 0 ] : bindParameters , queryOptions : undefined } ;
4949}
5050
51+ const symbolDispose = typeof Symbol . dispose === "symbol" ? Symbol . dispose : null ;
52+ const hasWeakRef = typeof WeakRef === "function" ;
53+
5154/**
5255 * Database represents a connection that can prepare and execute SQL statements.
5356 */
@@ -61,6 +64,8 @@ class Database {
6164 constructor ( path , opts ) {
6265 this . db = new NativeDb ( path , opts ) ;
6366 this . memory = this . db . memory
67+ this . _closed = false ;
68+ this . _statements = hasWeakRef ? new Set ( ) : null ;
6469 const db = this . db ;
6570 Object . defineProperties ( this , {
6671 inTransaction : {
@@ -95,7 +100,13 @@ class Database {
95100 prepare ( sql ) {
96101 try {
97102 const stmt = databasePrepareSync ( this . db , sql ) ;
98- return new Statement ( stmt ) ;
103+ const wrappedStmt = new Statement ( stmt , this ) ;
104+ if ( this . _statements != null ) {
105+ const statementRef = new WeakRef ( wrappedStmt ) ;
106+ wrappedStmt . _statementRef = statementRef ;
107+ this . _statements . add ( statementRef ) ;
108+ }
109+ return wrappedStmt ;
99110 } catch ( err ) {
100111 throw convertError ( err ) ;
101112 }
@@ -215,6 +226,21 @@ class Database {
215226 * Closes the database connection.
216227 */
217228 close ( ) {
229+ if ( this . _closed ) {
230+ return ;
231+ }
232+ this . _closed = true ;
233+ if ( this . _statements != null ) {
234+ for ( const statementRef of Array . from ( this . _statements ) ) {
235+ const statement = statementRef . deref ( ) ;
236+ if ( statement == null ) {
237+ this . _statements . delete ( statementRef ) ;
238+ continue ;
239+ }
240+ statement . close ( ) ;
241+ }
242+ this . _statements . clear ( ) ;
243+ }
218244 this . db . close ( ) ;
219245 }
220246
@@ -240,8 +266,36 @@ class Database {
240266 * Statement represents a prepared SQL statement that can be executed.
241267 */
242268class Statement {
243- constructor ( stmt ) {
269+ constructor ( stmt , database ) {
244270 this . stmt = stmt ;
271+ this . database = database ;
272+ this . _statementRef = null ;
273+ this . _closed = false ;
274+ }
275+
276+ close ( ) {
277+ if ( this . _closed ) {
278+ return this ;
279+ }
280+ this . _closed = true ;
281+ if ( this . database != null && this . database . _statements != null && this . _statementRef != null ) {
282+ this . database . _statements . delete ( this . _statementRef ) ;
283+ }
284+ if ( this . database != null ) {
285+ this . database = null ;
286+ }
287+ if ( this . stmt != null ) {
288+ this . stmt . close ( ) ;
289+ this . stmt = null ;
290+ }
291+ return this ;
292+ }
293+
294+ _getNativeStatement ( ) {
295+ if ( this . _closed || this . stmt == null ) {
296+ throw new TypeError ( "The database connection is not open" ) ;
297+ }
298+ return this . stmt ;
245299 }
246300
247301 /**
@@ -250,7 +304,7 @@ class Statement {
250304 * @param raw Enable or disable raw mode. If you don't pass the parameter, raw mode is enabled.
251305 */
252306 raw ( raw ) {
253- this . stmt . raw ( raw ) ;
307+ this . _getNativeStatement ( ) . raw ( raw ) ;
254308 return this ;
255309 }
256310
@@ -260,7 +314,7 @@ class Statement {
260314 * @param pluckMode Enable or disable pluck mode. If you don't pass the parameter, pluck mode is enabled.
261315 */
262316 pluck ( pluckMode ) {
263- this . stmt . pluck ( pluckMode ) ;
317+ this . _getNativeStatement ( ) . pluck ( pluckMode ) ;
264318 return this ;
265319 }
266320
@@ -270,12 +324,12 @@ class Statement {
270324 * @param timing Enable or disable query timing. If you don't pass the parameter, query timing is enabled.
271325 */
272326 timing ( timingMode ) {
273- this . stmt . timing ( timingMode ) ;
327+ this . _getNativeStatement ( ) . timing ( timingMode ) ;
274328 return this ;
275329 }
276330
277331 get reader ( ) {
278- return this . stmt . columns ( ) . length > 0 ;
332+ return this . _getNativeStatement ( ) . columns ( ) . length > 0 ;
279333 }
280334
281335 /**
@@ -284,7 +338,7 @@ class Statement {
284338 run ( ...bindParameters ) {
285339 try {
286340 const { params, queryOptions } = splitBindParameters ( bindParameters ) ;
287- return statementRunSync ( this . stmt , params , queryOptions ) ;
341+ return statementRunSync ( this . _getNativeStatement ( ) , params , queryOptions ) ;
288342 } catch ( err ) {
289343 throw convertError ( err ) ;
290344 }
@@ -298,7 +352,7 @@ class Statement {
298352 get ( ...bindParameters ) {
299353 try {
300354 const { params, queryOptions } = splitBindParameters ( bindParameters ) ;
301- return statementGetSync ( this . stmt , params , queryOptions ) ;
355+ return statementGetSync ( this . _getNativeStatement ( ) , params , queryOptions ) ;
302356 } catch ( err ) {
303357 throw convertError ( err ) ;
304358 }
@@ -312,7 +366,7 @@ class Statement {
312366 iterate ( ...bindParameters ) {
313367 try {
314368 const { params, queryOptions } = splitBindParameters ( bindParameters ) ;
315- const it = statementIterateSync ( this . stmt , params , queryOptions ) ;
369+ const it = statementIterateSync ( this . _getNativeStatement ( ) , params , queryOptions ) ;
316370 return {
317371 next : ( ) => iteratorNextSync ( it ) ,
318372 [ Symbol . iterator ] ( ) {
@@ -349,26 +403,31 @@ class Statement {
349403 * Interrupts the statement.
350404 */
351405 interrupt ( ) {
352- this . stmt . interrupt ( ) ;
406+ this . _getNativeStatement ( ) . interrupt ( ) ;
353407 return this ;
354408 }
355409
356410 /**
357411 * Returns the columns in the result set returned by this prepared statement.
358412 */
359413 columns ( ) {
360- return this . stmt . columns ( ) ;
414+ return this . _getNativeStatement ( ) . columns ( ) ;
361415 }
362416
363417 /**
364418 * Toggle 64-bit integer support.
365419 */
366420 safeIntegers ( toggle ) {
367- this . stmt . safeIntegers ( toggle ) ;
421+ this . _getNativeStatement ( ) . safeIntegers ( toggle ) ;
368422 return this ;
369423 }
370424}
371425
426+ if ( symbolDispose != null ) {
427+ Database . prototype [ symbolDispose ] = Database . prototype . close ;
428+ Statement . prototype [ symbolDispose ] = Statement . prototype . close ;
429+ }
430+
372431module . exports = Database ;
373432module . exports . SqliteError = SqliteError ;
374433module . exports . Authorization = Authorization ;
0 commit comments