expo-sqlite 57.0.3 → 57.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/sqlite/SQLiteModule.kt +38 -22
  4. package/build/SQLiteStatement.d.ts +10 -0
  5. package/build/SQLiteStatement.d.ts.map +1 -1
  6. package/build/SQLiteStatement.js +58 -16
  7. package/build/SQLiteStatement.js.map +1 -1
  8. package/expo-module.config.json +1 -1
  9. package/ios/SQLiteModule.swift +28 -0
  10. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/{57.0.3/expo.modules.sqlite-57.0.3-sources.jar → 57.0.4/expo.modules.sqlite-57.0.4-sources.jar} +0 -0
  11. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4-sources.jar.md5 +1 -0
  12. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4-sources.jar.sha1 +1 -0
  13. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4-sources.jar.sha256 +1 -0
  14. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4-sources.jar.sha512 +1 -0
  15. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/{57.0.3/expo.modules.sqlite-57.0.3.aar → 57.0.4/expo.modules.sqlite-57.0.4.aar} +0 -0
  16. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.aar.md5 +1 -0
  17. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.aar.sha1 +1 -0
  18. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.aar.sha256 +1 -0
  19. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.aar.sha512 +1 -0
  20. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/{57.0.3/expo.modules.sqlite-57.0.3.module → 57.0.4/expo.modules.sqlite-57.0.4.module} +22 -22
  21. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.module.md5 +1 -0
  22. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.module.sha1 +1 -0
  23. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.module.sha256 +1 -0
  24. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.module.sha512 +1 -0
  25. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/{57.0.3/expo.modules.sqlite-57.0.3.pom → 57.0.4/expo.modules.sqlite-57.0.4.pom} +1 -1
  26. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.pom.md5 +1 -0
  27. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.pom.sha1 +1 -0
  28. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.pom.sha256 +1 -0
  29. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.4/expo.modules.sqlite-57.0.4.pom.sha512 +1 -0
  30. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/maven-metadata.xml +4 -4
  31. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/maven-metadata.xml.md5 +1 -1
  32. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/maven-metadata.xml.sha1 +1 -1
  33. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/maven-metadata.xml.sha256 +1 -1
  34. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/maven-metadata.xml.sha512 +1 -1
  35. package/package.json +4 -4
  36. package/src/SQLiteStatement.ts +70 -16
  37. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3-sources.jar.md5 +0 -1
  38. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3-sources.jar.sha1 +0 -1
  39. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3-sources.jar.sha256 +0 -1
  40. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3-sources.jar.sha512 +0 -1
  41. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.aar.md5 +0 -1
  42. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.aar.sha1 +0 -1
  43. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.aar.sha256 +0 -1
  44. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.aar.sha512 +0 -1
  45. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.module.md5 +0 -1
  46. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.module.sha1 +0 -1
  47. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.module.sha256 +0 -1
  48. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.module.sha512 +0 -1
  49. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.pom.md5 +0 -1
  50. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.pom.sha1 +0 -1
  51. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.pom.sha256 +0 -1
  52. package/local-maven-repo/host/exp/exponent/expo.modules.sqlite/57.0.3/expo.modules.sqlite-57.0.3.pom.sha512 +0 -1
package/CHANGELOG.md CHANGED
@@ -10,6 +10,12 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 57.0.4 — 2026-10-06
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - Fixed reading a prepared statement result after the same statement ran again returning the later run's rows instead of throwing. Also guarded `step`, `getAll`, `reset` and `finalize` with the same per-statement lock that `run` takes. ([#49796](https://github.com/expo/expo/pull/49796) by [@tsapeta](https://github.com/tsapeta))
18
+
13
19
  ## 57.0.3 — 2026-09-11
14
20
 
15
21
  _This version does not introduce any user-facing changes._
@@ -47,13 +47,13 @@ def reactNativeArchitectures() {
47
47
  }
48
48
 
49
49
  group = 'host.exp.exponent'
50
- version = '57.0.3'
50
+ version = '57.0.4'
51
51
 
