react-native-nitro-sqlite 9.8.1 → 10.0.0
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.
- package/RNNitroSQLite.podspec +7 -3
- package/android/CMakeLists.txt +3 -2
- package/android/build.gradle +2 -0
- package/android/sqlite-flags.gradle +47 -0
- package/cpp/NitroSQLiteDatabaseConnections.cpp +306 -0
- package/cpp/NitroSQLiteDatabaseConnections.hpp +86 -0
- package/cpp/{databaseMigration.cpp → NitroSQLiteDatabaseMigration.cpp} +2 -2
- package/cpp/{sqliteExecuteBatch.cpp → NitroSQLiteExecuteBatch.cpp} +4 -4
- package/cpp/{sqliteExecuteBatch.hpp → NitroSQLiteExecuteBatch.hpp} +3 -6
- package/cpp/{importSqlFile.cpp → NitroSQLiteImportSqlFile.cpp} +4 -4
- package/cpp/{importSqlFile.hpp → NitroSQLiteImportSqlFile.hpp} +3 -3
- package/cpp/{macros.hpp → NitroSQLiteMacros.hpp} +3 -3
- package/cpp/NitroSQLiteOperations.cpp +396 -0
- package/cpp/NitroSQLiteOperations.hpp +72 -0
- package/cpp/{types.hpp → NitroSQLiteTypes.hpp} +3 -6
- package/cpp/{utils.hpp → NitroSQLiteUtils.hpp} +2 -2
- package/cpp/hybridObjects/HybridNitroSQLite.cpp +108 -22
- package/cpp/hybridObjects/HybridNitroSQLite.hpp +49 -5
- package/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.cpp +59 -0
- package/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.hpp +33 -0
- package/cpp/hybridObjects/HybridNitroSQLiteQueryResult.hpp +6 -4
- package/ios/OnLoad.mm +38 -2
- package/lib/commonjs/DatabaseQueue.js +52 -16
- package/lib/commonjs/DatabaseQueue.js.map +1 -1
- package/lib/commonjs/NitroSQLiteError.js +6 -7
- package/lib/commonjs/NitroSQLiteError.js.map +1 -1
- package/lib/commonjs/OnLoad.js +1 -1
- package/lib/commonjs/index.js +8 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/operations/execute.js +19 -4
- package/lib/commonjs/operations/execute.js.map +1 -1
- package/lib/commonjs/operations/executeBatch.js +19 -6
- package/lib/commonjs/operations/executeBatch.js.map +1 -1
- package/lib/commonjs/operations/prepare.js +54 -0
- package/lib/commonjs/operations/prepare.js.map +1 -0
- package/lib/commonjs/operations/session.js +106 -30
- package/lib/commonjs/operations/session.js.map +1 -1
- package/lib/commonjs/operations/transaction.js +30 -5
- package/lib/commonjs/operations/transaction.js.map +1 -1
- package/lib/commonjs/specs/NitroSQLitePreparedStatement.nitro.js +6 -0
- package/lib/commonjs/specs/NitroSQLitePreparedStatement.nitro.js.map +1 -0
- package/lib/commonjs/typeORM.js +10 -3
- package/lib/commonjs/typeORM.js.map +1 -1
- package/lib/commonjs/types.js +35 -9
- package/lib/commonjs/types.js.map +1 -1
- package/lib/module/DatabaseQueue.js +52 -16
- package/lib/module/DatabaseQueue.js.map +1 -1
- package/lib/module/NitroSQLiteError.js +6 -7
- package/lib/module/NitroSQLiteError.js.map +1 -1
- package/lib/module/OnLoad.js +1 -1
- package/lib/module/index.js +8 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/operations/execute.js +20 -5
- package/lib/module/operations/execute.js.map +1 -1
- package/lib/module/operations/executeBatch.js +20 -7
- package/lib/module/operations/executeBatch.js.map +1 -1
- package/lib/module/operations/prepare.js +49 -0
- package/lib/module/operations/prepare.js.map +1 -0
- package/lib/module/operations/session.js +107 -31
- package/lib/module/operations/session.js.map +1 -1
- package/lib/module/operations/transaction.js +30 -5
- package/lib/module/operations/transaction.js.map +1 -1
- package/lib/module/specs/NitroSQLitePreparedStatement.nitro.js +4 -0
- package/lib/module/specs/NitroSQLitePreparedStatement.nitro.js.map +1 -0
- package/lib/module/typeORM.js +11 -3
- package/lib/module/typeORM.js.map +1 -1
- package/lib/module/types.js +48 -9
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/commonjs/DatabaseQueue.d.ts +15 -7
- package/lib/typescript/commonjs/DatabaseQueue.d.ts.map +1 -1
- package/lib/typescript/commonjs/NitroSQLiteError.d.ts +6 -7
- package/lib/typescript/commonjs/NitroSQLiteError.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +9 -2
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/operations/execute.d.ts +17 -2
- package/lib/typescript/commonjs/operations/execute.d.ts.map +1 -1
- package/lib/typescript/commonjs/operations/executeBatch.d.ts +15 -2
- package/lib/typescript/commonjs/operations/executeBatch.d.ts.map +1 -1
- package/lib/typescript/commonjs/operations/prepare.d.ts +13 -0
- package/lib/typescript/commonjs/operations/prepare.d.ts.map +1 -0
- package/lib/typescript/commonjs/operations/session.d.ts +8 -0
- package/lib/typescript/commonjs/operations/session.d.ts.map +1 -1
- package/lib/typescript/commonjs/operations/transaction.d.ts +11 -1
- package/lib/typescript/commonjs/operations/transaction.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NitroSQLite.nitro.d.ts +83 -2
- package/lib/typescript/commonjs/specs/NitroSQLite.nitro.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NitroSQLitePreparedStatement.nitro.d.ts +26 -0
- package/lib/typescript/commonjs/specs/NitroSQLitePreparedStatement.nitro.d.ts.map +1 -0
- package/lib/typescript/commonjs/specs/NitroSQLiteQueryResult.nitro.d.ts +9 -15
- package/lib/typescript/commonjs/specs/NitroSQLiteQueryResult.nitro.d.ts.map +1 -1
- package/lib/typescript/commonjs/typeORM.d.ts +14 -3
- package/lib/typescript/commonjs/typeORM.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts +124 -21
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/module/DatabaseQueue.d.ts +15 -7
- package/lib/typescript/module/DatabaseQueue.d.ts.map +1 -1
- package/lib/typescript/module/NitroSQLiteError.d.ts +6 -7
- package/lib/typescript/module/NitroSQLiteError.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +9 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/operations/execute.d.ts +17 -2
- package/lib/typescript/module/operations/execute.d.ts.map +1 -1
- package/lib/typescript/module/operations/executeBatch.d.ts +15 -2
- package/lib/typescript/module/operations/executeBatch.d.ts.map +1 -1
- package/lib/typescript/module/operations/prepare.d.ts +13 -0
- package/lib/typescript/module/operations/prepare.d.ts.map +1 -0
- package/lib/typescript/module/operations/session.d.ts +8 -0
- package/lib/typescript/module/operations/session.d.ts.map +1 -1
- package/lib/typescript/module/operations/transaction.d.ts +11 -1
- package/lib/typescript/module/operations/transaction.d.ts.map +1 -1
- package/lib/typescript/module/specs/NitroSQLite.nitro.d.ts +83 -2
- package/lib/typescript/module/specs/NitroSQLite.nitro.d.ts.map +1 -1
- package/lib/typescript/module/specs/NitroSQLitePreparedStatement.nitro.d.ts +26 -0
- package/lib/typescript/module/specs/NitroSQLitePreparedStatement.nitro.d.ts.map +1 -0
- package/lib/typescript/module/specs/NitroSQLiteQueryResult.nitro.d.ts +9 -15
- package/lib/typescript/module/specs/NitroSQLiteQueryResult.nitro.d.ts.map +1 -1
- package/lib/typescript/module/typeORM.d.ts +14 -3
- package/lib/typescript/module/typeORM.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts +124 -21
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake +1 -0
- package/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.hpp +73 -0
- package/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.cpp +3 -0
- package/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.hpp +8 -2
- package/package.json +4 -2
- package/src/DatabaseQueue.ts +81 -25
- package/src/NitroSQLiteError.ts +6 -7
- package/src/OnLoad.ts +1 -1
- package/src/index.ts +7 -3
- package/src/operations/execute.ts +22 -3
- package/src/operations/executeBatch.ts +20 -5
- package/src/operations/prepare.ts +69 -0
- package/src/operations/session.ts +136 -45
- package/src/operations/transaction.ts +37 -4
- package/src/specs/NitroSQLite.nitro.ts +84 -2
- package/src/specs/NitroSQLitePreparedStatement.nitro.ts +28 -0
- package/src/specs/NitroSQLiteQueryResult.nitro.ts +9 -15
- package/src/typeORM.ts +14 -3
- package/src/types.ts +135 -21
- package/cpp/operations.cpp +0 -358
- package/cpp/operations.hpp +0 -56
- /package/android/{cpp-adapter.cpp → RNNitroSQLiteAdapter.cpp} +0 -0
- /package/cpp/{databaseMigration.hpp → NitroSQLiteDatabaseMigration.hpp} +0 -0
- /package/cpp/{logs.hpp → NitroSQLiteLogs.hpp} +0 -0
|
@@ -11,95 +11,186 @@ import type {
|
|
|
11
11
|
} from '../types'
|
|
12
12
|
import { executeAsyncManaged, executeManaged } from './execute'
|
|
13
13
|
import { executeBatch, executeBatchAsync } from './executeBatch'
|
|
14
|
+
import { prepare } from './prepare'
|
|
14
15
|
import NitroSQLiteError from '../NitroSQLiteError'
|
|
15
16
|
import {
|
|
16
17
|
closeDatabaseQueue,
|
|
18
|
+
getDatabaseQueue,
|
|
17
19
|
isDatabaseOpen,
|
|
18
20
|
openDatabaseQueue,
|
|
19
|
-
|
|
21
|
+
queueStatementAsync,
|
|
20
22
|
startOperationSync,
|
|
21
23
|
} from '../DatabaseQueue'
|
|
24
|
+
import type { DatabaseQueueKey } from '../DatabaseQueue'
|
|
22
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Open a database and return a managed connection. The default connection is
|
|
28
|
+
* addressed by its name, and opening it twice throws. Set `connection` to
|
|
29
|
+
* `'independent'` to open another native handle to the same file. Async calls
|
|
30
|
+
* on each connection run in call order.
|
|
31
|
+
* @param options Database name, optional directory, connection mode, and read-only setting.
|
|
32
|
+
* @returns A connection bound to the opened native handle.
|
|
33
|
+
*/
|
|
23
34
|
export function open(
|
|
24
35
|
options: NitroSQLiteConnectionOptions,
|
|
25
36
|
): NitroSQLiteConnection {
|
|
26
|
-
|
|
37
|
+
const { name, location: databaseLocation, connection, readOnly } = options
|
|
38
|
+
const { connectionId, queueKey } = openNativeConnection(options)
|
|
39
|
+
const connectionQueue = getDatabaseQueue(queueKey)
|
|
27
40
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
const assertCurrentConnection = () => {
|
|
42
|
+
if (
|
|
43
|
+
!isDatabaseOpen(queueKey) ||
|
|
44
|
+
getDatabaseQueue(queueKey) !== connectionQueue
|
|
45
|
+
) {
|
|
46
|
+
throw new NitroSQLiteError(
|
|
47
|
+
`Database ${name} is not open. There is no connection to the database.`,
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const assertNoReplacement = () => {
|
|
53
|
+
if (
|
|
54
|
+
isDatabaseOpen(queueKey) &&
|
|
55
|
+
getDatabaseQueue(queueKey) !== connectionQueue
|
|
56
|
+
) {
|
|
57
|
+
throw new NitroSQLiteError(
|
|
58
|
+
`Database ${name} has been reopened with another connection.`,
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const runSyncOperation = <Result>(callback: () => Result): Result => {
|
|
64
|
+
try {
|
|
65
|
+
assertCurrentConnection()
|
|
66
|
+
return startOperationSync(queueKey, callback)
|
|
67
|
+
} catch (error) {
|
|
68
|
+
throw NitroSQLiteError.fromError(error)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const runOperation = <Result>(callback: () => Result): Result => {
|
|
73
|
+
assertCurrentConnection()
|
|
74
|
+
return callback()
|
|
33
75
|
}
|
|
34
76
|
|
|
35
77
|
return {
|
|
36
78
|
close: () => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
HybridNitroSQLite.close(options.name),
|
|
40
|
-
)
|
|
41
|
-
closeDatabaseQueue(options.name)
|
|
42
|
-
} catch (error) {
|
|
43
|
-
throw NitroSQLiteError.fromError(error)
|
|
44
|
-
}
|
|
79
|
+
runSyncOperation(() => HybridNitroSQLite.close(connectionId))
|
|
80
|
+
closeDatabaseQueue(queueKey)
|
|
45
81
|
},
|
|
46
82
|
delete: () => {
|
|
83
|
+
if (readOnly) {
|
|
84
|
+
throw new NitroSQLiteError(`Cannot delete read-only database ${name}.`)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let dropFailed = false
|
|
47
88
|
try {
|
|
48
|
-
|
|
49
|
-
|
|
89
|
+
assertNoReplacement()
|
|
90
|
+
const drop = () => {
|
|
91
|
+
try {
|
|
92
|
+
if (connection === 'independent') {
|
|
93
|
+
HybridNitroSQLite.drop(name, databaseLocation, connectionId)
|
|
94
|
+
} else {
|
|
95
|
+
HybridNitroSQLite.drop(name, databaseLocation)
|
|
96
|
+
}
|
|
97
|
+
} catch (error) {
|
|
98
|
+
dropFailed = true
|
|
99
|
+
throw error
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (!isDatabaseOpen(queueKey)) {
|
|
104
|
+
drop()
|
|
50
105
|
return
|
|
51
106
|
}
|
|
52
107
|
|
|
53
|
-
startOperationSync(
|
|
54
|
-
|
|
55
|
-
)
|
|
56
|
-
closeDatabaseQueue(options.name)
|
|
108
|
+
startOperationSync(queueKey, drop)
|
|
109
|
+
closeDatabaseQueue(queueKey)
|
|
57
110
|
} catch (error) {
|
|
111
|
+
if (
|
|
112
|
+
dropFailed &&
|
|
113
|
+
isDatabaseOpen(queueKey) &&
|
|
114
|
+
getDatabaseQueue(queueKey) === connectionQueue &&
|
|
115
|
+
!HybridNitroSQLite.isConnectionOpen(connectionId)
|
|
116
|
+
) {
|
|
117
|
+
closeDatabaseQueue(queueKey)
|
|
118
|
+
}
|
|
58
119
|
throw NitroSQLiteError.fromError(error)
|
|
59
120
|
}
|
|
60
121
|
},
|
|
61
122
|
attach: (dbNameToAttach: string, alias: string, location?: string) =>
|
|
62
|
-
runSyncOperation(
|
|
63
|
-
HybridNitroSQLite.attach(
|
|
123
|
+
runSyncOperation(() =>
|
|
124
|
+
HybridNitroSQLite.attach(connectionId, dbNameToAttach, alias, location),
|
|
64
125
|
),
|
|
65
126
|
detach: (alias: string) =>
|
|
66
|
-
runSyncOperation(
|
|
67
|
-
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
transaction(options.name, fn),
|
|
127
|
+
runSyncOperation(() => HybridNitroSQLite.detach(connectionId, alias)),
|
|
128
|
+
transaction: async <Result = void>(
|
|
129
|
+
fn: (tx: Transaction) => Promise<Result>,
|
|
130
|
+
) => runOperation(() => transaction(connectionId, fn, false, queueKey)),
|
|
71
131
|
execute: <Row extends QueryResultRow = never>(
|
|
72
132
|
query: string,
|
|
73
133
|
params?: SQLiteQueryParams,
|
|
74
|
-
): QueryResult<Row> =>
|
|
75
|
-
|
|
134
|
+
): QueryResult<Row> =>
|
|
135
|
+
runOperation(() => executeManaged(connectionId, query, params, queueKey)),
|
|
136
|
+
executeAsync: async <Row extends QueryResultRow = never>(
|
|
76
137
|
query: string,
|
|
77
138
|
params?: SQLiteQueryParams,
|
|
78
139
|
): Promise<QueryResult<Row>> =>
|
|
79
|
-
|
|
140
|
+
runOperation(() =>
|
|
141
|
+
executeAsyncManaged(connectionId, query, params, queueKey),
|
|
142
|
+
),
|
|
143
|
+
prepare: (query: string) =>
|
|
144
|
+
runOperation(() => prepare(connectionId, query, queueKey)),
|
|
80
145
|
executeBatch: (commands: BatchQueryCommand[]) =>
|
|
81
|
-
executeBatch(
|
|
82
|
-
executeBatchAsync: (commands: BatchQueryCommand[]) =>
|
|
83
|
-
executeBatchAsync(
|
|
146
|
+
runOperation(() => executeBatch(connectionId, commands, queueKey)),
|
|
147
|
+
executeBatchAsync: async (commands: BatchQueryCommand[]) =>
|
|
148
|
+
runOperation(() => executeBatchAsync(connectionId, commands, queueKey)),
|
|
84
149
|
loadFile: (location: string) =>
|
|
85
|
-
runSyncOperation(
|
|
86
|
-
HybridNitroSQLite.loadFile(
|
|
150
|
+
runSyncOperation(() =>
|
|
151
|
+
HybridNitroSQLite.loadFile(connectionId, location),
|
|
87
152
|
),
|
|
88
153
|
loadFileAsync: (location: string) =>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
154
|
+
runOperation(() =>
|
|
155
|
+
queueStatementAsync(queueKey, async () => {
|
|
156
|
+
try {
|
|
157
|
+
return await HybridNitroSQLite.loadFileAsync(connectionId, location)
|
|
158
|
+
} catch (error) {
|
|
159
|
+
throw NitroSQLiteError.fromError(error)
|
|
160
|
+
}
|
|
161
|
+
}),
|
|
162
|
+
),
|
|
96
163
|
}
|
|
97
164
|
}
|
|
98
165
|
|
|
99
|
-
function
|
|
166
|
+
function openNativeConnection(options: NitroSQLiteConnectionOptions): {
|
|
167
|
+
connectionId: string
|
|
168
|
+
queueKey: DatabaseQueueKey
|
|
169
|
+
} {
|
|
170
|
+
if (options.connection === 'independent') {
|
|
171
|
+
let connectionId: string
|
|
172
|
+
try {
|
|
173
|
+
connectionId = options.readOnly
|
|
174
|
+
? HybridNitroSQLite.openConnection(options.name, options.location, true)
|
|
175
|
+
: HybridNitroSQLite.openConnection(options.name, options.location)
|
|
176
|
+
const queueKey = Symbol(options.name)
|
|
177
|
+
openDatabaseQueue(queueKey)
|
|
178
|
+
return { connectionId, queueKey }
|
|
179
|
+
} catch (error) {
|
|
180
|
+
throw NitroSQLiteError.fromError(error)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
openDatabaseQueue(options.name)
|
|
100
185
|
try {
|
|
101
|
-
|
|
186
|
+
if (options.readOnly) {
|
|
187
|
+
HybridNitroSQLite.open(options.name, options.location, true)
|
|
188
|
+
} else {
|
|
189
|
+
HybridNitroSQLite.open(options.name, options.location)
|
|
190
|
+
}
|
|
102
191
|
} catch (error) {
|
|
192
|
+
closeDatabaseQueue(options.name)
|
|
103
193
|
throw NitroSQLiteError.fromError(error)
|
|
104
194
|
}
|
|
195
|
+
return { connectionId: options.name, queueKey: options.name }
|
|
105
196
|
}
|
|
@@ -7,15 +7,35 @@ import type {
|
|
|
7
7
|
} from '../types'
|
|
8
8
|
import { executeAsyncNative, executeNative } from './execute'
|
|
9
9
|
import NitroSQLiteError from '../NitroSQLiteError'
|
|
10
|
+
import type { DatabaseQueueKey } from '../DatabaseQueue'
|
|
10
11
|
|
|
12
|
+
/** Queue a transaction for an open managed connection.
|
|
13
|
+
* Use only the supplied `tx` for work on this database inside the callback.
|
|
14
|
+
* A successful callback commits unless it explicitly committed or rolled back;
|
|
15
|
+
* a thrown error rolls back unless the transaction was already finalized.
|
|
16
|
+
* @param dbName Name of the open database.
|
|
17
|
+
* @param transactionCallback Async callback receiving the transaction handle.
|
|
18
|
+
* @param isExclusive Begin an exclusive transaction when true.
|
|
19
|
+
* @returns The callback's result after the transaction finishes.
|
|
20
|
+
*/
|
|
11
21
|
export const transaction = async <Result = void>(
|
|
12
22
|
dbName: string,
|
|
13
23
|
transactionCallback: (tx: Transaction) => Promise<Result>,
|
|
14
24
|
isExclusive = false,
|
|
25
|
+
queueKey: DatabaseQueueKey = dbName,
|
|
15
26
|
) => {
|
|
16
|
-
throwIfDatabaseIsNotOpen(
|
|
27
|
+
throwIfDatabaseIsNotOpen(queueKey)
|
|
17
28
|
|
|
18
29
|
let isFinished = false
|
|
30
|
+
const pendingAsyncStatements = new Set<Promise<unknown>>()
|
|
31
|
+
|
|
32
|
+
const throwIfAsyncPending = () => {
|
|
33
|
+
if (pendingAsyncStatements.size > 0) {
|
|
34
|
+
throw new NitroSQLiteError(
|
|
35
|
+
`Cannot run synchronous operation on transaction ${dbName} while async queries are pending. Await all tx.executeAsync calls first.`,
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
19
39
|
|
|
20
40
|
const executeOnTransaction = <Row extends QueryResultRow = never>(
|
|
21
41
|
query: string,
|
|
@@ -26,6 +46,7 @@ export const transaction = async <Result = void>(
|
|
|
26
46
|
`Cannot execute query on finalized transaction: ${dbName}`,
|
|
27
47
|
)
|
|
28
48
|
}
|
|
49
|
+
throwIfAsyncPending()
|
|
29
50
|
return executeNative(dbName, query, params)
|
|
30
51
|
}
|
|
31
52
|
|
|
@@ -38,7 +59,13 @@ export const transaction = async <Result = void>(
|
|
|
38
59
|
`Cannot execute query on finalized transaction: ${dbName}`,
|
|
39
60
|
)
|
|
40
61
|
}
|
|
41
|
-
|
|
62
|
+
const pending = executeAsyncNative<Row>(dbName, query, params)
|
|
63
|
+
pendingAsyncStatements.add(pending)
|
|
64
|
+
pending.then(
|
|
65
|
+
() => pendingAsyncStatements.delete(pending),
|
|
66
|
+
() => pendingAsyncStatements.delete(pending),
|
|
67
|
+
)
|
|
68
|
+
return pending
|
|
42
69
|
}
|
|
43
70
|
|
|
44
71
|
const commit = () => {
|
|
@@ -47,6 +74,7 @@ export const transaction = async <Result = void>(
|
|
|
47
74
|
`Cannot execute commit on finalized transaction: ${dbName}`,
|
|
48
75
|
)
|
|
49
76
|
}
|
|
77
|
+
throwIfAsyncPending()
|
|
50
78
|
isFinished = true
|
|
51
79
|
return executeNative(dbName, 'COMMIT')
|
|
52
80
|
}
|
|
@@ -57,11 +85,12 @@ export const transaction = async <Result = void>(
|
|
|
57
85
|
`Cannot execute rollback on finalized transaction: ${dbName}`,
|
|
58
86
|
)
|
|
59
87
|
}
|
|
88
|
+
throwIfAsyncPending()
|
|
60
89
|
isFinished = true
|
|
61
90
|
return executeNative(dbName, 'ROLLBACK')
|
|
62
91
|
}
|
|
63
92
|
|
|
64
|
-
return await queueOperationAsync(
|
|
93
|
+
return await queueOperationAsync(queueKey, async () => {
|
|
65
94
|
try {
|
|
66
95
|
await executeAsyncNative(
|
|
67
96
|
dbName,
|
|
@@ -80,8 +109,12 @@ export const transaction = async <Result = void>(
|
|
|
80
109
|
return result
|
|
81
110
|
} catch (executionError) {
|
|
82
111
|
if (!isFinished) {
|
|
112
|
+
isFinished = true
|
|
113
|
+
// All queued native calls must finish before ROLLBACK can run
|
|
114
|
+
// synchronously on this connection.
|
|
115
|
+
await Promise.allSettled(pendingAsyncStatements)
|
|
83
116
|
try {
|
|
84
|
-
|
|
117
|
+
executeNative(dbName, 'ROLLBACK')
|
|
85
118
|
} catch (rollbackError) {
|
|
86
119
|
throw NitroSQLiteError.fromError(rollbackError)
|
|
87
120
|
}
|
|
@@ -6,37 +6,119 @@ import type {
|
|
|
6
6
|
SQLiteQueryParams,
|
|
7
7
|
} from '../types'
|
|
8
8
|
import type { NitroSQLiteQueryResult } from './NitroSQLiteQueryResult.nitro'
|
|
9
|
+
import type { NitroSQLitePreparedStatement } from './NitroSQLitePreparedStatement.nitro'
|
|
9
10
|
|
|
11
|
+
/** Native database operations exposed through `NitroSQLite.native`.
|
|
12
|
+
* These calls bypass the managed connection queue. Coordinate them with any
|
|
13
|
+
* transaction or pending operation on the same database yourself.
|
|
14
|
+
*/
|
|
10
15
|
export interface NitroSQLite
|
|
11
16
|
extends HybridObject<{
|
|
12
17
|
ios: 'c++'
|
|
13
18
|
android: 'c++'
|
|
14
19
|
}> {
|
|
15
|
-
|
|
20
|
+
/** Open a name-based default connection, creating the database unless `readOnly` is true.
|
|
21
|
+
* @param dbName Database file name and default connection key.
|
|
22
|
+
* @param location Directory relative to the platform database directory.
|
|
23
|
+
* @param readOnly Open an existing database without write access.
|
|
24
|
+
*/
|
|
25
|
+
open(dbName: string, location?: string, readOnly?: boolean): void
|
|
26
|
+
/** Open a separate native handle, even when the database file is already open.
|
|
27
|
+
* Independent connections require a thread-safe SQLite build.
|
|
28
|
+
* @param dbName Database file name.
|
|
29
|
+
* @param location Directory relative to the platform database directory.
|
|
30
|
+
* @param readOnly Open an existing database without write access.
|
|
31
|
+
* @returns An opaque ID to pass to native connection operations.
|
|
32
|
+
*/
|
|
33
|
+
openConnection(dbName: string, location?: string, readOnly?: boolean): string
|
|
34
|
+
/** Check whether a native connection ID is still open.
|
|
35
|
+
* @param connectionId ID returned by `openConnection`.
|
|
36
|
+
*/
|
|
37
|
+
isConnectionOpen(connectionId: string): boolean
|
|
38
|
+
/** Close a default connection by name or an independent connection by ID. */
|
|
16
39
|
close(dbName: string): void
|
|
17
|
-
|
|
40
|
+
/** Delete a database and close the indicated connection if open.
|
|
41
|
+
* Deletion fails while another connection or attachment uses the database file.
|
|
42
|
+
* @param dbName Database file name.
|
|
43
|
+
* @param location Directory relative to the platform database directory.
|
|
44
|
+
* @param connectionId Optional ID of the independent connection to close.
|
|
45
|
+
*/
|
|
46
|
+
drop(dbName: string, location?: string, connectionId?: string): void
|
|
47
|
+
/** Attach a database file to an open main database under an SQL schema alias.
|
|
48
|
+
* @param mainDbName Name of the open main database.
|
|
49
|
+
* @param dbNameToAttach File name of the database to attach.
|
|
50
|
+
* @param alias SQL schema name for the attached database.
|
|
51
|
+
* @param location Directory relative to the platform database directory.
|
|
52
|
+
*/
|
|
53
|
+
|
|
18
54
|
attach(
|
|
19
55
|
mainDbName: string,
|
|
20
56
|
dbNameToAttach: string,
|
|
21
57
|
alias: string,
|
|
22
58
|
location?: string,
|
|
23
59
|
): void
|
|
60
|
+
/** Detach an attached database by its alias.
|
|
61
|
+
* @param mainDbName Name of the open main database.
|
|
62
|
+
* @param alias SQL schema name used when attaching.
|
|
63
|
+
*/
|
|
24
64
|
detach(mainDbName: string, alias: string): void
|
|
65
|
+
/** Execute one SQL statement synchronously on the calling thread.
|
|
66
|
+
* @param dbName Name of an open database.
|
|
67
|
+
* @param query SQL statement with optional positional placeholders.
|
|
68
|
+
* @param params Positional values bound to SQL placeholders.
|
|
69
|
+
* @returns Native query rows, affected row count, insert ID, and metadata.
|
|
70
|
+
*/
|
|
25
71
|
execute(
|
|
26
72
|
dbName: string,
|
|
27
73
|
query: string,
|
|
28
74
|
params?: SQLiteQueryParams,
|
|
29
75
|
): NitroSQLiteQueryResult
|
|
76
|
+
/** Execute one SQL statement on a background thread.
|
|
77
|
+
* @param dbName Name of an open database.
|
|
78
|
+
* @param query SQL statement with optional positional placeholders.
|
|
79
|
+
* @param params Positional values bound to SQL placeholders.
|
|
80
|
+
* @returns A promise of the native query result.
|
|
81
|
+
*/
|
|
30
82
|
executeAsync(
|
|
31
83
|
dbName: string,
|
|
32
84
|
query: string,
|
|
33
85
|
params?: SQLiteQueryParams,
|
|
34
86
|
): Promise<NitroSQLiteQueryResult>
|
|
87
|
+
/** Prepare one SQL statement on an open native connection for repeated execution.
|
|
88
|
+
* Finalize the returned statement before closing its connection.
|
|
89
|
+
* @param dbName Name or ID of an open database connection.
|
|
90
|
+
* @param query SQL statement with optional positional placeholders.
|
|
91
|
+
* @returns A native statement with synchronous and asynchronous execution methods.
|
|
92
|
+
*/
|
|
93
|
+
prepare(dbName: string, query: string): NitroSQLitePreparedStatement
|
|
94
|
+
/** Execute commands in one exclusive transaction on the calling thread.
|
|
95
|
+
* An empty batch throws; a failed command rolls back the batch.
|
|
96
|
+
* @param dbName Name of an open database.
|
|
97
|
+
* @param commands SQL commands and optional parameter sets.
|
|
98
|
+
* @returns Total affected row count.
|
|
99
|
+
*/
|
|
35
100
|
executeBatch(dbName: string, commands: BatchQueryCommand[]): BatchQueryResult
|
|
101
|
+
/** Execute commands in one exclusive transaction on a background thread.
|
|
102
|
+
* An empty batch rejects; a failed command rolls back the batch.
|
|
103
|
+
* @param dbName Name of an open database.
|
|
104
|
+
* @param commands SQL commands and optional parameter sets.
|
|
105
|
+
* @returns A promise of the total affected row count.
|
|
106
|
+
*/
|
|
36
107
|
executeBatchAsync(
|
|
37
108
|
dbName: string,
|
|
38
109
|
commands: BatchQueryCommand[],
|
|
39
110
|
): Promise<BatchQueryResult>
|
|
111
|
+
/** Import a SQL file in one exclusive transaction on the calling thread.
|
|
112
|
+
* Each non-empty line is treated as one statement.
|
|
113
|
+
* @param dbName Name of an open database.
|
|
114
|
+
* @param location Path to the SQL file.
|
|
115
|
+
* @returns Number of executed commands and affected rows.
|
|
116
|
+
*/
|
|
40
117
|
loadFile(dbName: string, location: string): FileLoadResult
|
|
118
|
+
/** Import a SQL file on a background thread.
|
|
119
|
+
* @param dbName Name of an open database.
|
|
120
|
+
* @param location Path to the SQL file.
|
|
121
|
+
* @returns A promise of the command and affected row counts.
|
|
122
|
+
*/
|
|
41
123
|
loadFileAsync(dbName: string, location: string): Promise<FileLoadResult>
|
|
42
124
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { HybridObject } from 'react-native-nitro-modules'
|
|
2
|
+
import type { SQLiteQueryParams } from '../types'
|
|
3
|
+
import type { NitroSQLiteQueryResult } from './NitroSQLiteQueryResult.nitro'
|
|
4
|
+
|
|
5
|
+
/** Native prepared statement returned by `NitroSQLite.native.prepare()`. */
|
|
6
|
+
export interface NitroSQLitePreparedStatement
|
|
7
|
+
extends HybridObject<{
|
|
8
|
+
ios: 'c++'
|
|
9
|
+
android: 'c++'
|
|
10
|
+
}> {
|
|
11
|
+
/** Whether the native statement has been finalized. */
|
|
12
|
+
readonly isFinalized: boolean
|
|
13
|
+
|
|
14
|
+
/** Execute on the calling thread, replacing the previous parameter bindings.
|
|
15
|
+
* Throws after finalization or connection closure.
|
|
16
|
+
* @param params Values bound to positional placeholders.
|
|
17
|
+
* @returns Native query rows, affected row count, insert ID, and metadata.
|
|
18
|
+
*/
|
|
19
|
+
execute(params?: SQLiteQueryParams): NitroSQLiteQueryResult
|
|
20
|
+
/** Execute on a background thread, replacing the previous parameter bindings.
|
|
21
|
+
* Rejects after finalization or connection closure.
|
|
22
|
+
* @param params Values bound to positional placeholders.
|
|
23
|
+
* @returns A promise of the native query result.
|
|
24
|
+
*/
|
|
25
|
+
executeAsync(params?: SQLiteQueryParams): Promise<NitroSQLiteQueryResult>
|
|
26
|
+
/** Release the native statement. Repeated calls are safe. */
|
|
27
|
+
finalize(): void
|
|
28
|
+
}
|
|
@@ -1,28 +1,21 @@
|
|
|
1
1
|
import type { HybridObject } from 'react-native-nitro-modules'
|
|
2
2
|
import type { ColumnType, SQLiteValue } from '../types'
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Object returned by SQL Query executions {
|
|
6
|
-
* insertId: Represent the auto-generated row id if applicable
|
|
7
|
-
* rowsAffected: Number of affected rows if result of a update query
|
|
8
|
-
* message: if status === 1, here you will find error description
|
|
9
|
-
* rows: if status is undefined or 0 this object will contain the query results
|
|
10
|
-
* }
|
|
11
|
-
*
|
|
12
|
-
* @interface QueryResult
|
|
13
|
-
*/
|
|
4
|
+
/** Native result of one SQL statement. The managed API also adds a `rows` adapter. */
|
|
14
5
|
export interface NitroSQLiteQueryResult
|
|
15
6
|
extends HybridObject<{
|
|
16
7
|
ios: 'c++'
|
|
17
8
|
android: 'c++'
|
|
18
9
|
}> {
|
|
10
|
+
/** SQLite's latest row change count. For a read-only query it may reflect an earlier write. */
|
|
19
11
|
readonly rowsAffected: number
|
|
12
|
+
/** Last insert row ID for this connection. It may refer to an earlier statement. */
|
|
20
13
|
readonly insertId?: number
|
|
21
14
|
|
|
22
|
-
/**
|
|
15
|
+
/** Rows keyed by result column names. */
|
|
23
16
|
readonly results: Record<string, SQLiteValue>[]
|
|
24
17
|
|
|
25
|
-
/**
|
|
18
|
+
/** Column metadata keyed by result column name, when available. */
|
|
26
19
|
readonly metadata?: Record<string, NitroSQLiteQueryColumnMetadata>
|
|
27
20
|
}
|
|
28
21
|
|
|
@@ -33,13 +26,14 @@ export interface NitroSQLiteQueryResult
|
|
|
33
26
|
|
|
34
27
|
// type NitroQueryResultRow = Record<string, SQLiteValue>
|
|
35
28
|
|
|
29
|
+
/** Name, declared type, and position of a result column. */
|
|
36
30
|
export type NitroSQLiteQueryColumnMetadata = {
|
|
37
|
-
/**
|
|
31
|
+
/** Name used for this column in the result set. */
|
|
38
32
|
name: string
|
|
39
33
|
|
|
40
|
-
/**
|
|
34
|
+
/** Native type category derived from the column declaration. */
|
|
41
35
|
type: ColumnType
|
|
42
36
|
|
|
43
|
-
/**
|
|
37
|
+
/** Zero-based position in the result set. */
|
|
44
38
|
index: number
|
|
45
39
|
}
|
package/src/typeORM.ts
CHANGED
|
@@ -13,29 +13,40 @@ import type {
|
|
|
13
13
|
} from './types'
|
|
14
14
|
import * as Operations from './operations/session'
|
|
15
15
|
|
|
16
|
+
/** Callback-oriented connection returned to TypeORM. */
|
|
16
17
|
interface TypeOrmNitroSQLiteConnection {
|
|
18
|
+
/** Execute SQL asynchronously and report the result through a callback. */
|
|
17
19
|
executeSql: <RowData extends QueryResultRow = never>(
|
|
18
20
|
sql: string,
|
|
19
21
|
params: SQLiteQueryParams | undefined,
|
|
20
22
|
okExecute: (res: QueryResult<RowData>) => void,
|
|
21
23
|
failExecute: (msg: string) => void,
|
|
22
24
|
) => Promise<void>
|
|
25
|
+
/** Run TypeORM work in a managed transaction. */
|
|
23
26
|
transaction: (fn: (tx: Transaction) => Promise<void>) => Promise<void>
|
|
27
|
+
/** Close the connection and report completion through callbacks. */
|
|
24
28
|
close: (okClose: () => void, failClose: (e: unknown) => void) => void
|
|
29
|
+
/** Attach another database and invoke `callback` after it succeeds. */
|
|
25
30
|
attach: (
|
|
26
31
|
dbNameToAttach: string,
|
|
27
32
|
alias: string,
|
|
28
33
|
location: string | undefined,
|
|
29
34
|
callback: () => void,
|
|
30
35
|
) => void
|
|
36
|
+
/** Detach an attached database and invoke `callback` after it succeeds. */
|
|
31
37
|
detach: (alias: string, callback: () => void) => void
|
|
32
38
|
}
|
|
33
39
|
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
40
|
+
/** Adapter for TypeORM's React Native driver. Application code should use `open()`.
|
|
41
|
+
* `openDatabase` reports success or failure through callbacks and returns the
|
|
42
|
+
* connection on success, or `null` when opening fails.
|
|
37
43
|
*/
|
|
38
44
|
export const typeORMDriver = {
|
|
45
|
+
/** Open a database for TypeORM.
|
|
46
|
+
* @param options Database name and optional relative directory.
|
|
47
|
+
* @param ok Receives the adapter connection on success.
|
|
48
|
+
* @param fail Receives the opening error on failure.
|
|
49
|
+
*/
|
|
39
50
|
openDatabase: (
|
|
40
51
|
options: {
|
|
41
52
|
name: string
|