52
52
  android {
53
53
  namespace "expo.modules.sqlite"
54
54
  defaultConfig {
55
55
  versionCode 18
56
- versionName "57.0.3"
56
+ versionName "57.0.4"
57
57
  buildConfigField "boolean", "USE_LIBSQL", project.ext.USE_LIBSQL.toString()
58
58
  buildConfigField "boolean", "WITH_SQLITE_VEC", project.ext.WITH_SQLITE_VEC.toString()
59
59
 
@@ -437,40 +437,52 @@ class SQLiteModule : Module() {
437
437
  private fun step(statement: NativeStatement, database: NativeDatabase): SQLiteColumnValues? {
438
438
  maybeThrowForClosedDatabase(database)
439
439
  maybeThrowForFinalizedStatement(statement)
440
- val ret = statement.ref.sqlite3_step()
441
- if (ret == NativeDatabaseBinding.SQLITE_ROW) {
442
- return statement.getTransformedColumnValues()
443
- }
444
- if (ret != NativeDatabaseBinding.SQLITE_DONE) {
445
- throw SQLiteErrorException(database.ref.convertSqlLiteErrorToString())
440
+
441
+ // Guard the stateful statement, see `run` above.
442
+ synchronized(statement) {
443
+ val ret = statement.ref.sqlite3_step()
444
+ if (ret == NativeDatabaseBinding.SQLITE_ROW) {
445
+ return statement.getTransformedColumnValues()
446
+ }
447
+ if (ret != NativeDatabaseBinding.SQLITE_DONE) {
448
+ throw SQLiteErrorException(database.ref.convertSqlLiteErrorToString())
449
+ }
450
+ return null
446
451
  }
447
- return null
448
452
  }
449
453
 
450
454
  @Throws(AccessClosedResourceException::class, InvalidConvertibleException::class, SQLiteErrorException::class)
451
455
  private fun getAll(statement: NativeStatement, database: NativeDatabase): List<SQLiteColumnValues> {
452
456
  maybeThrowForClosedDatabase(database)
453
457
  maybeThrowForFinalizedStatement(statement)
454
- val columnValuesList = mutableListOf<SQLiteColumnValues>()
455
- while (true) {
456
- val ret = statement.ref.sqlite3_step()
457
- if (ret == NativeDatabaseBinding.SQLITE_ROW) {
458
- columnValuesList.add(statement.getTransformedColumnValues())
459
- continue
460
- } else if (ret == NativeDatabaseBinding.SQLITE_DONE) {
461
- break
458
+
459
+ // Guard the stateful statement, see `run` above.
460
+ synchronized(statement) {
461
+ val columnValuesList = mutableListOf<SQLiteColumnValues>()
462
+ while (true) {
463
+ val ret = statement.ref.sqlite3_step()
464
+ if (ret == NativeDatabaseBinding.SQLITE_ROW) {
465
+ columnValuesList.add(statement.getTransformedColumnValues())
466
+ continue
467
+ } else if (ret == NativeDatabaseBinding.SQLITE_DONE) {
468
+ break
469
+ }
470
+ throw SQLiteErrorException(database.ref.convertSqlLiteErrorToString())
462
471
  }
463
- throw SQLiteErrorException(database.ref.convertSqlLiteErrorToString())
472
+ return columnValuesList
464
473
  }
465
- return columnValuesList
466
474
  }
467
475
 
468
476
  @Throws(AccessClosedResourceException::class, SQLiteErrorException::class)
469
477
  private fun reset(statement: NativeStatement, database: NativeDatabase) {
470
478
  maybeThrowForClosedDatabase(database)
471
479
  maybeThrowForFinalizedStatement(statement)
472
- if (statement.ref.sqlite3_reset() != NativeDatabaseBinding.SQLITE_OK) {
473
- throw SQLiteErrorException(database.ref.convertSqlLiteErrorToString())
480
+
481
+ // Guard the stateful statement, see `run` above.
482
+ synchronized(statement) {
483
+ if (statement.ref.sqlite3_reset() != NativeDatabaseBinding.SQLITE_OK) {
484
+ throw SQLiteErrorException(database.ref.convertSqlLiteErrorToString())
485
+ }
474
486
  }
475
487
  }
476
488
 
@@ -478,10 +490,14 @@ class SQLiteModule : Module() {
478
490
  private fun finalize(statement: NativeStatement, database: NativeDatabase) {
479
491
  maybeThrowForClosedDatabase(database)
480
492
  maybeThrowForFinalizedStatement(statement)
481
- if (statement.ref.sqlite3_finalize() != NativeDatabaseBinding.SQLITE_OK) {
482
- throw SQLiteErrorException(database.ref.convertSqlLiteErrorToString())
493
+
494
+ // Guard the stateful statement, see `run` above.
495
+ synchronized(statement) {
496
+ if (statement.ref.sqlite3_finalize() != NativeDatabaseBinding.SQLITE_OK) {
497
+ throw SQLiteErrorException(database.ref.convertSqlLiteErrorToString())
498
+ }
499
+ statement.isFinalized = true
483
500
  }
484
- statement.isFinalized = true
485
501
  }
486
502
 
487
503
  private fun addUpdateHook(database: NativeDatabase) {
@@ -8,7 +8,17 @@ type ValuesOf<T extends object> = T[keyof T][];
8
8
  export declare class SQLiteStatement {
9
9
  private readonly nativeDatabase;
10
10
  private readonly nativeStatement;
11
+ /**
12
+ * The cursor that currently owns the underlying `sqlite3_stmt`. A prepared statement has exactly
13
+ * one cursor, so running the statement again invalidates the cursor of every earlier run.
14
+ */
15
+ private currentCursor;
11
16
  constructor(nativeDatabase: NativeDatabase, nativeStatement: NativeStatement);
17
+ /**
18
+ * Make the run that just finished the owner of the statement cursor, and return a predicate
19
+ * that tells whether it still is.
20
+ */
21
+ private claimCursor;
12
22
  /**
13
23
  * Run the prepared statement and return the [`SQLiteExecuteAsyncResult`](#sqliteexecuteasyncresult) instance.
14
24
  * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`SQLiteBindValue`](#sqlitebindvalue) for more information about binding values.
@@ -1 +1 @@
1
- {"version":3,"file":"SQLiteStatement.d.ts","sourceRoot":"","sources":["../src/SQLiteStatement.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SQLiteStatement.d.ts","sourceRoot":"","sources":["../src/SQLiteStatement.ts"],"names":[],"mappings":"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"}
@@ -5,17 +5,31 @@ import { composeRow, composeRows, normalizeParams } from './paramUtils';
5
5
  export class SQLiteStatement {
6
6
  nativeDatabase;
7
7
  nativeStatement;
8
+ /**
9
+ * The cursor that currently owns the underlying `sqlite3_stmt`. A prepared statement has exactly
10
+ * one cursor, so running the statement again invalidates the cursor of every earlier run.
11
+ */
12
+ currentCursor = null;
8
13
  constructor(nativeDatabase, nativeStatement) {
9
14
  this.nativeDatabase = nativeDatabase;
10
15
  this.nativeStatement = nativeStatement;
11
16
  }
17
+ /**
18
+ * Make the run that just finished the owner of the statement cursor, and return a predicate
19
+ * that tells whether it still is.
20
+ */
21
+ claimCursor() {
22
+ const cursor = {};
23
+ this.currentCursor = cursor;
24
+ return () => this.currentCursor === cursor;
25
+ }
12
26
  async executeAsync(...params) {
13
27
  const { lastInsertRowId, changes, firstRowValues } = await this.nativeStatement.runAsync(this.nativeDatabase, ...normalizeParams(...params));
14
28
  return createSQLiteExecuteAsyncResult(this.nativeDatabase, this.nativeStatement, firstRowValues, {
15
29
  rawResult: false,
16
30
  lastInsertRowId,
17
31
  changes,
18
- });
32
+ }, this.claimCursor());
19
33
  }
20
34
  async executeForRawResultAsync(...params) {
21
35
  const { lastInsertRowId, changes, firstRowValues } = await this.nativeStatement.runAsync(this.nativeDatabase, ...normalizeParams(...params));
@@ -23,7 +37,7 @@ export class SQLiteStatement {
23
37
  rawResult: true,
24
38
  lastInsertRowId,
25
39
  changes,
26
- });
40
+ }, this.claimCursor());
27
41
  }
28
42
  /**
29
43
  * Get the column names of the prepared statement.
@@ -48,7 +62,7 @@ export class SQLiteStatement {
48
62
  rawResult: false,
49
63
  lastInsertRowId,
50
64
  changes,
51
- });
65
+ }, this.claimCursor());
52
66
  }
53
67
  executeForRawResultSync(...params) {
54
68
  const { lastInsertRowId, changes, firstRowValues } = this.nativeStatement.runSync(this.nativeDatabase, ...normalizeParams(...params));
@@ -56,7 +70,7 @@ export class SQLiteStatement {
56
70
  rawResult: true,
57
71
  lastInsertRowId,
58
72
  changes,
59
- });
73
+ }, this.claimCursor());
60
74
  }
61
75
  /**
62
76
  * Get the column names of the prepared statement.
@@ -77,14 +91,18 @@ export class SQLiteStatement {
77
91
  this.nativeStatement.finalizeSync(this.nativeDatabase);
78
92
  }
79
93
  }
94
+ const SUPERSEDED_CURSOR_MESSAGE = 'This result is no longer readable because the prepared statement ran again. ' +
95
+ 'A prepared statement holds a single SQLite cursor, so a later run rebinds the parameters and moves that cursor, ' +
96
+ 'and this result would return the rows of the later run. ' +
97
+ 'Read a result to the end before you run the same statement again, or prepare a separate statement for each reader.';
80
98
  /**
81
99
  * Create the `SQLiteExecuteAsyncResult` instance.
82
100
  *
83
101
  * NOTE: Since Hermes does not support the `Symbol.asyncIterator` feature, we have to use an AsyncGenerator to implement the `AsyncIterableIterator` interface.
84
102
  * This is done by `Object.defineProperties` to add the properties to the AsyncGenerator.
85
103
  */
86
- async function createSQLiteExecuteAsyncResult(database, statement, firstRowValues, options) {
87
- const instance = new SQLiteExecuteAsyncResultImpl(database, statement, firstRowValues ? processNativeRow(firstRowValues) : null, options);
104
+ async function createSQLiteExecuteAsyncResult(database, statement, firstRowValues, options, isCursorOwner) {
105
+ const instance = new SQLiteExecuteAsyncResultImpl(database, statement, firstRowValues ? processNativeRow(firstRowValues) : null, options, isCursorOwner);
88
106
  const generator = instance.generatorAsync();
89
107
  Object.defineProperties(generator, {
90
108
  lastInsertRowId: {
@@ -118,8 +136,8 @@ async function createSQLiteExecuteAsyncResult(database, statement, firstRowValue
118
136
  /**
119
137
  * Create the `SQLiteExecuteSyncResult` instance.
120
138
  */
121
- function createSQLiteExecuteSyncResult(database, statement, firstRowValues, options) {
122
- const instance = new SQLiteExecuteSyncResultImpl(database, statement, firstRowValues ? processNativeRow(firstRowValues) : firstRowValues, options);
139
+ function createSQLiteExecuteSyncResult(database, statement, firstRowValues, options, isCursorOwner) {
140
+ const instance = new SQLiteExecuteSyncResultImpl(database, statement, firstRowValues ? processNativeRow(firstRowValues) : firstRowValues, options, isCursorOwner);
123
141
  const generator = instance.generatorSync();
124
142
  Object.defineProperties(generator, {
125
143
  lastInsertRowId: {
@@ -155,13 +173,21 @@ class SQLiteExecuteAsyncResultImpl {
155
173
  statement;
156
174
  firstRowValues;
157
175
  options;
176
+ isCursorOwner;
158
177
  columnNames = null;
159
178
  isStepCalled = false;
160
- constructor(database, statement, firstRowValues, options) {
179
+ constructor(database, statement, firstRowValues, options, isCursorOwner) {
161
180
  this.database = database;
162
181
  this.statement = statement;
163
182
  this.firstRowValues = firstRowValues;
164
183
  this.options = options;
184
+ this.isCursorOwner = isCursorOwner;
185
+ }
186
+ /** Throw rather than step a cursor that a later run of the same statement has taken over. */
187
+ assertCursorOwner() {
188
+ if (!this.isCursorOwner()) {
189
+ throw new Error(SUPERSEDED_CURSOR_MESSAGE);
190
+ }
165
191
  }
166
192
  async getFirstAsync() {
167
193
  if (this.isStepCalled) {
@@ -173,6 +199,7 @@ class SQLiteExecuteAsyncResultImpl {
173
199
  if (firstRowValues != null) {
174
200
  return composeRowIfNeeded(this.options.rawResult, columnNames, firstRowValues);
175
201
  }
202
+ this.assertCursorOwner();
176
203
  const firstRow = await this.statement.stepAsync(this.database);
177
204
  return firstRow != null
178
205
  ? composeRowIfNeeded(this.options.rawResult, columnNames, processNativeRow(firstRow))
@@ -189,9 +216,10 @@ class SQLiteExecuteAsyncResultImpl {
189
216
  return [];
190
217
  }
191
218
  const columnNames = await this.getColumnNamesAsync();
219
+ this.assertCursorOwner();
192
220
  const nativeRows = await this.statement.getAllAsync(this.database);
193
221
  const allRows = processNativeRows(nativeRows);
194
- if (firstRowValues != null && firstRowValues.length > 0) {
222
+ if (firstRowValues.length > 0) {
195
223
  return composeRowsIfNeeded(this.options.rawResult, columnNames, [
196
224
  firstRowValues,
197
225
  ...allRows,
@@ -208,16 +236,18 @@ class SQLiteExecuteAsyncResultImpl {
208
236
  }
209
237
  let result;
210
238
  do {
239
+ this.assertCursorOwner();
211
240
  result = await this.statement.stepAsync(this.database);
212
241
  if (result != null) {
213
242
  yield composeRowIfNeeded(this.options.rawResult, columnNames, processNativeRow(result));
214
243
  }
215
244
  } while (result != null);
216
245
  }
217
- resetAsync() {
218
- const result = this.statement.resetAsync(this.database);
246
+ async resetAsync() {
247
+ // Resetting a superseded result would rewind the cursor of the run that owns it now.
248
+ this.assertCursorOwner();
249
+ await this.statement.resetAsync(this.database);
219
250
  this.isStepCalled = false;
220
- return result;
221
251
  }
222
252
  popFirstRowValues() {
223
253
  if (this.firstRowValues != null) {
@@ -239,13 +269,21 @@ class SQLiteExecuteSyncResultImpl {
239
269
  statement;
240
270
  firstRowValues;
241
271
  options;
272
+ isCursorOwner;
242
273
  columnNames = null;
243
274
  isStepCalled = false;
244
- constructor(database, statement, firstRowValues, options) {
275
+ constructor(database, statement, firstRowValues, options, isCursorOwner) {
245
276
  this.database = database;
246
277
  this.statement = statement;
247
278
  this.firstRowValues = firstRowValues;
248
279
  this.options = options;
280
+ this.isCursorOwner = isCursorOwner;
281
+ }
282
+ /** Throw rather than step a cursor that a later run of the same statement has taken over. */
283
+ assertCursorOwner() {
284
+ if (!this.isCursorOwner()) {
285
+ throw new Error(SUPERSEDED_CURSOR_MESSAGE);
286
+ }
249
287
  }
250
288
  getFirstSync() {
251
289
  if (this.isStepCalled) {
@@ -256,6 +294,7 @@ class SQLiteExecuteSyncResultImpl {
256
294
  if (firstRowValues != null) {
257
295
  return composeRowIfNeeded(this.options.rawResult, columnNames, firstRowValues);
258
296
  }
297
+ this.assertCursorOwner();
259
298
  const firstRow = this.statement.stepSync(this.database);
260
299
  return firstRow != null
261
300
  ? composeRowIfNeeded(this.options.rawResult, columnNames, processNativeRow(firstRow))
@@ -271,6 +310,7 @@ class SQLiteExecuteSyncResultImpl {
271
310
  return [];
272
311
  }
273
312
  const columnNames = this.getColumnNamesSync();
313
+ this.assertCursorOwner();
274
314
  const nativeRows = this.statement.getAllSync(this.database);
275
315
  const allRows = processNativeRows(nativeRows);
276
316
  if (firstRowValues != null && firstRowValues.length > 0) {
@@ -289,6 +329,7 @@ class SQLiteExecuteSyncResultImpl {
289
329
  }
290
330
  let result;
291
331
  do {
332
+ this.assertCursorOwner();
292
333
  result = this.statement.stepSync(this.database);
293
334
  if (result != null) {
294
335
  yield composeRowIfNeeded(this.options.rawResult, columnNames, processNativeRow(result));
@@ -296,9 +337,10 @@ class SQLiteExecuteSyncResultImpl {
296
337
  } while (result != null);
297
338
  }
298
339
  resetSync() {
299
- const result = this.statement.resetSync(this.database);
340
+ // Resetting a superseded result would rewind the cursor of the run that owns it now.
341
+ this.assertCursorOwner();
342
+ this.statement.resetSync(this.database);
300
343
  this.isStepCalled = false;
301
- return result;
302
344
  }
303
345
  popFirstRowValues() {
304
346
  if (this.firstRowValues != null) {
@@ -1 +1 @@
1
- {"version":3,"file":"SQLiteStatement.js","sourceRoot":"","sources":["../src/SQLiteStatement.ts"],"names":[],"mappings":"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","sourcesContent":["import type { NativeDatabase } from './NativeDatabase';\nimport type {\n NativeStatement,\n SQLiteBindParams,\n SQLiteVariadicBindParams,\n SQLiteAnyDatabase,\n SQLiteColumnNames,\n SQLiteColumnValues,\n} from './NativeStatement';\nimport { composeRow, composeRows, normalizeParams } from './paramUtils';\n\nexport type {\n SQLiteBindParams,\n SQLiteBindValue,\n SQLiteRunResult,\n SQLiteVariadicBindParams,\n} from './NativeStatement';\n\ntype ValuesOf<T extends object> = T[keyof T][];\n\n/**\n * A prepared statement returned by [`SQLiteDatabase.prepareAsync()`](#prepareasyncsource) or [`SQLiteDatabase.prepareSync()`](#preparesyncsource) that can be binded with parameters and executed.\n */\nexport class SQLiteStatement {\n constructor(\n private readonly nativeDatabase: NativeDatabase,\n private readonly nativeStatement: NativeStatement\n ) {}\n\n //#region Asynchronous API\n\n /**\n * Run the prepared statement and return the [`SQLiteExecuteAsyncResult`](#sqliteexecuteasyncresult) instance.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`SQLiteBindValue`](#sqlitebindvalue) for more information about binding values.\n */\n public executeAsync<T>(params: SQLiteBindParams): Promise<SQLiteExecuteAsyncResult<T>>;\n /**\n * @hidden\n */\n public executeAsync<T>(...params: SQLiteVariadicBindParams): Promise<SQLiteExecuteAsyncResult<T>>;\n public async executeAsync<T>(...params: unknown[]): Promise<SQLiteExecuteAsyncResult<T>> {\n const { lastInsertRowId, changes, firstRowValues } = await this.nativeStatement.runAsync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return createSQLiteExecuteAsyncResult<T>(\n this.nativeDatabase,\n this.nativeStatement,\n firstRowValues,\n {\n rawResult: false,\n lastInsertRowId,\n changes,\n }\n );\n }\n\n /**\n * Similar to [`executeAsync()`](#executeasyncparams) but returns the raw value array result instead of the row objects.\n * @hidden Advanced use only.\n */\n public executeForRawResultAsync<T extends object>(\n params: SQLiteBindParams\n ): Promise<SQLiteExecuteAsyncResult<ValuesOf<T>>>;\n /**\n * @hidden\n */\n public executeForRawResultAsync<T extends object>(\n ...params: SQLiteVariadicBindParams\n ): Promise<SQLiteExecuteAsyncResult<ValuesOf<T>>>;\n public async executeForRawResultAsync<T extends object>(\n ...params: unknown[]\n ): Promise<SQLiteExecuteAsyncResult<ValuesOf<T>>> {\n const { lastInsertRowId, changes, firstRowValues } = await this.nativeStatement.runAsync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return createSQLiteExecuteAsyncResult<ValuesOf<T>>(\n this.nativeDatabase,\n this.nativeStatement,\n firstRowValues,\n {\n rawResult: true,\n lastInsertRowId,\n changes,\n }\n );\n }\n\n /**\n * Get the column names of the prepared statement.\n */\n public getColumnNamesAsync(): Promise<string[]> {\n return this.nativeStatement.getColumnNamesAsync();\n }\n\n /**\n * Finalize the prepared statement. This will call the [`sqlite3_finalize()`](https://www.sqlite.org/c3ref/finalize.html) C function under the hood.\n *\n * Attempting to access a finalized statement will result in an error.\n * > **Note:** While `expo-sqlite` will automatically finalize any orphaned prepared statements upon closing the database, it is considered best practice\n * > to manually finalize prepared statements as soon as they are no longer needed. This helps to prevent resource leaks.\n * > You can use the `try...finally` statement to ensure that prepared statements are finalized even if an error occurs.\n */\n public async finalizeAsync(): Promise<void> {\n await this.nativeStatement.finalizeAsync(this.nativeDatabase);\n }\n\n //#endregion\n\n //#region Synchronous API\n\n /**\n * Run the prepared statement and return the [`SQLiteExecuteSyncResult`](#sqliteexecutesyncresult) instance.\n * > **Note:** Running heavy tasks with this function can block the JavaScript thread and affect performance.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`SQLiteBindValue`](#sqlitebindvalue) for more information about binding values.\n */\n public executeSync<T>(params: SQLiteBindParams): SQLiteExecuteSyncResult<T>;\n /**\n * @hidden\n */\n public executeSync<T>(...params: SQLiteVariadicBindParams): SQLiteExecuteSyncResult<T>;\n public executeSync<T>(...params: unknown[]): SQLiteExecuteSyncResult<T> {\n const { lastInsertRowId, changes, firstRowValues } = this.nativeStatement.runSync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return createSQLiteExecuteSyncResult<T>(\n this.nativeDatabase,\n this.nativeStatement,\n firstRowValues,\n {\n rawResult: false,\n lastInsertRowId,\n changes,\n }\n );\n }\n\n /**\n * Similar to [`executeSync()`](#executesyncparams) but returns the raw value array result instead of the row objects.\n * @hidden Advanced use only.\n */\n public executeForRawResultSync<T extends object>(\n params: SQLiteBindParams\n ): SQLiteExecuteSyncResult<ValuesOf<T>>;\n /**\n * @hidden\n */\n public executeForRawResultSync<T extends object>(\n ...params: SQLiteVariadicBindParams\n ): SQLiteExecuteSyncResult<ValuesOf<T>>;\n public executeForRawResultSync<T extends object>(\n ...params: unknown[]\n ): SQLiteExecuteSyncResult<ValuesOf<T>> {\n const { lastInsertRowId, changes, firstRowValues } = this.nativeStatement.runSync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return createSQLiteExecuteSyncResult<ValuesOf<T>>(\n this.nativeDatabase,\n this.nativeStatement,\n firstRowValues,\n {\n rawResult: true,\n lastInsertRowId,\n changes,\n }\n );\n }\n\n /**\n * Get the column names of the prepared statement.\n */\n public getColumnNamesSync(): string[] {\n return this.nativeStatement.getColumnNamesSync();\n }\n\n /**\n * Finalize the prepared statement. This will call the [`sqlite3_finalize()`](https://www.sqlite.org/c3ref/finalize.html) C function under the hood.\n *\n * Attempting to access a finalized statement will result in an error.\n *\n * > **Note:** While `expo-sqlite` will automatically finalize any orphaned prepared statements upon closing the database, it is considered best practice\n * > to manually finalize prepared statements as soon as they are no longer needed. This helps to prevent resource leaks.\n * > You can use the `try...finally` statement to ensure that prepared statements are finalized even if an error occurs.\n */\n public finalizeSync(): void {\n this.nativeStatement.finalizeSync(this.nativeDatabase);\n }\n\n //#endregion\n}\n\n/**\n * A result returned by [`SQLiteStatement.executeAsync()`](#executeasyncparams).\n *\n * @example\n * The result includes the [`lastInsertRowId`](https://www.sqlite.org/c3ref/last_insert_rowid.html) and [`changes`](https://www.sqlite.org/c3ref/changes.html) properties. You can get the information from the write operations.\n * ```ts\n * const statement = await db.prepareAsync('INSERT INTO test (value) VALUES (?)');\n * try {\n * const result = await statement.executeAsync(101);\n * console.log('lastInsertRowId:', result.lastInsertRowId);\n * console.log('changes:', result.changes);\n * } finally {\n * await statement.finalizeAsync();\n * }\n * ```\n *\n * @example\n * The result implements the [`AsyncIterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator) interface, so you can use it in `for await...of` loops.\n * ```ts\n * const statement = await db.prepareAsync('SELECT value FROM test WHERE value > ?');\n * try {\n * const result = await statement.executeAsync<{ value: number }>(100);\n * for await (const row of result) {\n * console.log('row value:', row.value);\n * }\n * } finally {\n * await statement.finalizeAsync();\n * }\n * ```\n *\n * @example\n * If your write operations also return values, you can mix all of them together.\n * ```ts\n * const statement = await db.prepareAsync('INSERT INTO test (name, value) VALUES (?, ?) RETURNING name');\n * try {\n * const result = await statement.executeAsync<{ name: string }>('John Doe', 101);\n * console.log('lastInsertRowId:', result.lastInsertRowId);\n * console.log('changes:', result.changes);\n * for await (const row of result) {\n * console.log('name:', row.name);\n * }\n * } finally {\n * await statement.finalizeAsync();\n * }\n * ```\n */\nexport interface SQLiteExecuteAsyncResult<T> extends AsyncIterableIterator<T> {\n /**\n * The last inserted row ID. Returned from the [`sqlite3_last_insert_rowid()`](https://www.sqlite.org/c3ref/last_insert_rowid.html) function.\n */\n readonly lastInsertRowId: number;\n\n /**\n * The number of rows affected. Returned from the [`sqlite3_changes()`](https://www.sqlite.org/c3ref/changes.html) function.\n */\n readonly changes: number;\n\n /**\n * Get the first row of the result set. This requires the SQLite cursor to be in its initial state. If you have already retrieved rows from the result set, you need to reset the cursor first by calling [`resetAsync()`](#resetasync). Otherwise, an error will be thrown.\n */\n getFirstAsync(): Promise<T | null>;\n\n /**\n * Get all rows of the result set. This requires the SQLite cursor to be in its initial state. If you have already retrieved rows from the result set, you need to reset the cursor first by calling [`resetAsync()`](#resetasync). Otherwise, an error will be thrown.\n */\n getAllAsync(): Promise<T[]>;\n\n /**\n * Reset the prepared statement cursor. This will call the [`sqlite3_reset()`](https://www.sqlite.org/c3ref/reset.html) C function under the hood.\n */\n resetAsync(): Promise<void>;\n}\n\n/**\n * A result returned by [`SQLiteStatement.executeSync()`](#executesyncparams).\n * > **Note:** Running heavy tasks with this function can block the JavaScript thread and affect performance.\n\n * @example\n * The result includes the [`lastInsertRowId`](https://www.sqlite.org/c3ref/last_insert_rowid.html) and [`changes`](https://www.sqlite.org/c3ref/changes.html) properties. You can get the information from the write operations.\n * ```ts\n * const statement = db.prepareSync('INSERT INTO test (value) VALUES (?)');\n * try {\n * const result = statement.executeSync(101);\n * console.log('lastInsertRowId:', result.lastInsertRowId);\n * console.log('changes:', result.changes);\n * } finally {\n * statement.finalizeSync();\n * }\n * ```\n *\n * @example\n * The result implements the [`Iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator) interface, so you can use it in `for...of` loops.\n * ```ts\n * const statement = db.prepareSync('SELECT value FROM test WHERE value > ?');\n * try {\n * const result = statement.executeSync<{ value: number }>(100);\n * for (const row of result) {\n * console.log('row value:', row.value);\n * }\n * } finally {\n * statement.finalizeSync();\n * }\n * ```\n *\n * @example\n * If your write operations also return values, you can mix all of them together.\n * ```ts\n * const statement = db.prepareSync('INSERT INTO test (name, value) VALUES (?, ?) RETURNING name');\n * try {\n * const result = statement.executeSync<{ name: string }>('John Doe', 101);\n * console.log('lastInsertRowId:', result.lastInsertRowId);\n * console.log('changes:', result.changes);\n * for (const row of result) {\n * console.log('name:', row.name);\n * }\n * } finally {\n * statement.finalizeSync();\n * }\n * ```\n */\nexport interface SQLiteExecuteSyncResult<T> extends IterableIterator<T> {\n /**\n * The last inserted row ID. Returned from the [`sqlite3_last_insert_rowid()`](https://www.sqlite.org/c3ref/last_insert_rowid.html) function.\n */\n readonly lastInsertRowId: number;\n\n /**\n * The number of rows affected. Returned from the [`sqlite3_changes()`](https://www.sqlite.org/c3ref/changes.html) function.\n */\n readonly changes: number;\n\n /**\n * Get the first row of the result set. This requires the SQLite cursor to be in its initial state. If you have already retrieved rows from the result set, you need to reset the cursor first by calling [`resetSync()`](#resetsync). Otherwise, an error will be thrown.\n */\n getFirstSync(): T | null;\n\n /**\n * Get all rows of the result set. This requires the SQLite cursor to be in its initial state. If you have already retrieved rows from the result set, you need to reset the cursor first by calling [`resetSync()`](#resetsync). Otherwise, an error will be thrown.\n */\n getAllSync(): T[];\n\n /**\n * Reset the prepared statement cursor. This will call the [`sqlite3_reset()`](https://www.sqlite.org/c3ref/reset.html) C function under the hood.\n */\n resetSync(): void;\n}\n\n//#region Internals for SQLiteExecuteAsyncResult and SQLiteExecuteSyncResult\n\ninterface SQLiteExecuteResultOptions {\n rawResult: boolean;\n lastInsertRowId: number;\n changes: number;\n}\n\n/**\n * Create the `SQLiteExecuteAsyncResult` instance.\n *\n * NOTE: Since Hermes does not support the `Symbol.asyncIterator` feature, we have to use an AsyncGenerator to implement the `AsyncIterableIterator` interface.\n * This is done by `Object.defineProperties` to add the properties to the AsyncGenerator.\n */\nasync function createSQLiteExecuteAsyncResult<T>(\n database: SQLiteAnyDatabase,\n statement: NativeStatement,\n firstRowValues: SQLiteColumnValues | null,\n options: SQLiteExecuteResultOptions\n): Promise<SQLiteExecuteAsyncResult<T>> {\n const instance = new SQLiteExecuteAsyncResultImpl<T>(\n database,\n statement,\n firstRowValues ? processNativeRow(firstRowValues) : null,\n options\n );\n const generator = instance.generatorAsync();\n Object.defineProperties(generator, {\n lastInsertRowId: {\n value: options.lastInsertRowId,\n enumerable: true,\n writable: false,\n configurable: true,\n },\n changes: { value: options.changes, enumerable: true, writable: false, configurable: true },\n getFirstAsync: {\n value: instance.getFirstAsync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n getAllAsync: {\n value: instance.getAllAsync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n resetAsync: {\n value: instance.resetAsync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n });\n\n return generator as SQLiteExecuteAsyncResult<T>;\n}\n\n/**\n * Create the `SQLiteExecuteSyncResult` instance.\n */\nfunction createSQLiteExecuteSyncResult<T>(\n database: SQLiteAnyDatabase,\n statement: NativeStatement,\n firstRowValues: SQLiteColumnValues | null,\n options: SQLiteExecuteResultOptions\n): SQLiteExecuteSyncResult<T> {\n const instance = new SQLiteExecuteSyncResultImpl<T>(\n database,\n statement,\n firstRowValues ? processNativeRow(firstRowValues) : firstRowValues,\n options\n );\n const generator = instance.generatorSync();\n Object.defineProperties(generator, {\n lastInsertRowId: {\n value: options.lastInsertRowId,\n enumerable: true,\n writable: false,\n configurable: true,\n },\n changes: { value: options.changes, enumerable: true, writable: false, configurable: true },\n getFirstSync: {\n value: instance.getFirstSync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n getAllSync: {\n value: instance.getAllSync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n resetSync: {\n value: instance.resetSync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n });\n\n return generator as SQLiteExecuteSyncResult<T>;\n}\n\nclass SQLiteExecuteAsyncResultImpl<T> {\n private columnNames: string[] | null = null;\n private isStepCalled = false;\n\n constructor(\n private readonly database: SQLiteAnyDatabase,\n private readonly statement: NativeStatement,\n private firstRowValues: SQLiteColumnValues | null,\n public readonly options: SQLiteExecuteResultOptions\n ) {}\n\n async getFirstAsync(): Promise<T | null> {\n if (this.isStepCalled) {\n throw new Error(\n 'The SQLite cursor has been shifted and is unable to retrieve the first row without being reset. Invoke `resetAsync()` to reset the cursor first if you want to retrieve the first row.'\n );\n }\n this.isStepCalled = true;\n const columnNames = await this.getColumnNamesAsync();\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues != null) {\n return composeRowIfNeeded<T>(this.options.rawResult, columnNames, firstRowValues);\n }\n const firstRow = await this.statement.stepAsync(this.database);\n return firstRow != null\n ? composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(firstRow))\n : null;\n }\n\n async getAllAsync(): Promise<T[]> {\n if (this.isStepCalled) {\n throw new Error(\n 'The SQLite cursor has been shifted and is unable to retrieve all rows without being reset. Invoke `resetAsync()` to reset the cursor first if you want to retrieve all rows.'\n );\n }\n this.isStepCalled = true;\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues == null) {\n // If the first row is empty, this SQL query may be a write operation. We should not call `statement.getAllAsync()` to write again.\n return [];\n }\n const columnNames = await this.getColumnNamesAsync();\n const nativeRows = await this.statement.getAllAsync(this.database);\n const allRows = processNativeRows(nativeRows);\n if (firstRowValues != null && firstRowValues.length > 0) {\n return composeRowsIfNeeded<T>(this.options.rawResult, columnNames, [\n firstRowValues,\n ...allRows,\n ]);\n }\n return composeRowsIfNeeded<T>(this.options.rawResult, columnNames, allRows);\n }\n\n async *generatorAsync(): AsyncIterableIterator<T> {\n this.isStepCalled = true;\n const columnNames = await this.getColumnNamesAsync();\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues != null) {\n yield composeRowIfNeeded<T>(this.options.rawResult, columnNames, firstRowValues);\n }\n\n let result;\n do {\n result = await this.statement.stepAsync(this.database);\n if (result != null) {\n yield composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(result));\n }\n } while (result != null);\n }\n\n resetAsync(): Promise<void> {\n const result = this.statement.resetAsync(this.database);\n this.isStepCalled = false;\n return result;\n }\n\n private popFirstRowValues(): SQLiteColumnValues | null {\n if (this.firstRowValues != null) {\n const firstRowValues = this.firstRowValues;\n this.firstRowValues = null;\n return firstRowValues.length > 0 ? firstRowValues : null;\n }\n return null;\n }\n\n private async getColumnNamesAsync(): Promise<string[]> {\n if (this.columnNames == null) {\n this.columnNames = await this.statement.getColumnNamesAsync();\n }\n return this.columnNames;\n }\n}\n\nclass SQLiteExecuteSyncResultImpl<T> {\n private columnNames: string[] | null = null;\n private isStepCalled = false;\n\n constructor(\n private readonly database: SQLiteAnyDatabase,\n private readonly statement: NativeStatement,\n private firstRowValues: SQLiteColumnValues | null,\n public readonly options: SQLiteExecuteResultOptions\n ) {}\n\n getFirstSync(): T | null {\n if (this.isStepCalled) {\n throw new Error(\n 'The SQLite cursor has been shifted and is unable to retrieve the first row without being reset. Invoke `resetSync()` to reset the cursor first if you want to retrieve the first row.'\n );\n }\n const columnNames = this.getColumnNamesSync();\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues != null) {\n return composeRowIfNeeded<T>(this.options.rawResult, columnNames, firstRowValues);\n }\n const firstRow = this.statement.stepSync(this.database);\n return firstRow != null\n ? composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(firstRow))\n : null;\n }\n\n getAllSync(): T[] {\n if (this.isStepCalled) {\n throw new Error(\n 'The SQLite cursor has been shifted and is unable to retrieve all rows without being reset. Invoke `resetSync()` to reset the cursor first if you want to retrieve all rows.'\n );\n }\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues == null) {\n // If the first row is empty, this SQL query may be a write operation. We should not call `statement.getAllAsync()` to write again.\n return [];\n }\n const columnNames = this.getColumnNamesSync();\n const nativeRows = this.statement.getAllSync(this.database);\n const allRows = processNativeRows(nativeRows);\n if (firstRowValues != null && firstRowValues.length > 0) {\n return composeRowsIfNeeded<T>(this.options.rawResult, columnNames, [\n firstRowValues,\n ...allRows,\n ]);\n }\n return composeRowsIfNeeded<T>(this.options.rawResult, columnNames, allRows);\n }\n\n *generatorSync(): IterableIterator<T> {\n const columnNames = this.getColumnNamesSync();\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues != null) {\n yield composeRowIfNeeded<T>(this.options.rawResult, columnNames, firstRowValues);\n }\n let result;\n do {\n result = this.statement.stepSync(this.database);\n if (result != null) {\n yield composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(result));\n }\n } while (result != null);\n }\n\n resetSync(): void {\n const result = this.statement.resetSync(this.database);\n this.isStepCalled = false;\n return result;\n }\n\n private popFirstRowValues(): SQLiteColumnValues | null {\n if (this.firstRowValues != null) {\n const firstRowValues = this.firstRowValues;\n this.firstRowValues = null;\n return firstRowValues.length > 0 ? firstRowValues : null;\n }\n return null;\n }\n\n private getColumnNamesSync(): string[] {\n if (this.columnNames == null) {\n this.columnNames = this.statement.getColumnNamesSync();\n }\n return this.columnNames;\n }\n}\n\nfunction composeRowIfNeeded<T>(\n rawResult: boolean,\n columnNames: SQLiteColumnNames,\n columnValues: SQLiteColumnValues\n): T {\n return rawResult\n ? (columnValues as T) // T would be a ValuesOf<> from caller\n : composeRow<T>(columnNames, columnValues);\n}\n\nfunction composeRowsIfNeeded<T>(\n rawResult: boolean,\n columnNames: SQLiteColumnNames,\n columnValuesList: SQLiteColumnValues[]\n): T[] {\n return rawResult\n ? (columnValuesList as T[]) // T[] would be a ValuesOf<>[] from caller\n : composeRows<T>(columnNames, columnValuesList);\n}\n\nfunction processNativeRow(nativeRow: SQLiteColumnValues): SQLiteColumnValues {\n return nativeRow?.map((column) =>\n column instanceof ArrayBuffer ? new Uint8Array(column) : column\n );\n}\n\nfunction processNativeRows(nativeRows: SQLiteColumnValues[]): SQLiteColumnValues[] {\n return nativeRows.map(processNativeRow);\n}\n\n//#endregion\n"]}
1
+ {"version":3,"file":"SQLiteStatement.js","sourceRoot":"","sources":["../src/SQLiteStatement.ts"],"names":[],"mappings":"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","sourcesContent":["import type { NativeDatabase } from './NativeDatabase';\nimport type {\n NativeStatement,\n SQLiteBindParams,\n SQLiteVariadicBindParams,\n SQLiteAnyDatabase,\n SQLiteColumnNames,\n SQLiteColumnValues,\n} from './NativeStatement';\nimport { composeRow, composeRows, normalizeParams } from './paramUtils';\n\nexport type {\n SQLiteBindParams,\n SQLiteBindValue,\n SQLiteRunResult,\n SQLiteVariadicBindParams,\n} from './NativeStatement';\n\ntype ValuesOf<T extends object> = T[keyof T][];\n\n/**\n * A prepared statement returned by [`SQLiteDatabase.prepareAsync()`](#prepareasyncsource) or [`SQLiteDatabase.prepareSync()`](#preparesyncsource) that can be binded with parameters and executed.\n */\nexport class SQLiteStatement {\n /**\n * The cursor that currently owns the underlying `sqlite3_stmt`. A prepared statement has exactly\n * one cursor, so running the statement again invalidates the cursor of every earlier run.\n */\n private currentCursor: object | null = null;\n\n constructor(\n private readonly nativeDatabase: NativeDatabase,\n private readonly nativeStatement: NativeStatement\n ) {}\n\n /**\n * Make the run that just finished the owner of the statement cursor, and return a predicate\n * that tells whether it still is.\n */\n private claimCursor(): () => boolean {\n const cursor = {};\n this.currentCursor = cursor;\n return () => this.currentCursor === cursor;\n }\n\n //#region Asynchronous API\n\n /**\n * Run the prepared statement and return the [`SQLiteExecuteAsyncResult`](#sqliteexecuteasyncresult) instance.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`SQLiteBindValue`](#sqlitebindvalue) for more information about binding values.\n */\n public executeAsync<T>(params: SQLiteBindParams): Promise<SQLiteExecuteAsyncResult<T>>;\n /**\n * @hidden\n */\n public executeAsync<T>(...params: SQLiteVariadicBindParams): Promise<SQLiteExecuteAsyncResult<T>>;\n public async executeAsync<T>(...params: unknown[]): Promise<SQLiteExecuteAsyncResult<T>> {\n const { lastInsertRowId, changes, firstRowValues } = await this.nativeStatement.runAsync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return createSQLiteExecuteAsyncResult<T>(\n this.nativeDatabase,\n this.nativeStatement,\n firstRowValues,\n {\n rawResult: false,\n lastInsertRowId,\n changes,\n },\n this.claimCursor()\n );\n }\n\n /**\n * Similar to [`executeAsync()`](#executeasyncparams) but returns the raw value array result instead of the row objects.\n * @hidden Advanced use only.\n */\n public executeForRawResultAsync<T extends object>(\n params: SQLiteBindParams\n ): Promise<SQLiteExecuteAsyncResult<ValuesOf<T>>>;\n /**\n * @hidden\n */\n public executeForRawResultAsync<T extends object>(\n ...params: SQLiteVariadicBindParams\n ): Promise<SQLiteExecuteAsyncResult<ValuesOf<T>>>;\n public async executeForRawResultAsync<T extends object>(\n ...params: unknown[]\n ): Promise<SQLiteExecuteAsyncResult<ValuesOf<T>>> {\n const { lastInsertRowId, changes, firstRowValues } = await this.nativeStatement.runAsync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return createSQLiteExecuteAsyncResult<ValuesOf<T>>(\n this.nativeDatabase,\n this.nativeStatement,\n firstRowValues,\n {\n rawResult: true,\n lastInsertRowId,\n changes,\n },\n this.claimCursor()\n );\n }\n\n /**\n * Get the column names of the prepared statement.\n */\n public getColumnNamesAsync(): Promise<string[]> {\n return this.nativeStatement.getColumnNamesAsync();\n }\n\n /**\n * Finalize the prepared statement. This will call the [`sqlite3_finalize()`](https://www.sqlite.org/c3ref/finalize.html) C function under the hood.\n *\n * Attempting to access a finalized statement will result in an error.\n * > **Note:** While `expo-sqlite` will automatically finalize any orphaned prepared statements upon closing the database, it is considered best practice\n * > to manually finalize prepared statements as soon as they are no longer needed. This helps to prevent resource leaks.\n * > You can use the `try...finally` statement to ensure that prepared statements are finalized even if an error occurs.\n */\n public async finalizeAsync(): Promise<void> {\n await this.nativeStatement.finalizeAsync(this.nativeDatabase);\n }\n\n //#endregion\n\n //#region Synchronous API\n\n /**\n * Run the prepared statement and return the [`SQLiteExecuteSyncResult`](#sqliteexecutesyncresult) instance.\n * > **Note:** Running heavy tasks with this function can block the JavaScript thread and affect performance.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`SQLiteBindValue`](#sqlitebindvalue) for more information about binding values.\n */\n public executeSync<T>(params: SQLiteBindParams): SQLiteExecuteSyncResult<T>;\n /**\n * @hidden\n */\n public executeSync<T>(...params: SQLiteVariadicBindParams): SQLiteExecuteSyncResult<T>;\n public executeSync<T>(...params: unknown[]): SQLiteExecuteSyncResult<T> {\n const { lastInsertRowId, changes, firstRowValues } = this.nativeStatement.runSync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return createSQLiteExecuteSyncResult<T>(\n this.nativeDatabase,\n this.nativeStatement,\n firstRowValues,\n {\n rawResult: false,\n lastInsertRowId,\n changes,\n },\n this.claimCursor()\n );\n }\n\n /**\n * Similar to [`executeSync()`](#executesyncparams) but returns the raw value array result instead of the row objects.\n * @hidden Advanced use only.\n */\n public executeForRawResultSync<T extends object>(\n params: SQLiteBindParams\n ): SQLiteExecuteSyncResult<ValuesOf<T>>;\n /**\n * @hidden\n */\n public executeForRawResultSync<T extends object>(\n ...params: SQLiteVariadicBindParams\n ): SQLiteExecuteSyncResult<ValuesOf<T>>;\n public executeForRawResultSync<T extends object>(\n ...params: unknown[]\n ): SQLiteExecuteSyncResult<ValuesOf<T>> {\n const { lastInsertRowId, changes, firstRowValues } = this.nativeStatement.runSync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return createSQLiteExecuteSyncResult<ValuesOf<T>>(\n this.nativeDatabase,\n this.nativeStatement,\n firstRowValues,\n {\n rawResult: true,\n lastInsertRowId,\n changes,\n },\n this.claimCursor()\n );\n }\n\n /**\n * Get the column names of the prepared statement.\n */\n public getColumnNamesSync(): string[] {\n return this.nativeStatement.getColumnNamesSync();\n }\n\n /**\n * Finalize the prepared statement. This will call the [`sqlite3_finalize()`](https://www.sqlite.org/c3ref/finalize.html) C function under the hood.\n *\n * Attempting to access a finalized statement will result in an error.\n *\n * > **Note:** While `expo-sqlite` will automatically finalize any orphaned prepared statements upon closing the database, it is considered best practice\n * > to manually finalize prepared statements as soon as they are no longer needed. This helps to prevent resource leaks.\n * > You can use the `try...finally` statement to ensure that prepared statements are finalized even if an error occurs.\n */\n public finalizeSync(): void {\n this.nativeStatement.finalizeSync(this.nativeDatabase);\n }\n\n //#endregion\n}\n\n/**\n * A result returned by [`SQLiteStatement.executeAsync()`](#executeasyncparams).\n *\n * @example\n * The result includes the [`lastInsertRowId`](https://www.sqlite.org/c3ref/last_insert_rowid.html) and [`changes`](https://www.sqlite.org/c3ref/changes.html) properties. You can get the information from the write operations.\n * ```ts\n * const statement = await db.prepareAsync('INSERT INTO test (value) VALUES (?)');\n * try {\n * const result = await statement.executeAsync(101);\n * console.log('lastInsertRowId:', result.lastInsertRowId);\n * console.log('changes:', result.changes);\n * } finally {\n * await statement.finalizeAsync();\n * }\n * ```\n *\n * @example\n * The result implements the [`AsyncIterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator) interface, so you can use it in `for await...of` loops.\n * ```ts\n * const statement = await db.prepareAsync('SELECT value FROM test WHERE value > ?');\n * try {\n * const result = await statement.executeAsync<{ value: number }>(100);\n * for await (const row of result) {\n * console.log('row value:', row.value);\n * }\n * } finally {\n * await statement.finalizeAsync();\n * }\n * ```\n *\n * @example\n * If your write operations also return values, you can mix all of them together.\n * ```ts\n * const statement = await db.prepareAsync('INSERT INTO test (name, value) VALUES (?, ?) RETURNING name');\n * try {\n * const result = await statement.executeAsync<{ name: string }>('John Doe', 101);\n * console.log('lastInsertRowId:', result.lastInsertRowId);\n * console.log('changes:', result.changes);\n * for await (const row of result) {\n * console.log('name:', row.name);\n * }\n * } finally {\n * await statement.finalizeAsync();\n * }\n * ```\n */\nexport interface SQLiteExecuteAsyncResult<T> extends AsyncIterableIterator<T> {\n /**\n * The last inserted row ID. Returned from the [`sqlite3_last_insert_rowid()`](https://www.sqlite.org/c3ref/last_insert_rowid.html) function.\n */\n readonly lastInsertRowId: number;\n\n /**\n * The number of rows affected. Returned from the [`sqlite3_changes()`](https://www.sqlite.org/c3ref/changes.html) function.\n */\n readonly changes: number;\n\n /**\n * Get the first row of the result set. This requires the SQLite cursor to be in its initial state. If you have already retrieved rows from the result set, you need to reset the cursor first by calling [`resetAsync()`](#resetasync). Otherwise, an error will be thrown.\n */\n getFirstAsync(): Promise<T | null>;\n\n /**\n * Get all rows of the result set. This requires the SQLite cursor to be in its initial state. If you have already retrieved rows from the result set, you need to reset the cursor first by calling [`resetAsync()`](#resetasync). Otherwise, an error will be thrown.\n */\n getAllAsync(): Promise<T[]>;\n\n /**\n * Reset the prepared statement cursor. This will call the [`sqlite3_reset()`](https://www.sqlite.org/c3ref/reset.html) C function under the hood.\n */\n resetAsync(): Promise<void>;\n}\n\n/**\n * A result returned by [`SQLiteStatement.executeSync()`](#executesyncparams).\n * > **Note:** Running heavy tasks with this function can block the JavaScript thread and affect performance.\n\n * @example\n * The result includes the [`lastInsertRowId`](https://www.sqlite.org/c3ref/last_insert_rowid.html) and [`changes`](https://www.sqlite.org/c3ref/changes.html) properties. You can get the information from the write operations.\n * ```ts\n * const statement = db.prepareSync('INSERT INTO test (value) VALUES (?)');\n * try {\n * const result = statement.executeSync(101);\n * console.log('lastInsertRowId:', result.lastInsertRowId);\n * console.log('changes:', result.changes);\n * } finally {\n * statement.finalizeSync();\n * }\n * ```\n *\n * @example\n * The result implements the [`Iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator) interface, so you can use it in `for...of` loops.\n * ```ts\n * const statement = db.prepareSync('SELECT value FROM test WHERE value > ?');\n * try {\n * const result = statement.executeSync<{ value: number }>(100);\n * for (const row of result) {\n * console.log('row value:', row.value);\n * }\n * } finally {\n * statement.finalizeSync();\n * }\n * ```\n *\n * @example\n * If your write operations also return values, you can mix all of them together.\n * ```ts\n * const statement = db.prepareSync('INSERT INTO test (name, value) VALUES (?, ?) RETURNING name');\n * try {\n * const result = statement.executeSync<{ name: string }>('John Doe', 101);\n * console.log('lastInsertRowId:', result.lastInsertRowId);\n * console.log('changes:', result.changes);\n * for (const row of result) {\n * console.log('name:', row.name);\n * }\n * } finally {\n * statement.finalizeSync();\n * }\n * ```\n */\nexport interface SQLiteExecuteSyncResult<T> extends IterableIterator<T> {\n /**\n * The last inserted row ID. Returned from the [`sqlite3_last_insert_rowid()`](https://www.sqlite.org/c3ref/last_insert_rowid.html) function.\n */\n readonly lastInsertRowId: number;\n\n /**\n * The number of rows affected. Returned from the [`sqlite3_changes()`](https://www.sqlite.org/c3ref/changes.html) function.\n */\n readonly changes: number;\n\n /**\n * Get the first row of the result set. This requires the SQLite cursor to be in its initial state. If you have already retrieved rows from the result set, you need to reset the cursor first by calling [`resetSync()`](#resetsync). Otherwise, an error will be thrown.\n */\n getFirstSync(): T | null;\n\n /**\n * Get all rows of the result set. This requires the SQLite cursor to be in its initial state. If you have already retrieved rows from the result set, you need to reset the cursor first by calling [`resetSync()`](#resetsync). Otherwise, an error will be thrown.\n */\n getAllSync(): T[];\n\n /**\n * Reset the prepared statement cursor. This will call the [`sqlite3_reset()`](https://www.sqlite.org/c3ref/reset.html) C function under the hood.\n */\n resetSync(): void;\n}\n\n//#region Internals for SQLiteExecuteAsyncResult and SQLiteExecuteSyncResult\n\ninterface SQLiteExecuteResultOptions {\n rawResult: boolean;\n lastInsertRowId: number;\n changes: number;\n}\n\nconst SUPERSEDED_CURSOR_MESSAGE =\n 'This result is no longer readable because the prepared statement ran again. ' +\n 'A prepared statement holds a single SQLite cursor, so a later run rebinds the parameters and moves that cursor, ' +\n 'and this result would return the rows of the later run. ' +\n 'Read a result to the end before you run the same statement again, or prepare a separate statement for each reader.';\n\n/**\n * Create the `SQLiteExecuteAsyncResult` instance.\n *\n * NOTE: Since Hermes does not support the `Symbol.asyncIterator` feature, we have to use an AsyncGenerator to implement the `AsyncIterableIterator` interface.\n * This is done by `Object.defineProperties` to add the properties to the AsyncGenerator.\n */\nasync function createSQLiteExecuteAsyncResult<T>(\n database: SQLiteAnyDatabase,\n statement: NativeStatement,\n firstRowValues: SQLiteColumnValues | null,\n options: SQLiteExecuteResultOptions,\n isCursorOwner: () => boolean\n): Promise<SQLiteExecuteAsyncResult<T>> {\n const instance = new SQLiteExecuteAsyncResultImpl<T>(\n database,\n statement,\n firstRowValues ? processNativeRow(firstRowValues) : null,\n options,\n isCursorOwner\n );\n const generator = instance.generatorAsync();\n Object.defineProperties(generator, {\n lastInsertRowId: {\n value: options.lastInsertRowId,\n enumerable: true,\n writable: false,\n configurable: true,\n },\n changes: { value: options.changes, enumerable: true, writable: false, configurable: true },\n getFirstAsync: {\n value: instance.getFirstAsync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n getAllAsync: {\n value: instance.getAllAsync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n resetAsync: {\n value: instance.resetAsync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n });\n\n return generator as SQLiteExecuteAsyncResult<T>;\n}\n\n/**\n * Create the `SQLiteExecuteSyncResult` instance.\n */\nfunction createSQLiteExecuteSyncResult<T>(\n database: SQLiteAnyDatabase,\n statement: NativeStatement,\n firstRowValues: SQLiteColumnValues | null,\n options: SQLiteExecuteResultOptions,\n isCursorOwner: () => boolean\n): SQLiteExecuteSyncResult<T> {\n const instance = new SQLiteExecuteSyncResultImpl<T>(\n database,\n statement,\n firstRowValues ? processNativeRow(firstRowValues) : firstRowValues,\n options,\n isCursorOwner\n );\n const generator = instance.generatorSync();\n Object.defineProperties(generator, {\n lastInsertRowId: {\n value: options.lastInsertRowId,\n enumerable: true,\n writable: false,\n configurable: true,\n },\n changes: { value: options.changes, enumerable: true, writable: false, configurable: true },\n getFirstSync: {\n value: instance.getFirstSync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n getAllSync: {\n value: instance.getAllSync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n resetSync: {\n value: instance.resetSync.bind(instance),\n enumerable: true,\n writable: false,\n configurable: true,\n },\n });\n\n return generator as SQLiteExecuteSyncResult<T>;\n}\n\nclass SQLiteExecuteAsyncResultImpl<T> {\n private columnNames: string[] | null = null;\n private isStepCalled = false;\n\n constructor(\n private readonly database: SQLiteAnyDatabase,\n private readonly statement: NativeStatement,\n private firstRowValues: SQLiteColumnValues | null,\n public readonly options: SQLiteExecuteResultOptions,\n private readonly isCursorOwner: () => boolean\n ) {}\n\n /** Throw rather than step a cursor that a later run of the same statement has taken over. */\n private assertCursorOwner() {\n if (!this.isCursorOwner()) {\n throw new Error(SUPERSEDED_CURSOR_MESSAGE);\n }\n }\n\n async getFirstAsync(): Promise<T | null> {\n if (this.isStepCalled) {\n throw new Error(\n 'The SQLite cursor has been shifted and is unable to retrieve the first row without being reset. Invoke `resetAsync()` to reset the cursor first if you want to retrieve the first row.'\n );\n }\n this.isStepCalled = true;\n const columnNames = await this.getColumnNamesAsync();\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues != null) {\n return composeRowIfNeeded<T>(this.options.rawResult, columnNames, firstRowValues);\n }\n this.assertCursorOwner();\n const firstRow = await this.statement.stepAsync(this.database);\n return firstRow != null\n ? composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(firstRow))\n : null;\n }\n\n async getAllAsync(): Promise<T[]> {\n if (this.isStepCalled) {\n throw new Error(\n 'The SQLite cursor has been shifted and is unable to retrieve all rows without being reset. Invoke `resetAsync()` to reset the cursor first if you want to retrieve all rows.'\n );\n }\n this.isStepCalled = true;\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues == null) {\n // If the first row is empty, this SQL query may be a write operation. We should not call `statement.getAllAsync()` to write again.\n return [];\n }\n const columnNames = await this.getColumnNamesAsync();\n this.assertCursorOwner();\n const nativeRows = await this.statement.getAllAsync(this.database);\n const allRows = processNativeRows(nativeRows);\n if (firstRowValues.length > 0) {\n return composeRowsIfNeeded<T>(this.options.rawResult, columnNames, [\n firstRowValues,\n ...allRows,\n ]);\n }\n return composeRowsIfNeeded<T>(this.options.rawResult, columnNames, allRows);\n }\n\n async *generatorAsync(): AsyncIterableIterator<T> {\n this.isStepCalled = true;\n const columnNames = await this.getColumnNamesAsync();\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues != null) {\n yield composeRowIfNeeded<T>(this.options.rawResult, columnNames, firstRowValues);\n }\n\n let result;\n do {\n this.assertCursorOwner();\n result = await this.statement.stepAsync(this.database);\n if (result != null) {\n yield composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(result));\n }\n } while (result != null);\n }\n\n async resetAsync(): Promise<void> {\n // Resetting a superseded result would rewind the cursor of the run that owns it now.\n this.assertCursorOwner();\n await this.statement.resetAsync(this.database);\n this.isStepCalled = false;\n }\n\n private popFirstRowValues(): SQLiteColumnValues | null {\n if (this.firstRowValues != null) {\n const firstRowValues = this.firstRowValues;\n this.firstRowValues = null;\n return firstRowValues.length > 0 ? firstRowValues : null;\n }\n return null;\n }\n\n private async getColumnNamesAsync(): Promise<string[]> {\n if (this.columnNames == null) {\n this.columnNames = await this.statement.getColumnNamesAsync();\n }\n return this.columnNames;\n }\n}\n\nclass SQLiteExecuteSyncResultImpl<T> {\n private columnNames: string[] | null = null;\n private isStepCalled = false;\n\n constructor(\n private readonly database: SQLiteAnyDatabase,\n private readonly statement: NativeStatement,\n private firstRowValues: SQLiteColumnValues | null,\n public readonly options: SQLiteExecuteResultOptions,\n private readonly isCursorOwner: () => boolean\n ) {}\n\n /** Throw rather than step a cursor that a later run of the same statement has taken over. */\n private assertCursorOwner() {\n if (!this.isCursorOwner()) {\n throw new Error(SUPERSEDED_CURSOR_MESSAGE);\n }\n }\n\n getFirstSync(): T | null {\n if (this.isStepCalled) {\n throw new Error(\n 'The SQLite cursor has been shifted and is unable to retrieve the first row without being reset. Invoke `resetSync()` to reset the cursor first if you want to retrieve the first row.'\n );\n }\n const columnNames = this.getColumnNamesSync();\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues != null) {\n return composeRowIfNeeded<T>(this.options.rawResult, columnNames, firstRowValues);\n }\n this.assertCursorOwner();\n const firstRow = this.statement.stepSync(this.database);\n return firstRow != null\n ? composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(firstRow))\n : null;\n }\n\n getAllSync(): T[] {\n if (this.isStepCalled) {\n throw new Error(\n 'The SQLite cursor has been shifted and is unable to retrieve all rows without being reset. Invoke `resetSync()` to reset the cursor first if you want to retrieve all rows.'\n );\n }\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues == null) {\n // If the first row is empty, this SQL query may be a write operation. We should not call `statement.getAllAsync()` to write again.\n return [];\n }\n const columnNames = this.getColumnNamesSync();\n this.assertCursorOwner();\n const nativeRows = this.statement.getAllSync(this.database);\n const allRows = processNativeRows(nativeRows);\n if (firstRowValues != null && firstRowValues.length > 0) {\n return composeRowsIfNeeded<T>(this.options.rawResult, columnNames, [\n firstRowValues,\n ...allRows,\n ]);\n }\n return composeRowsIfNeeded<T>(this.options.rawResult, columnNames, allRows);\n }\n\n *generatorSync(): IterableIterator<T> {\n const columnNames = this.getColumnNamesSync();\n const firstRowValues = this.popFirstRowValues();\n if (firstRowValues != null) {\n yield composeRowIfNeeded<T>(this.options.rawResult, columnNames, firstRowValues);\n }\n let result;\n do {\n this.assertCursorOwner();\n result = this.statement.stepSync(this.database);\n if (result != null) {\n yield composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(result));\n }\n } while (result != null);\n }\n\n resetSync(): void {\n // Resetting a superseded result would rewind the cursor of the run that owns it now.\n this.assertCursorOwner();\n this.statement.resetSync(this.database);\n this.isStepCalled = false;\n }\n\n private popFirstRowValues(): SQLiteColumnValues | null {\n if (this.firstRowValues != null) {\n const firstRowValues = this.firstRowValues;\n this.firstRowValues = null;\n return firstRowValues.length > 0 ? firstRowValues : null;\n }\n return null;\n }\n\n private getColumnNamesSync(): string[] {\n if (this.columnNames == null) {\n this.columnNames = this.statement.getColumnNamesSync();\n }\n return this.columnNames;\n }\n}\n\nfunction composeRowIfNeeded<T>(\n rawResult: boolean,\n columnNames: SQLiteColumnNames,\n columnValues: SQLiteColumnValues\n): T {\n return rawResult\n ? (columnValues as T) // T would be a ValuesOf<> from caller\n : composeRow<T>(columnNames, columnValues);\n}\n\nfunction composeRowsIfNeeded<T>(\n rawResult: boolean,\n columnNames: SQLiteColumnNames,\n columnValuesList: SQLiteColumnValues[]\n): T[] {\n return rawResult\n ? (columnValuesList as T[]) // T[] would be a ValuesOf<>[] from caller\n : composeRows<T>(columnNames, columnValuesList);\n}\n\nfunction processNativeRow(nativeRow: SQLiteColumnValues): SQLiteColumnValues {\n return nativeRow?.map((column) =>\n column instanceof ArrayBuffer ? new Uint8Array(column) : column\n );\n}\n\nfunction processNativeRows(nativeRows: SQLiteColumnValues[]): SQLiteColumnValues[] {\n return nativeRows.map(processNativeRow);\n}\n\n//#endregion\n"]}
@@ -9,7 +9,7 @@
9
9
  "publication": {
10
10
  "groupId": "host.exp.exponent",
11
11
  "artifactId": "expo.modules.sqlite",
12
- "version": "57.0.3",
12
+ "version": "57.0.4",
13
13
  "repository": "local-maven-repo"
14
14
  }
15
15
  },
@@ -428,6 +428,13 @@ public final class SQLiteModule: Module {
428
428
  private func step(statement: NativeStatement, database: NativeDatabase) throws -> SQLiteColumnValues? {
429
429
  try maybeThrowForClosedDatabase(database)
430
430
  try maybeThrowForFinalizedStatement(statement)
431
+
432
+ // Guard the stateful statement, see `run` above.
433
+ statement.lock.wait()
434
+ defer {
435
+ statement.lock.signal()
436
+ }
437
+
431
438
  let ret = exsqlite3_step(statement.pointer)
432
439
  if ret == SQLITE_ROW {
433
440
  return try getColumnValues(statement: statement)
@@ -441,6 +448,13 @@ public final class SQLiteModule: Module {
441
448
  private func getAll(statement: NativeStatement, database: NativeDatabase) throws -> [SQLiteColumnValues] {
442
449
  try maybeThrowForClosedDatabase(database)
443
450
  try maybeThrowForFinalizedStatement(statement)
451
+
452
+ // Guard the stateful statement, see `run` above.
453
+ statement.lock.wait()
454
+ defer {
455
+ statement.lock.signal()
456
+ }
457
+
444
458
  var columnValuesList: [SQLiteColumnValues] = []
445
459
  while true {
446
460
  let ret = exsqlite3_step(statement.pointer)
@@ -459,6 +473,13 @@ public final class SQLiteModule: Module {
459
473
  private func reset(statement: NativeStatement, database: NativeDatabase) throws {
460
474
  try maybeThrowForClosedDatabase(database)
461
475
  try maybeThrowForFinalizedStatement(statement)
476
+
477
+ // Guard the stateful statement, see `run` above.
478
+ statement.lock.wait()
479
+ defer {
480
+ statement.lock.signal()
481
+ }
482
+
462
483
  if exsqlite3_reset(statement.pointer) != SQLITE_OK {
463
484
  throw SQLiteErrorException(convertSqlLiteErrorToString(database))
464
485
  }
@@ -467,6 +488,13 @@ public final class SQLiteModule: Module {
467
488
  private func finalize(statement: NativeStatement, database: NativeDatabase) throws {
468
489
  try maybeThrowForClosedDatabase(database)
469
490
  try maybeThrowForFinalizedStatement(statement)
491
+
492
+ // Guard the stateful statement, see `run` above.
493
+ statement.lock.wait()
494
+ defer {
495
+ statement.lock.signal()
496
+ }
497
+
470
498
  if exsqlite3_finalize(statement.pointer) != SQLITE_OK {
471
499
  throw SQLiteErrorException(convertSqlLiteErrorToString(database))
472
500
  }
@@ -0,0 +1 @@
1
+ 02bdb019cd014cbe43cff391ee53f9eed49ff6c78e425113af3a892390822f29
@@ -0,0 +1 @@
1
+ 37442b363d616ef7fd204893efb02ac15d4829aa5e2a3fe91be4b3cb17d9826f1d0abfdc9b3017b7618dfd85aa8156c234f39bc3ac7abd676072783d25e93125
@@ -0,0 +1 @@
1
+ fafd65cc002c5173fe1935d4db3a860f7fb248e1252a18cd45374fd951183125
@@ -0,0 +1 @@
1
+ 9125c2a3ff328bf8a1491d7e235a9b77e842b01ff3b02013eba7769fcca0f486a3d56e08da83757b9ea429667fca726d92de122440b2b0e9df1d9711a379bab9
@@ -3,7 +3,7 @@
3
3
  "component": {
4
4
  "group": "host.exp.exponent",
5
5
  "module": "expo.modules.sqlite",
6
- "version": "57.0.3",
6
+ "version": "57.0.4",
7
7
  "attributes": {
8
8
  "org.gradle.status": "release"
9
9
  }
@@ -24,13 +24,13 @@
24
24
  },
25
25
  "files": [
26
26
  {
27
- "name": "expo.modules.sqlite-57.0.3.aar",
28
- "url": "expo.modules.sqlite-57.0.3.aar",
29
- "size": 3823160,
30
- "sha512": "97b9f3c849ecda169a14bd40502d11b42a7db55e98a1ac3a33391a720bdac4748fd4e7fe190c1ab77c37aada7d932f7b587efa141949d4f4f281959e5e1a2475",
31
- "sha256": "df1da5f5381b01deb84c69e946436e98f69fb7a3c3f55c03b01e88061fd88e4d",
32
- "sha1": "87f1f42b8d635fff98edf78cf7a123628dc369e0",
33
- "md5": "89190f5fa83aadb89346c061f9cb6c34"
27
+ "name": "expo.modules.sqlite-57.0.4.aar",
28
+ "url": "expo.modules.sqlite-57.0.4.aar",
29
+ "size": 3823428,
30
+ "sha512": "9125c2a3ff328bf8a1491d7e235a9b77e842b01ff3b02013eba7769fcca0f486a3d56e08da83757b9ea429667fca726d92de122440b2b0e9df1d9711a379bab9",
31
+ "sha256": "fafd65cc002c5173fe1935d4db3a860f7fb248e1252a18cd45374fd951183125",
32
+ "sha1": "7324fa7559653d19ad9e9997f8e9bf98308e805c",
33
+ "md5": "8a8943ce1632fc9989a6d5276e673c06"
34
34
  }
35
35
  ]
36
36
  },
@@ -67,13 +67,13 @@
67
67
  ],
68
68
  "files": [
69
69
  {
70
- "name": "expo.modules.sqlite-57.0.3.aar",
71
- "url": "expo.modules.sqlite-57.0.3.aar",
72
- "size": 3823160,
73
- "sha512": "97b9f3c849ecda169a14bd40502d11b42a7db55e98a1ac3a33391a720bdac4748fd4e7fe190c1ab77c37aada7d932f7b587efa141949d4f4f281959e5e1a2475",
74
- "sha256": "df1da5f5381b01deb84c69e946436e98f69fb7a3c3f55c03b01e88061fd88e4d",
75
- "sha1": "87f1f42b8d635fff98edf78cf7a123628dc369e0",
76
- "md5": "89190f5fa83aadb89346c061f9cb6c34"
70
+ "name": "expo.modules.sqlite-57.0.4.aar",
71
+ "url": "expo.modules.sqlite-57.0.4.aar",
72
+ "size": 3823428,
73
+ "sha512": "9125c2a3ff328bf8a1491d7e235a9b77e842b01ff3b02013eba7769fcca0f486a3d56e08da83757b9ea429667fca726d92de122440b2b0e9df1d9711a379bab9",
74
+ "sha256": "fafd65cc002c5173fe1935d4db3a860f7fb248e1252a18cd45374fd951183125",
75
+ "sha1": "7324fa7559653d19ad9e9997f8e9bf98308e805c",
76
+ "md5": "8a8943ce1632fc9989a6d5276e673c06"
77
77
  }
78
78
  ]
79
79
  },
@@ -87,13 +87,13 @@
87
87
  },
88
88
  "files": [
89
89
  {
90
- "name": "expo.modules.sqlite-57.0.3-sources.jar",
91
- "url": "expo.modules.sqlite-57.0.3-sources.jar",
92
- "size": 11551,
93
- "sha512": "3b63d91aadb7a09514fc8fb158bb08caf92b6108cbc0876893b1a7a3fd33c1a4934c3b7912a858404f0a0eac7b854572fa90c90b8c93b9b52bde2204dcdab735",
94
- "sha256": "b8f668275e3ec93cff367011da2b3ae7bd83f43a690ce56473395ba6284c8b7c",
95
- "sha1": "7c0a8d8193faac646dccacbe00982974ffb4f488",
96
- "md5": "9b900a345245e67770016ae8154b63e1"
90
+ "name": "expo.modules.sqlite-57.0.4-sources.jar",
91
+ "url": "expo.modules.sqlite-57.0.4-sources.jar",
92
+ "size": 11596,
93
+ "sha512": "37442b363d616ef7fd204893efb02ac15d4829aa5e2a3fe91be4b3cb17d9826f1d0abfdc9b3017b7618dfd85aa8156c234f39bc3ac7abd676072783d25e93125",
94
+ "sha256": "02bdb019cd014cbe43cff391ee53f9eed49ff6c78e425113af3a892390822f29",
95
+ "sha1": "c386518214d8885ee76a3a74d1fe9f1d3b4cbd26",
96
+ "md5": "2a2a61f4c3d0acedc5a7bcb4b9e57d6b"
97
97
  }
98
98
  ]
99
99
  }
@@ -0,0 +1 @@
1
+ 32006cd7b6db719b0d1128927fb263d3fd32c3603ba2d693d136f8164c28d396
@@ -0,0 +1 @@
1
+ 50966a95d994aa5fd02e79b140949ad4b67107454db1ee207f18e4ee3d3834c9ffadef7e4dc388bcbd926e8471118f1acb55f17d5ecbdb5f84d8171bf4f79c17
@@ -9,7 +9,7 @@
9
9
  <modelVersion>4.0.0</modelVersion>
10
10
  <groupId>host.exp.exponent</groupId>
11
11
  <artifactId>expo.modules.sqlite</artifactId>
12
- <version>57.0.3</version>
12
+ <version>57.0.4</version>
13
13
  <packaging>aar</packaging>
14
14
  <name>expo.modules.sqlite</name>
15
15
  <url>https://github.com/expo/expo</url>
@@ -0,0 +1 @@
1
+ 62d81beab910b4ef587a515c384b64afe2ad0be9dbe55dd2a0104cd0b053f4cc
@@ -0,0 +1 @@
1
+ c27968915e38ad2bb3a17d96c0fd73d651a4153d72b41b1f728836ec1d31460db2a5181c61301cf812f17c7af1fe0e3fd8bebb6ac3c4b37754b297e2522eb175
@@ -3,11 +3,11 @@
3
3
  <groupId>host.exp.exponent</groupId>
4
4
  <artifactId>expo.modules.sqlite</artifactId>
5
5
  <versioning>
6
- <latest>57.0.3</latest>
7
- <release>57.0.3</release>
6
+ <latest>57.0.4</latest>
7
+ <release>57.0.4</release>
8
8
  <versions>
9
- <version>57.0.3</version>
9
+ <version>57.0.4</version>
10
10
  </versions>
11
- <lastUpdated>20260911111657</lastUpdated>
11
+ <lastUpdated>20261006120125</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- 5cb9dfd764cd0e869f7e386f6b7ce0bc
1
+ d4a2192c71378c23486cb4d637c45b26
@@ -1 +1 @@
1
- 19c3594316a37dc3e9d0fde3db4d68b1b0d89ce1
1
+ 6385eb786defeadab4c7efc41b425bd8940c4162
@@ -1 +1 @@
1
- 72bc2d458f5ca000bc7e23bc0e303d45be74b3aa47ad0dcd01d929d54776fee3
1
+ 14c9e125a492e31b4f9e6767f02b6cac50a969754bf68978c7ad7bc6dff7cd23
@@ -1 +1 @@
1
- 80b8bd1ab7324b519d09d3393ad25884eb047741ff2f25c6a53caed51827e8301f9ec4e8e4e8d713ac05e80fa0adc64383c8d7302994bc34e9c3be39d7e29dab
1
+ d5d1d62ea565ab63307ca35a0dd0c23d5a5a332214ed02980dbb236d81be9f108e200b6d0214123236de38591f0c26f6cb5cee17362230aa83f71643810336e9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-sqlite",
3
- "version": "57.0.3",
3
+ "version": "57.0.4",
4
4
  "description": "Provides access to a database using SQLite (https://www.sqlite.org/). The database is persisted across restarts of your app.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -55,15 +55,15 @@
55
55
  "@types/react": "~19.2.0",
56
56
  "better-sqlite3": "^11.6.0",
57
57
  "react-error-boundary": "^4.0.11",
58
- "expo": "57.0.22",
59
- "expo-module-scripts": "56.0.3"
58
+ "expo-module-scripts": "56.0.3",
59
+ "expo": "57.0.27"
60
60
  },
61
61
  "peerDependencies": {
62
62
  "expo": "*",
63
63
  "react": "*",
64
64
  "react-native": "*"
65
65
  },
66
- "gitHead": "9e5319c0f821a27b7924841903abae50e2b41790",
66
+ "gitHead": "50ac74f1ab5682c8e32b24da6e5e97dd4dbbb80f",
67
67
  "scripts": {
68
68
  "build": "expo-module build",
69
69
  "bundle:webui": "pushd dev-plugin-webui && bun run build && popd && rm -rf dev-plugin-dist && mv dev-plugin-webui/dist dev-plugin-dist",
@@ -22,11 +22,27 @@ type ValuesOf<T extends object> = T[keyof T][];
22
22
  * A prepared statement returned by [`SQLiteDatabase.prepareAsync()`](#prepareasyncsource) or [`SQLiteDatabase.prepareSync()`](#preparesyncsource) that can be binded with parameters and executed.
23
23
  */
24
24
  export class SQLiteStatement {
25
+ /**
26
+ * The cursor that currently owns the underlying `sqlite3_stmt`. A prepared statement has exactly
27
+ * one cursor, so running the statement again invalidates the cursor of every earlier run.
28
+ */
29
+ private currentCursor: object | null = null;
30
+
25
31
  constructor(
26
32
  private readonly nativeDatabase: NativeDatabase,
27
33
  private readonly nativeStatement: NativeStatement
28
34
  ) {}
29
35
 
36
+ /**
37
+ * Make the run that just finished the owner of the statement cursor, and return a predicate
38
+ * that tells whether it still is.
39
+ */
40
+ private claimCursor(): () => boolean {
41
+ const cursor = {};
42
+ this.currentCursor = cursor;
43
+ return () => this.currentCursor === cursor;
44
+ }
45
+
30
46
  //#region Asynchronous API
31
47
 
32
48
  /**
@@ -51,7 +67,8 @@ export class SQLiteStatement {
51
67
  rawResult: false,
52
68
  lastInsertRowId,
53
69
  changes,
54
- }
70
+ },
71
+ this.claimCursor()
55
72
  );
56
73
  }
57
74
 
@@ -83,7 +100,8 @@ export class SQLiteStatement {
83
100
  rawResult: true,
84
101
  lastInsertRowId,
85
102
  changes,
86
- }
103
+ },
104
+ this.claimCursor()
87
105
  );
88
106
  }
89
107
 
@@ -133,7 +151,8 @@ export class SQLiteStatement {
133
151
  rawResult: false,
134
152
  lastInsertRowId,
135
153
  changes,
136
- }
154
+ },
155
+ this.claimCursor()
137
156
  );
138
157
  }
139
158
 
@@ -165,7 +184,8 @@ export class SQLiteStatement {
165
184
  rawResult: true,
166
185
  lastInsertRowId,
167
186
  changes,
168
- }
187
+ },
188
+ this.claimCursor()
169
189
  );
170
190
  }
171
191
 
@@ -347,6 +367,12 @@ interface SQLiteExecuteResultOptions {
347
367
  changes: number;
348
368
  }
349
369
 
370
+ const SUPERSEDED_CURSOR_MESSAGE =
371
+ 'This result is no longer readable because the prepared statement ran again. ' +
372
+ 'A prepared statement holds a single SQLite cursor, so a later run rebinds the parameters and moves that cursor, ' +
373
+ 'and this result would return the rows of the later run. ' +
374
+ 'Read a result to the end before you run the same statement again, or prepare a separate statement for each reader.';
375
+
350
376
  /**
351
377
  * Create the `SQLiteExecuteAsyncResult` instance.
352
378
  *
@@ -357,13 +383,15 @@ async function createSQLiteExecuteAsyncResult<T>(
357
383
  database: SQLiteAnyDatabase,
358
384
  statement: NativeStatement,
359
385
  firstRowValues: SQLiteColumnValues | null,
360
- options: SQLiteExecuteResultOptions
386
+ options: SQLiteExecuteResultOptions,
387
+ isCursorOwner: () => boolean
361
388
  ): Promise<SQLiteExecuteAsyncResult<T>> {
362
389
  const instance = new SQLiteExecuteAsyncResultImpl<T>(
363
390
  database,
364
391
  statement,
365
392
  firstRowValues ? processNativeRow(firstRowValues) : null,
366
- options
393
+ options,
394
+ isCursorOwner
367
395
  );
368
396
  const generator = instance.generatorAsync();
369
397
  Object.defineProperties(generator, {
@@ -404,13 +432,15 @@ function createSQLiteExecuteSyncResult<T>(
404
432
  database: SQLiteAnyDatabase,
405
433
  statement: NativeStatement,
406
434
  firstRowValues: SQLiteColumnValues | null,
407
- options: SQLiteExecuteResultOptions
435
+ options: SQLiteExecuteResultOptions,
436
+ isCursorOwner: () => boolean
408
437
  ): SQLiteExecuteSyncResult<T> {
409
438
  const instance = new SQLiteExecuteSyncResultImpl<T>(
410
439
  database,
411
440
  statement,
412
441
  firstRowValues ? processNativeRow(firstRowValues) : firstRowValues,
413
- options
442
+ options,
443
+ isCursorOwner
414
444
  );
415
445
  const generator = instance.generatorSync();
416
446
  Object.defineProperties(generator, {
@@ -452,9 +482,17 @@ class SQLiteExecuteAsyncResultImpl<T> {
452
482
  private readonly database: SQLiteAnyDatabase,
453
483
  private readonly statement: NativeStatement,
454
484
  private firstRowValues: SQLiteColumnValues | null,
455
- public readonly options: SQLiteExecuteResultOptions
485
+ public readonly options: SQLiteExecuteResultOptions,
486
+ private readonly isCursorOwner: () => boolean
456
487
  ) {}
457
488
 
489
+ /** Throw rather than step a cursor that a later run of the same statement has taken over. */
490
+ private assertCursorOwner() {
491
+ if (!this.isCursorOwner()) {
492
+ throw new Error(SUPERSEDED_CURSOR_MESSAGE);
493
+ }
494
+ }
495
+
458
496
  async getFirstAsync(): Promise<T | null> {
459
497
  if (this.isStepCalled) {
460
498
  throw new Error(
@@ -467,6 +505,7 @@ class SQLiteExecuteAsyncResultImpl<T> {
467
505
  if (firstRowValues != null) {
468
506
  return composeRowIfNeeded<T>(this.options.rawResult, columnNames, firstRowValues);
469
507
  }
508
+ this.assertCursorOwner();
470
509
  const firstRow = await this.statement.stepAsync(this.database);
471
510
  return firstRow != null
472
511
  ? composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(firstRow))
@@ -486,9 +525,10 @@ class SQLiteExecuteAsyncResultImpl<T> {
486
525
  return [];
487
526
  }
488
527
  const columnNames = await this.getColumnNamesAsync();
528
+ this.assertCursorOwner();
489
529
  const nativeRows = await this.statement.getAllAsync(this.database);
490
530
  const allRows = processNativeRows(nativeRows);
491
- if (firstRowValues != null && firstRowValues.length > 0) {
531
+ if (firstRowValues.length > 0) {
492
532
  return composeRowsIfNeeded<T>(this.options.rawResult, columnNames, [
493
533
  firstRowValues,
494
534
  ...allRows,
@@ -507,6 +547,7 @@ class SQLiteExecuteAsyncResultImpl<T> {
507
547
 
508
548
  let result;
509
549
  do {
550
+ this.assertCursorOwner();
510
551
  result = await this.statement.stepAsync(this.database);
511
552
  if (result != null) {
512
553
  yield composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(result));
@@ -514,10 +555,11 @@ class SQLiteExecuteAsyncResultImpl<T> {
514
555
  } while (result != null);
515
556
  }
516
557
 
517
- resetAsync(): Promise<void> {
518
- const result = this.statement.resetAsync(this.database);
558
+ async resetAsync(): Promise<void> {
559
+ // Resetting a superseded result would rewind the cursor of the run that owns it now.
560
+ this.assertCursorOwner();
561
+ await this.statement.resetAsync(this.database);
519
562
  this.isStepCalled = false;
520
- return result;
521
563
  }
522
564
 
523
565
  private popFirstRowValues(): SQLiteColumnValues | null {
@@ -545,9 +587,17 @@ class SQLiteExecuteSyncResultImpl<T> {
545
587
  private readonly database: SQLiteAnyDatabase,
546
588
  private readonly statement: NativeStatement,
547
589
  private firstRowValues: SQLiteColumnValues | null,
548
- public readonly options: SQLiteExecuteResultOptions
590
+ public readonly options: SQLiteExecuteResultOptions,
591
+ private readonly isCursorOwner: () => boolean
549
592
  ) {}
550
593
 
594
+ /** Throw rather than step a cursor that a later run of the same statement has taken over. */
595
+ private assertCursorOwner() {
596
+ if (!this.isCursorOwner()) {
597
+ throw new Error(SUPERSEDED_CURSOR_MESSAGE);
598
+ }
599
+ }
600
+
551
601
  getFirstSync(): T | null {
552
602
  if (this.isStepCalled) {
553
603
  throw new Error(
@@ -559,6 +609,7 @@ class SQLiteExecuteSyncResultImpl<T> {
559
609
  if (firstRowValues != null) {
560
610
  return composeRowIfNeeded<T>(this.options.rawResult, columnNames, firstRowValues);
561
611
  }
612
+ this.assertCursorOwner();
562
613
  const firstRow = this.statement.stepSync(this.database);
563
614
  return firstRow != null
564
615
  ? composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(firstRow))
@@ -577,6 +628,7 @@ class SQLiteExecuteSyncResultImpl<T> {
577
628
  return [];
578
629
  }
579
630
  const columnNames = this.getColumnNamesSync();
631
+ this.assertCursorOwner();
580
632
  const nativeRows = this.statement.getAllSync(this.database);
581
633
  const allRows = processNativeRows(nativeRows);
582
634
  if (firstRowValues != null && firstRowValues.length > 0) {
@@ -596,6 +648,7 @@ class SQLiteExecuteSyncResultImpl<T> {
596
648
  }
597
649
  let result;
598
650
  do {
651
+ this.assertCursorOwner();
599
652
  result = this.statement.stepSync(this.database);
600
653
  if (result != null) {
601
654
  yield composeRowIfNeeded<T>(this.options.rawResult, columnNames, processNativeRow(result));
@@ -604,9 +657,10 @@ class SQLiteExecuteSyncResultImpl<T> {
604
657
  }
605
658
 
606
659
  resetSync(): void {
607
- const result = this.statement.resetSync(this.database);
660
+ // Resetting a superseded result would rewind the cursor of the run that owns it now.
661
+ this.assertCursorOwner();
662
+ this.statement.resetSync(this.database);
608
663
  this.isStepCalled = false;
609
- return result;
610
664
  }
611
665
 
612
666
  private popFirstRowValues(): SQLiteColumnValues | null {
@@ -1 +0,0 @@
1
- b8f668275e3ec93cff367011da2b3ae7bd83f43a690ce56473395ba6284c8b7c
@@ -1 +0,0 @@
1
- 3b63d91aadb7a09514fc8fb158bb08caf92b6108cbc0876893b1a7a3fd33c1a4934c3b7912a858404f0a0eac7b854572fa90c90b8c93b9b52bde2204dcdab735
@@ -1 +0,0 @@
1
- 87f1f42b8d635fff98edf78cf7a123628dc369e0
@@ -1 +0,0 @@
1
- df1da5f5381b01deb84c69e946436e98f69fb7a3c3f55c03b01e88061fd88e4d
@@ -1 +0,0 @@
1
- 97b9f3c849ecda169a14bd40502d11b42a7db55e98a1ac3a33391a720bdac4748fd4e7fe190c1ab77c37aada7d932f7b587efa141949d4f4f281959e5e1a2475
@@ -1 +0,0 @@
1
- ee3f075f3c6a0fd48956f50476ba6b9b2c53dfe35b19cce7f8e1976a1edb57a7
@@ -1 +0,0 @@
1
- 7072e77137d8d04d74c12cc050c55aad54854784349d7810b257b6cf8ea13dc94c885edd53532403ffa546d5f0d65623bb42340f7466e6f9b0442c6cc1b01d3a
@@ -1 +0,0 @@
1
- 2d42be1f6cf0cb586196d93f920c8c780f4635d9
@@ -1 +0,0 @@
1
- 3af19f382afed8dd75aec53c44bf8e83edc810d919cb7603b9c70e055314bf85
@@ -1 +0,0 @@
1
- 2ad35fe02f25b6a226941470aa67c2027318609b7ec156d61d77837bbdc8811de072fd24692a4577419b2fb1350e23377e031f82b9c835202b42ef14da542ca4