expo-sqlite 12.2.1 → 13.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/CHANGELOG.md +16 -0
- package/android/CMakeLists.txt +1 -1
- package/android/build.gradle +2 -2
- package/android/src/main/cpp/NativeStatementBinding.cpp +16 -15
- package/android/src/main/java/expo/modules/sqlite/NativeDatabase.kt +2 -0
- package/android/src/main/java/expo/modules/sqlite/NativeStatement.kt +2 -0
- package/android/src/main/java/expo/modules/sqlite/SQLExceptions.kt +6 -0
- package/android/src/main/java/expo/modules/sqlite/SQLiteModuleNext.kt +98 -95
- package/build/next/NativeStatement.d.ts +9 -13
- package/build/next/NativeStatement.d.ts.map +1 -1
- package/build/next/NativeStatement.js.map +1 -1
- package/build/next/Statement.d.ts +4 -6
- package/build/next/Statement.d.ts.map +1 -1
- package/build/next/Statement.js +36 -47
- package/build/next/Statement.js.map +1 -1
- package/ios/Exceptions.swift +12 -0
- package/ios/NativeDatabase.swift +1 -0
- package/ios/NativeStatement.swift +1 -0
- package/ios/SQLiteModule.swift +3 -4
- package/ios/SQLiteModuleNext.swift +105 -89
- package/ios/crsqlite.xcframework/Info.plist +4 -0
- package/ios/crsqlite.xcframework/ios-arm64/crsqlite.framework/Info.plist +4 -0
- package/package.json +2 -2
- package/src/next/NativeStatement.ts +36 -22
- package/src/next/Statement.ts +54 -49
package/build/next/Statement.js
CHANGED
|
@@ -9,42 +9,28 @@ export class Statement {
|
|
|
9
9
|
this.nativeStatement = nativeStatement;
|
|
10
10
|
}
|
|
11
11
|
async runAsync(...params) {
|
|
12
|
-
|
|
13
|
-
if (shouldPassAsObject) {
|
|
14
|
-
return await this.nativeStatement.objectRunAsync(this.nativeDatabase, bindParams);
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
return await this.nativeStatement.arrayRunAsync(this.nativeDatabase, bindParams);
|
|
18
|
-
}
|
|
12
|
+
return await this.nativeStatement.runAsync(this.nativeDatabase, ...normalizeParams(...params));
|
|
19
13
|
}
|
|
20
14
|
async *eachAsync(...params) {
|
|
21
|
-
const
|
|
22
|
-
const func =
|
|
23
|
-
? this.nativeStatement.objectGetAsync.bind(this.nativeStatement)
|
|
24
|
-
: this.nativeStatement.arrayGetAsync.bind(this.nativeStatement);
|
|
15
|
+
const paramTuple = normalizeParams(...params);
|
|
16
|
+
const func = this.nativeStatement.getAsync.bind(this.nativeStatement);
|
|
25
17
|
const columnNames = await this.getColumnNamesAsync();
|
|
26
18
|
let result = null;
|
|
27
19
|
do {
|
|
28
|
-
result = await func(this.nativeDatabase,
|
|
20
|
+
result = await func(this.nativeDatabase, ...paramTuple);
|
|
29
21
|
if (result != null) {
|
|
30
22
|
yield composeRow(columnNames, result);
|
|
31
23
|
}
|
|
32
24
|
} while (result != null);
|
|
33
25
|
}
|
|
34
26
|
async getAsync(...params) {
|
|
35
|
-
const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);
|
|
36
27
|
const columnNames = await this.getColumnNamesAsync();
|
|
37
|
-
const columnValues =
|
|
38
|
-
? await this.nativeStatement.objectGetAsync(this.nativeDatabase, bindParams)
|
|
39
|
-
: await this.nativeStatement.arrayGetAsync(this.nativeDatabase, bindParams);
|
|
28
|
+
const columnValues = await this.nativeStatement.getAsync(this.nativeDatabase, ...normalizeParams(...params));
|
|
40
29
|
return columnValues != null ? composeRow(columnNames, columnValues) : null;
|
|
41
30
|
}
|
|
42
31
|
async allAsync(...params) {
|
|
43
|
-
const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);
|
|
44
32
|
const columnNames = await this.getColumnNamesAsync();
|
|
45
|
-
const columnValuesList =
|
|
46
|
-
? await this.nativeStatement.objectGetAllAsync(this.nativeDatabase, bindParams)
|
|
47
|
-
: await this.nativeStatement.arrayGetAllAsync(this.nativeDatabase, bindParams);
|
|
33
|
+
const columnValuesList = await this.nativeStatement.getAllAsync(this.nativeDatabase, ...normalizeParams(...params));
|
|
48
34
|
return composeRows(columnNames, columnValuesList);
|
|
49
35
|
}
|
|
50
36
|
/**
|
|
@@ -67,42 +53,28 @@ export class Statement {
|
|
|
67
53
|
await this.nativeStatement.finalizeAsync(this.nativeDatabase);
|
|
68
54
|
}
|
|
69
55
|
runSync(...params) {
|
|
70
|
-
|
|
71
|
-
if (shouldPassAsObject) {
|
|
72
|
-
return this.nativeStatement.objectRunSync(this.nativeDatabase, bindParams);
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
return this.nativeStatement.arrayRunSync(this.nativeDatabase, bindParams);
|
|
76
|
-
}
|
|
56
|
+
return this.nativeStatement.runSync(this.nativeDatabase, ...normalizeParams(...params));
|
|
77
57
|
}
|
|
78
58
|
*eachSync(...params) {
|
|
79
|
-
const
|
|
80
|
-
const func =
|
|
81
|
-
? this.nativeStatement.objectGetSync.bind(this.nativeStatement)
|
|
82
|
-
: this.nativeStatement.arrayGetSync.bind(this.nativeStatement);
|
|
59
|
+
const paramTuple = normalizeParams(...params);
|
|
60
|
+
const func = this.nativeStatement.getSync.bind(this.nativeStatement);
|
|
83
61
|
const columnNames = this.getColumnNamesSync();
|
|
84
62
|
let result = null;
|
|
85
63
|
do {
|
|
86
|
-
result = func(this.nativeDatabase,
|
|
64
|
+
result = func(this.nativeDatabase, ...paramTuple);
|
|
87
65
|
if (result != null) {
|
|
88
66
|
yield composeRow(columnNames, result);
|
|
89
67
|
}
|
|
90
68
|
} while (result != null);
|
|
91
69
|
}
|
|
92
70
|
getSync(...params) {
|
|
93
|
-
const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);
|
|
94
71
|
const columnNames = this.getColumnNamesSync();
|
|
95
|
-
const columnValues =
|
|
96
|
-
? this.nativeStatement.objectGetSync(this.nativeDatabase, bindParams)
|
|
97
|
-
: this.nativeStatement.arrayGetSync(this.nativeDatabase, bindParams);
|
|
72
|
+
const columnValues = this.nativeStatement.getSync(this.nativeDatabase, ...normalizeParams(...params));
|
|
98
73
|
return columnValues != null ? composeRow(columnNames, columnValues) : null;
|
|
99
74
|
}
|
|
100
75
|
allSync(...params) {
|
|
101
|
-
const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);
|
|
102
76
|
const columnNames = this.getColumnNamesSync();
|
|
103
|
-
const columnValuesList =
|
|
104
|
-
? this.nativeStatement.objectGetAllSync(this.nativeDatabase, bindParams)
|
|
105
|
-
: this.nativeStatement.arrayGetAllSync(this.nativeDatabase, bindParams);
|
|
77
|
+
const columnValuesList = this.nativeStatement.getAllSync(this.nativeDatabase, ...normalizeParams(...params));
|
|
106
78
|
return composeRows(columnNames, columnValuesList);
|
|
107
79
|
}
|
|
108
80
|
/**
|
|
@@ -128,7 +100,8 @@ export class Statement {
|
|
|
128
100
|
}
|
|
129
101
|
}
|
|
130
102
|
/**
|
|
131
|
-
* Normalize the bind params to
|
|
103
|
+
* Normalize the bind params to data structure that can be passed to native module.
|
|
104
|
+
* The data structure is a tuple of [primitiveParams, blobParams, shouldPassAsArray].
|
|
132
105
|
* @hidden
|
|
133
106
|
*/
|
|
134
107
|
export function normalizeParams(...params) {
|
|
@@ -136,14 +109,30 @@ export function normalizeParams(...params) {
|
|
|
136
109
|
if (bindParams == null) {
|
|
137
110
|
bindParams = [];
|
|
138
111
|
}
|
|
139
|
-
if (typeof bindParams !== 'object'
|
|
112
|
+
if (typeof bindParams !== 'object' ||
|
|
113
|
+
bindParams instanceof ArrayBuffer ||
|
|
114
|
+
ArrayBuffer.isView(bindParams)) {
|
|
140
115
|
bindParams = [bindParams];
|
|
141
116
|
}
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
117
|
+
const shouldPassAsArray = Array.isArray(bindParams);
|
|
118
|
+
if (Array.isArray(bindParams)) {
|
|
119
|
+
bindParams = bindParams.reduce((acc, value, index) => {
|
|
120
|
+
acc[index] = value;
|
|
121
|
+
return acc;
|
|
122
|
+
}, {});
|
|
123
|
+
}
|
|
124
|
+
const primitiveParams = {};
|
|
125
|
+
const blobParams = {};
|
|
126
|
+
for (const key in bindParams) {
|
|
127
|
+
const value = bindParams[key];
|
|
128
|
+
if (value instanceof Uint8Array) {
|
|
129
|
+
blobParams[key] = value;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
primitiveParams[key] = value;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return [primitiveParams, blobParams, shouldPassAsArray];
|
|
147
136
|
}
|
|
148
137
|
/**
|
|
149
138
|
* Compose `columnNames` and `columnValues` to an row object.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Statement.js","sourceRoot":"","sources":["../../src/next/Statement.ts"],"names":[],"mappings":"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","sourcesContent":["import { NativeDatabase } from './NativeDatabase';\nimport {\n BindParams,\n BindValue,\n NativeStatement,\n RunResult,\n VariadicBindParams,\n type ColumnNames,\n type ColumnValues,\n} from './NativeStatement';\n\nexport { BindParams, BindValue, RunResult, VariadicBindParams };\n\n/**\n * A prepared statement returned by [`Database.prepareAsync()`](#prepareasyncsource) or [`Database.prepareSync()`](#preparesyncsource) that can be binded with parameters and executed.\n */\nexport class Statement {\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 result.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`BindValue`](#bindvalue) for more information about binding values.\n */\n public runAsync(params: BindParams): Promise<RunResult>;\n /**\n * @hidden\n */\n public runAsync(...params: VariadicBindParams): Promise<RunResult>;\n public async runAsync(...params: unknown[]): Promise<RunResult> {\n const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);\n if (shouldPassAsObject) {\n return await this.nativeStatement.objectRunAsync(this.nativeDatabase, bindParams);\n } else {\n return await this.nativeStatement.arrayRunAsync(this.nativeDatabase, bindParams);\n }\n }\n\n /**\n * Iterate the prepared statement and return results as an async iterable.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`BindValue`](#bindvalue) for more information about binding values.\n * @example\n * ```ts\n * const statement = await db.prepareAsync('SELECT * FROM test');\n * for await (const row of statement.eachAsync<any>()) {\n * console.log(row);\n * }\n * await statement.finalizeAsync();\n * ```\n */\n public eachAsync<T>(params: BindParams): AsyncIterableIterator<T>;\n /**\n * @hidden\n */\n public eachAsync<T>(...params: VariadicBindParams): AsyncIterableIterator<T>;\n public async *eachAsync<T>(...params: unknown[]): AsyncIterableIterator<T> {\n const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);\n const func = shouldPassAsObject\n ? this.nativeStatement.objectGetAsync.bind(this.nativeStatement)\n : this.nativeStatement.arrayGetAsync.bind(this.nativeStatement);\n\n const columnNames = await this.getColumnNamesAsync();\n let result = null;\n do {\n result = await func(this.nativeDatabase, bindParams);\n if (result != null) {\n yield composeRow<T>(columnNames, result);\n }\n } while (result != null);\n }\n\n /**\n * Get one row from the prepared statement.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`BindValue`](#bindvalue) for more information about binding values.\n */\n public getAsync<T>(params: BindParams): Promise<T | null>;\n /**\n * @hidden\n */\n public getAsync<T>(...params: VariadicBindParams): Promise<T | null>;\n public async getAsync<T>(...params: unknown[]): Promise<T | null> {\n const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);\n const columnNames = await this.getColumnNamesAsync();\n const columnValues = shouldPassAsObject\n ? await this.nativeStatement.objectGetAsync(this.nativeDatabase, bindParams)\n : await this.nativeStatement.arrayGetAsync(this.nativeDatabase, bindParams);\n return columnValues != null ? composeRow<T>(columnNames, columnValues) : null;\n }\n\n /**\n * Get all rows from the prepared statement.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`BindValue`](#bindvalue) for more information about binding values.\n */\n public allAsync<T>(params: BindParams): Promise<T[]>;\n /**\n * @hidden\n */\n public allAsync<T>(...params: VariadicBindParams): Promise<T[]>;\n public async allAsync<T>(...params: unknown[]): Promise<T[]> {\n const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);\n const columnNames = await this.getColumnNamesAsync();\n const columnValuesList = shouldPassAsObject\n ? await this.nativeStatement.objectGetAllAsync(this.nativeDatabase, bindParams)\n : await this.nativeStatement.arrayGetAllAsync(this.nativeDatabase, bindParams);\n return composeRows<T>(columnNames, columnValuesList);\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 * Reset the prepared statement cursor.\n */\n public async resetAsync(): Promise<void> {\n await this.nativeStatement.resetAsync(this.nativeDatabase);\n }\n\n /**\n * Finalize the prepared statement.\n * > **Note:** Remember to finalize the prepared statement whenever you call `prepareAsync()` to avoid resource leaks.\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 result.\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 [`BindValue`](#bindvalue) for more information about binding values.\n */\n public runSync(params: BindParams): RunResult;\n /**\n * @hidden\n */\n public runSync(...params: VariadicBindParams): RunResult;\n public runSync(...params: unknown[]): RunResult {\n const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);\n if (shouldPassAsObject) {\n return this.nativeStatement.objectRunSync(this.nativeDatabase, bindParams);\n } else {\n return this.nativeStatement.arrayRunSync(this.nativeDatabase, bindParams);\n }\n }\n\n /**\n * Iterate the prepared statement and return results as an iterable.\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 [`BindValue`](#bindvalue) for more information about binding values.\n */\n public eachSync<T>(params: BindParams): IterableIterator<T>;\n /**\n * @hidden\n */\n public eachSync<T>(...params: VariadicBindParams): IterableIterator<T>;\n public *eachSync<T>(...params: unknown[]): IterableIterator<T> {\n const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);\n const func = shouldPassAsObject\n ? this.nativeStatement.objectGetSync.bind(this.nativeStatement)\n : this.nativeStatement.arrayGetSync.bind(this.nativeStatement);\n\n const columnNames = this.getColumnNamesSync();\n let result = null;\n do {\n result = func(this.nativeDatabase, bindParams);\n if (result != null) {\n yield composeRow<T>(columnNames, result);\n }\n } while (result != null);\n }\n\n /**\n * Get one row from the prepared statement.\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 [`BindValue`](#bindvalue) for more information about binding values.\n */\n public getSync<T>(params: BindParams): T | null;\n /**\n * @hidden\n */\n public getSync<T>(...params: VariadicBindParams): T | null;\n public getSync<T>(...params: unknown[]): T | null {\n const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);\n const columnNames = this.getColumnNamesSync();\n const columnValues = shouldPassAsObject\n ? this.nativeStatement.objectGetSync(this.nativeDatabase, bindParams)\n : this.nativeStatement.arrayGetSync(this.nativeDatabase, bindParams);\n return columnValues != null ? composeRow<T>(columnNames, columnValues) : null;\n }\n\n /**\n * Get all rows from the prepared statement.\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 [`BindValue`](#bindvalue) for more information about binding values.\n */\n public allSync<T>(params: BindParams): T[];\n /**\n * @hidden\n */\n public allSync<T>(...params: VariadicBindParams): T[];\n public allSync<T>(...params: unknown[]): T[] {\n const { params: bindParams, shouldPassAsObject } = normalizeParams(...params);\n const columnNames = this.getColumnNamesSync();\n const columnValuesList = shouldPassAsObject\n ? this.nativeStatement.objectGetAllSync(this.nativeDatabase, bindParams)\n : this.nativeStatement.arrayGetAllSync(this.nativeDatabase, bindParams);\n return composeRows<T>(columnNames, columnValuesList);\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 * Reset the prepared statement cursor.\n */\n public resetSync(): void {\n this.nativeStatement.resetSync(this.nativeDatabase);\n }\n\n /**\n * Finalize the prepared statement.\n *\n * > **Note:** Remember to finalize the prepared statement whenever you call `prepareSync()` to avoid resource leaks.\n *\n */\n public finalizeSync(): void {\n this.nativeStatement.finalizeSync(this.nativeDatabase);\n }\n\n //#endregion\n}\n\n/**\n * Normalize the bind params to an array or object.\n * @hidden\n */\nexport function normalizeParams(...params: any[]): {\n params: BindParams;\n shouldPassAsObject: boolean;\n} {\n let bindParams = params.length > 1 ? params : (params[0] as BindParams);\n if (bindParams == null) {\n bindParams = [];\n }\n if (typeof bindParams !== 'object') {\n bindParams = [bindParams];\n }\n const shouldPassAsObject = !Array.isArray(bindParams);\n return {\n params: bindParams,\n shouldPassAsObject,\n };\n}\n\n/**\n * Compose `columnNames` and `columnValues` to an row object.\n * @hidden\n */\nexport function composeRow<T>(columnNames: ColumnNames, columnValues: ColumnValues): T {\n const row = {};\n if (columnNames.length !== columnValues.length) {\n throw new Error(\n `Column names and values count mismatch. Names: ${columnNames.length}, Values: ${columnValues.length}`\n );\n }\n for (let i = 0; i < columnNames.length; i++) {\n row[columnNames[i]] = columnValues[i];\n }\n return row as T;\n}\n\n/**\n * Compose `columnNames` and `columnValuesList` to an array of row objects.\n * @hidden\n */\nexport function composeRows<T>(columnNames: ColumnNames, columnValuesList: ColumnValues[]): T[] {\n if (columnValuesList.length === 0) {\n return [];\n }\n if (columnNames.length !== columnValuesList[0].length) {\n // We only check the first row because SQLite returns the same column count for all rows.\n throw new Error(\n `Column names and values count mismatch. Names: ${columnNames.length}, Values: ${columnValuesList[0].length}`\n );\n }\n const results: T[] = [];\n for (const columnValues of columnValuesList) {\n const row = {};\n for (let i = 0; i < columnNames.length; i++) {\n row[columnNames[i]] = columnValues[i];\n }\n results.push(row as T);\n }\n return results;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Statement.js","sourceRoot":"","sources":["../../src/next/Statement.ts"],"names":[],"mappings":"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","sourcesContent":["import { NativeDatabase } from './NativeDatabase';\nimport {\n BindBlobParams,\n BindParams,\n BindPrimitiveParams,\n BindValue,\n NativeStatement,\n RunResult,\n VariadicBindParams,\n type ColumnNames,\n type ColumnValues,\n} from './NativeStatement';\n\nexport { BindParams, BindValue, RunResult, VariadicBindParams };\n\n/**\n * A prepared statement returned by [`Database.prepareAsync()`](#prepareasyncsource) or [`Database.prepareSync()`](#preparesyncsource) that can be binded with parameters and executed.\n */\nexport class Statement {\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 result.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`BindValue`](#bindvalue) for more information about binding values.\n */\n public runAsync(params: BindParams): Promise<RunResult>;\n /**\n * @hidden\n */\n public runAsync(...params: VariadicBindParams): Promise<RunResult>;\n public async runAsync(...params: unknown[]): Promise<RunResult> {\n return await this.nativeStatement.runAsync(this.nativeDatabase, ...normalizeParams(...params));\n }\n\n /**\n * Iterate the prepared statement and return results as an async iterable.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`BindValue`](#bindvalue) for more information about binding values.\n * @example\n * ```ts\n * const statement = await db.prepareAsync('SELECT * FROM test');\n * for await (const row of statement.eachAsync<any>()) {\n * console.log(row);\n * }\n * await statement.finalizeAsync();\n * ```\n */\n public eachAsync<T>(params: BindParams): AsyncIterableIterator<T>;\n /**\n * @hidden\n */\n public eachAsync<T>(...params: VariadicBindParams): AsyncIterableIterator<T>;\n public async *eachAsync<T>(...params: unknown[]): AsyncIterableIterator<T> {\n const paramTuple = normalizeParams(...params);\n const func = this.nativeStatement.getAsync.bind(this.nativeStatement);\n\n const columnNames = await this.getColumnNamesAsync();\n let result = null;\n do {\n result = await func(this.nativeDatabase, ...paramTuple);\n if (result != null) {\n yield composeRow<T>(columnNames, result);\n }\n } while (result != null);\n }\n\n /**\n * Get one row from the prepared statement.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`BindValue`](#bindvalue) for more information about binding values.\n */\n public getAsync<T>(params: BindParams): Promise<T | null>;\n /**\n * @hidden\n */\n public getAsync<T>(...params: VariadicBindParams): Promise<T | null>;\n public async getAsync<T>(...params: unknown[]): Promise<T | null> {\n const columnNames = await this.getColumnNamesAsync();\n const columnValues = await this.nativeStatement.getAsync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return columnValues != null ? composeRow<T>(columnNames, columnValues) : null;\n }\n\n /**\n * Get all rows from the prepared statement.\n * @param params The parameters to bind to the prepared statement. You can pass values in array, object, or variadic arguments. See [`BindValue`](#bindvalue) for more information about binding values.\n */\n public allAsync<T>(params: BindParams): Promise<T[]>;\n /**\n * @hidden\n */\n public allAsync<T>(...params: VariadicBindParams): Promise<T[]>;\n public async allAsync<T>(...params: unknown[]): Promise<T[]> {\n const columnNames = await this.getColumnNamesAsync();\n const columnValuesList = await this.nativeStatement.getAllAsync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return composeRows<T>(columnNames, columnValuesList);\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 * Reset the prepared statement cursor.\n */\n public async resetAsync(): Promise<void> {\n await this.nativeStatement.resetAsync(this.nativeDatabase);\n }\n\n /**\n * Finalize the prepared statement.\n * > **Note:** Remember to finalize the prepared statement whenever you call `prepareAsync()` to avoid resource leaks.\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 result.\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 [`BindValue`](#bindvalue) for more information about binding values.\n */\n public runSync(params: BindParams): RunResult;\n /**\n * @hidden\n */\n public runSync(...params: VariadicBindParams): RunResult;\n public runSync(...params: unknown[]): RunResult {\n return this.nativeStatement.runSync(this.nativeDatabase, ...normalizeParams(...params));\n }\n\n /**\n * Iterate the prepared statement and return results as an iterable.\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 [`BindValue`](#bindvalue) for more information about binding values.\n */\n public eachSync<T>(params: BindParams): IterableIterator<T>;\n /**\n * @hidden\n */\n public eachSync<T>(...params: VariadicBindParams): IterableIterator<T>;\n public *eachSync<T>(...params: unknown[]): IterableIterator<T> {\n const paramTuple = normalizeParams(...params);\n const func = this.nativeStatement.getSync.bind(this.nativeStatement);\n\n const columnNames = this.getColumnNamesSync();\n let result = null;\n do {\n result = func(this.nativeDatabase, ...paramTuple);\n if (result != null) {\n yield composeRow<T>(columnNames, result);\n }\n } while (result != null);\n }\n\n /**\n * Get one row from the prepared statement.\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 [`BindValue`](#bindvalue) for more information about binding values.\n */\n public getSync<T>(params: BindParams): T | null;\n /**\n * @hidden\n */\n public getSync<T>(...params: VariadicBindParams): T | null;\n public getSync<T>(...params: unknown[]): T | null {\n const columnNames = this.getColumnNamesSync();\n const columnValues = this.nativeStatement.getSync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return columnValues != null ? composeRow<T>(columnNames, columnValues) : null;\n }\n\n /**\n * Get all rows from the prepared statement.\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 [`BindValue`](#bindvalue) for more information about binding values.\n */\n public allSync<T>(params: BindParams): T[];\n /**\n * @hidden\n */\n public allSync<T>(...params: VariadicBindParams): T[];\n public allSync<T>(...params: unknown[]): T[] {\n const columnNames = this.getColumnNamesSync();\n const columnValuesList = this.nativeStatement.getAllSync(\n this.nativeDatabase,\n ...normalizeParams(...params)\n );\n return composeRows<T>(columnNames, columnValuesList);\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 * Reset the prepared statement cursor.\n */\n public resetSync(): void {\n this.nativeStatement.resetSync(this.nativeDatabase);\n }\n\n /**\n * Finalize the prepared statement.\n *\n * > **Note:** Remember to finalize the prepared statement whenever you call `prepareSync()` to avoid resource leaks.\n *\n */\n public finalizeSync(): void {\n this.nativeStatement.finalizeSync(this.nativeDatabase);\n }\n\n //#endregion\n}\n\n/**\n * Normalize the bind params to data structure that can be passed to native module.\n * The data structure is a tuple of [primitiveParams, blobParams, shouldPassAsArray].\n * @hidden\n */\nexport function normalizeParams(...params: any[]): [BindPrimitiveParams, BindBlobParams, boolean] {\n let bindParams = params.length > 1 ? params : (params[0] as BindParams);\n if (bindParams == null) {\n bindParams = [];\n }\n if (\n typeof bindParams !== 'object' ||\n bindParams instanceof ArrayBuffer ||\n ArrayBuffer.isView(bindParams)\n ) {\n bindParams = [bindParams];\n }\n const shouldPassAsArray = Array.isArray(bindParams);\n if (Array.isArray(bindParams)) {\n bindParams = bindParams.reduce<Record<string, BindValue>>((acc, value, index) => {\n acc[index] = value;\n return acc;\n }, {});\n }\n\n const primitiveParams: BindPrimitiveParams = {};\n const blobParams: BindBlobParams = {};\n for (const key in bindParams) {\n const value = bindParams[key];\n if (value instanceof Uint8Array) {\n blobParams[key] = value;\n } else {\n primitiveParams[key] = value;\n }\n }\n\n return [primitiveParams, blobParams, shouldPassAsArray];\n}\n\n/**\n * Compose `columnNames` and `columnValues` to an row object.\n * @hidden\n */\nexport function composeRow<T>(columnNames: ColumnNames, columnValues: ColumnValues): T {\n const row = {};\n if (columnNames.length !== columnValues.length) {\n throw new Error(\n `Column names and values count mismatch. Names: ${columnNames.length}, Values: ${columnValues.length}`\n );\n }\n for (let i = 0; i < columnNames.length; i++) {\n row[columnNames[i]] = columnValues[i];\n }\n return row as T;\n}\n\n/**\n * Compose `columnNames` and `columnValuesList` to an array of row objects.\n * @hidden\n */\nexport function composeRows<T>(columnNames: ColumnNames, columnValuesList: ColumnValues[]): T[] {\n if (columnValuesList.length === 0) {\n return [];\n }\n if (columnNames.length !== columnValuesList[0].length) {\n // We only check the first row because SQLite returns the same column count for all rows.\n throw new Error(\n `Column names and values count mismatch. Names: ${columnNames.length}, Values: ${columnValuesList[0].length}`\n );\n }\n const results: T[] = [];\n for (const columnValues of columnValuesList) {\n const row = {};\n for (let i = 0; i < columnNames.length; i++) {\n row[columnNames[i]] = columnValues[i];\n }\n results.push(row as T);\n }\n return results;\n}\n"]}
|
package/ios/Exceptions.swift
CHANGED
|
@@ -52,6 +52,18 @@ internal class InvalidArgumentsException: Exception {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
internal class InvalidBindParameterException: Exception {
|
|
56
|
+
override var reason: String {
|
|
57
|
+
"Invalid bind parameter"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
internal class AccessClosedResourceException: Exception {
|
|
62
|
+
override var reason: String {
|
|
63
|
+
"Access to closed resource"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
55
67
|
internal class SQLiteErrorException: GenericException<String> {
|
|
56
68
|
override var code: String {
|
|
57
69
|
"ERR_INTERNAL_SQLITE_ERROR"
|
package/ios/NativeDatabase.swift
CHANGED
|
@@ -5,6 +5,7 @@ import ExpoModulesCore
|
|
|
5
5
|
final class NativeDatabase: SharedRef<OpaquePointer?>, Equatable, Hashable {
|
|
6
6
|
let dbName: String
|
|
7
7
|
let openOptions: OpenDatabaseOptions
|
|
8
|
+
var isClosed = false
|
|
8
9
|
|
|
9
10
|
init(_ pointer: OpaquePointer?, dbName: String, openOptions: OpenDatabaseOptions) {
|
|
10
11
|
self.dbName = dbName
|
package/ios/SQLiteModule.swift
CHANGED
|
@@ -63,12 +63,11 @@ public final class SQLiteModule: Module {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
private func pathForDatabaseName(name: String) -> URL? {
|
|
66
|
-
guard let
|
|
66
|
+
guard let path = appContext?.config.documentDirectory?.path else {
|
|
67
67
|
return nil
|
|
68
68
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
fileSystem.ensureDirExists(withPath: directory?.absoluteString)
|
|
69
|
+
let directory = URL(string: path)?.appendingPathComponent("SQLite")
|
|
70
|
+
FileSystemUtilities.ensureDirExists(at: directory)
|
|
72
71
|
|
|
73
72
|
return directory?.appendingPathComponent(name)
|
|
74
73
|
}
|
|
@@ -6,6 +6,7 @@ import sqlite3
|
|
|
6
6
|
private typealias ColumnNames = [String]
|
|
7
7
|
private typealias ColumnValues = [Any]
|
|
8
8
|
private let SQLITE_TRANSIENT = unsafeBitCast(OpaquePointer(bitPattern: -1), to: sqlite3_destructor_type.self)
|
|
9
|
+
private let MEMORY_DB_NAME = ":memory:"
|
|
9
10
|
|
|
10
11
|
public final class SQLiteModuleNext: Module {
|
|
11
12
|
// Store unmanaged (SQLiteModuleNext, Database) pairs for sqlite callbacks,
|
|
@@ -68,16 +69,18 @@ public final class SQLiteModuleNext: Module {
|
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
AsyncFunction("initAsync") { (database: NativeDatabase) in
|
|
71
|
-
initDb(database: database)
|
|
72
|
+
try initDb(database: database)
|
|
72
73
|
}
|
|
73
74
|
Function("initSync") { (database: NativeDatabase) in
|
|
74
|
-
initDb(database: database)
|
|
75
|
+
try initDb(database: database)
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
AsyncFunction("isInTransactionAsync") { (database: NativeDatabase) -> Bool in
|
|
79
|
+
try maybeThrowForClosedDatabase(database)
|
|
78
80
|
return sqlite3_get_autocommit(database.pointer) == 0
|
|
79
81
|
}
|
|
80
82
|
Function("isInTransactionSync") { (database: NativeDatabase) -> Bool in
|
|
83
|
+
try maybeThrowForClosedDatabase(database)
|
|
81
84
|
return sqlite3_get_autocommit(database.pointer) == 0
|
|
82
85
|
}
|
|
83
86
|
|
|
@@ -111,53 +114,36 @@ public final class SQLiteModuleNext: Module {
|
|
|
111
114
|
return NativeStatement()
|
|
112
115
|
}
|
|
113
116
|
|
|
114
|
-
|
|
115
|
-
return try arrayRun(statement: statement, database: database, bindParams: bindParams)
|
|
116
|
-
}
|
|
117
|
-
Function("arrayRunSync") { (statement: NativeStatement, database: NativeDatabase, bindParams: [Any]) -> [String: Int] in
|
|
118
|
-
return try arrayRun(statement: statement, database: database, bindParams: bindParams)
|
|
119
|
-
}
|
|
117
|
+
// swiftlint:disable line_length
|
|
120
118
|
|
|
121
|
-
AsyncFunction("
|
|
122
|
-
return try
|
|
119
|
+
AsyncFunction("runAsync") { (statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any], bindBlobParams: [String: Data], shouldPassAsArray: Bool) -> [String: Any] in
|
|
120
|
+
return try run(statement: statement, database: database, bindParams: bindParams, bindBlobParams: bindBlobParams, shouldPassAsArray: shouldPassAsArray)
|
|
123
121
|
}
|
|
124
|
-
Function("
|
|
125
|
-
return try
|
|
122
|
+
Function("runSync") { (statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any], bindBlobParams: [String: Data], shouldPassAsArray: Bool) -> [String: Int] in
|
|
123
|
+
return try run(statement: statement, database: database, bindParams: bindParams, bindBlobParams: bindBlobParams, shouldPassAsArray: shouldPassAsArray)
|
|
126
124
|
}
|
|
127
125
|
|
|
128
|
-
AsyncFunction("
|
|
129
|
-
return try
|
|
126
|
+
AsyncFunction("getAsync") { (statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any], bindBlobParams: [String: Data], shouldPassAsArray: Bool) -> ColumnValues? in
|
|
127
|
+
return try get(statement: statement, database: database, bindParams: bindParams, bindBlobParams: bindBlobParams, shouldPassAsArray: shouldPassAsArray)
|
|
130
128
|
}
|
|
131
|
-
Function("
|
|
132
|
-
return try
|
|
129
|
+
Function("getSync") { (statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any], bindBlobParams: [String: Data], shouldPassAsArray: Bool) -> ColumnValues? in
|
|
130
|
+
return try get(statement: statement, database: database, bindParams: bindParams, bindBlobParams: bindBlobParams, shouldPassAsArray: shouldPassAsArray)
|
|
133
131
|
}
|
|
134
132
|
|
|
135
|
-
AsyncFunction("
|
|
136
|
-
return try
|
|
133
|
+
AsyncFunction("getAllAsync") { (statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any], bindBlobParams: [String: Data], shouldPassAsArray: Bool) -> [ColumnValues] in
|
|
134
|
+
return try getAll(statement: statement, database: database, bindParams: bindParams, bindBlobParams: bindBlobParams, shouldPassAsArray: shouldPassAsArray)
|
|
137
135
|
}
|
|
138
|
-
Function("
|
|
139
|
-
return try
|
|
136
|
+
Function("getAllSync") { (statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any], bindBlobParams: [String: Data], shouldPassAsArray: Bool) -> [ColumnValues] in
|
|
137
|
+
return try getAll(statement: statement, database: database, bindParams: bindParams, bindBlobParams: bindBlobParams, shouldPassAsArray: shouldPassAsArray)
|
|
140
138
|
}
|
|
141
139
|
|
|
142
|
-
|
|
143
|
-
return try arrayGetAll(statement: statement, database: database, bindParams: bindParams)
|
|
144
|
-
}
|
|
145
|
-
Function("arrayGetAllSync") { (statement: NativeStatement, database: NativeDatabase, bindParams: [Any]) -> [ColumnValues] in
|
|
146
|
-
return try arrayGetAll(statement: statement, database: database, bindParams: bindParams)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
AsyncFunction("objectGetAllAsync") { (statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any]) -> [ColumnValues] in
|
|
150
|
-
return try objectGetAll(statement: statement, database: database, bindParams: bindParams)
|
|
151
|
-
}
|
|
152
|
-
Function("objectGetAllSync") { (statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any]) -> [ColumnValues] in
|
|
153
|
-
return try objectGetAll(statement: statement, database: database, bindParams: bindParams)
|
|
154
|
-
}
|
|
140
|
+
// swiftlint:enable line_length
|
|
155
141
|
|
|
156
142
|
AsyncFunction("getColumnNamesAsync") { (statement: NativeStatement) -> ColumnNames in
|
|
157
|
-
return getColumnNames(statement: statement)
|
|
143
|
+
return try getColumnNames(statement: statement)
|
|
158
144
|
}
|
|
159
145
|
Function("getColumnNamesSync") { (statement: NativeStatement) -> ColumnNames in
|
|
160
|
-
return getColumnNames(statement: statement)
|
|
146
|
+
return try getColumnNames(statement: statement)
|
|
161
147
|
}
|
|
162
148
|
|
|
163
149
|
AsyncFunction("resetAsync") { (statement: NativeStatement, database: NativeDatabase) in
|
|
@@ -177,6 +163,9 @@ public final class SQLiteModuleNext: Module {
|
|
|
177
163
|
}
|
|
178
164
|
|
|
179
165
|
private func pathForDatabaseName(name: String) -> URL? {
|
|
166
|
+
if name == MEMORY_DB_NAME {
|
|
167
|
+
return URL(string: name)
|
|
168
|
+
}
|
|
180
169
|
guard let fileSystem = appContext?.fileSystem else {
|
|
181
170
|
return nil
|
|
182
171
|
}
|
|
@@ -187,7 +176,8 @@ public final class SQLiteModuleNext: Module {
|
|
|
187
176
|
return directory?.appendingPathComponent(name)
|
|
188
177
|
}
|
|
189
178
|
|
|
190
|
-
private func initDb(database: NativeDatabase) {
|
|
179
|
+
private func initDb(database: NativeDatabase) throws {
|
|
180
|
+
try maybeThrowForClosedDatabase(database)
|
|
191
181
|
if database.openOptions.enableCRSQLite {
|
|
192
182
|
crsqlite_init_from_swift(database.pointer)
|
|
193
183
|
}
|
|
@@ -197,6 +187,7 @@ public final class SQLiteModuleNext: Module {
|
|
|
197
187
|
}
|
|
198
188
|
|
|
199
189
|
private func exec(database: NativeDatabase, source: String) throws {
|
|
190
|
+
try maybeThrowForClosedDatabase(database)
|
|
200
191
|
var error: UnsafeMutablePointer<CChar>?
|
|
201
192
|
let ret = sqlite3_exec(database.pointer, source, nil, nil, &error)
|
|
202
193
|
if ret != SQLITE_OK, let error = error {
|
|
@@ -207,33 +198,32 @@ public final class SQLiteModuleNext: Module {
|
|
|
207
198
|
}
|
|
208
199
|
|
|
209
200
|
private func prepareStatement(database: NativeDatabase, statement: NativeStatement, source: String) throws {
|
|
201
|
+
try maybeThrowForClosedDatabase(database)
|
|
202
|
+
try maybeThrowForFinalizedStatement(statement)
|
|
210
203
|
if sqlite3_prepare_v2(database.pointer, source, Int32(source.count), &statement.pointer, nil) != SQLITE_OK {
|
|
211
204
|
throw SQLiteErrorException(convertSqlLiteErrorToString(database))
|
|
212
205
|
}
|
|
213
206
|
maybeAddCachedStatement(database: database, statement: statement)
|
|
214
207
|
}
|
|
215
208
|
|
|
216
|
-
|
|
217
|
-
for (index, param) in bindParams.enumerated() {
|
|
218
|
-
try bindStatementParam(statement: statement, with: param, at: Int32(index + 1))
|
|
219
|
-
}
|
|
220
|
-
let ret = sqlite3_step(statement.pointer)
|
|
221
|
-
if ret != SQLITE_ROW && ret != SQLITE_DONE {
|
|
222
|
-
throw SQLiteErrorException(convertSqlLiteErrorToString(database))
|
|
223
|
-
}
|
|
224
|
-
return [
|
|
225
|
-
"lastInsertRowid": Int(sqlite3_last_insert_rowid(database.pointer)),
|
|
226
|
-
"changes": Int(sqlite3_changes(database.pointer))
|
|
227
|
-
]
|
|
228
|
-
}
|
|
209
|
+
// swiftlint:disable line_length
|
|
229
210
|
|
|
230
|
-
private func
|
|
231
|
-
|
|
232
|
-
|
|
211
|
+
private func run(statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any], bindBlobParams: [String: Data], shouldPassAsArray: Bool) throws -> [String: Int] {
|
|
212
|
+
try maybeThrowForClosedDatabase(database)
|
|
213
|
+
try maybeThrowForFinalizedStatement(statement)
|
|
214
|
+
for (key, param) in bindParams {
|
|
215
|
+
let index = try getBindParamIndex(statement: statement, key: key, shouldPassAsArray: shouldPassAsArray)
|
|
216
|
+
if index > 0 {
|
|
217
|
+
try bindStatementParam(statement: statement, with: param, at: index)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
for (key, param) in bindBlobParams {
|
|
221
|
+
let index = try getBindParamIndex(statement: statement, key: key, shouldPassAsArray: shouldPassAsArray)
|
|
233
222
|
if index > 0 {
|
|
234
223
|
try bindStatementParam(statement: statement, with: param, at: index)
|
|
235
224
|
}
|
|
236
225
|
}
|
|
226
|
+
|
|
237
227
|
let ret = sqlite3_step(statement.pointer)
|
|
238
228
|
if ret != SQLITE_ROW && ret != SQLITE_DONE {
|
|
239
229
|
throw SQLiteErrorException(convertSqlLiteErrorToString(database))
|
|
@@ -244,27 +234,22 @@ public final class SQLiteModuleNext: Module {
|
|
|
244
234
|
]
|
|
245
235
|
}
|
|
246
236
|
|
|
247
|
-
private func
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
if ret != SQLITE_DONE {
|
|
256
|
-
throw SQLiteErrorException(convertSqlLiteErrorToString(database))
|
|
237
|
+
private func get(statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any], bindBlobParams: [String: Data], shouldPassAsArray: Bool) throws -> ColumnValues? {
|
|
238
|
+
try maybeThrowForClosedDatabase(database)
|
|
239
|
+
try maybeThrowForFinalizedStatement(statement)
|
|
240
|
+
for (key, param) in bindParams {
|
|
241
|
+
let index = try getBindParamIndex(statement: statement, key: key, shouldPassAsArray: shouldPassAsArray)
|
|
242
|
+
if index > 0 {
|
|
243
|
+
try bindStatementParam(statement: statement, with: param, at: index)
|
|
244
|
+
}
|
|
257
245
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
private func objectGet(statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any]) throws -> ColumnValues? {
|
|
262
|
-
for (name, param) in bindParams {
|
|
263
|
-
let index = sqlite3_bind_parameter_index(statement.pointer, name.cString(using: .utf8))
|
|
246
|
+
for (key, param) in bindBlobParams {
|
|
247
|
+
let index = try getBindParamIndex(statement: statement, key: key, shouldPassAsArray: shouldPassAsArray)
|
|
264
248
|
if index > 0 {
|
|
265
249
|
try bindStatementParam(statement: statement, with: param, at: index)
|
|
266
250
|
}
|
|
267
251
|
}
|
|
252
|
+
|
|
268
253
|
let ret = sqlite3_step(statement.pointer)
|
|
269
254
|
if ret == SQLITE_ROW {
|
|
270
255
|
return try getColumnValues(statement: statement)
|
|
@@ -275,31 +260,22 @@ public final class SQLiteModuleNext: Module {
|
|
|
275
260
|
return nil
|
|
276
261
|
}
|
|
277
262
|
|
|
278
|
-
private func
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if ret == SQLITE_ROW {
|
|
286
|
-
columnValuesList.append(try getColumnValues(statement: statement))
|
|
287
|
-
continue
|
|
288
|
-
} else if ret == SQLITE_DONE {
|
|
289
|
-
break
|
|
263
|
+
private func getAll(statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any], bindBlobParams: [String: Data], shouldPassAsArray: Bool) throws -> [ColumnValues] {
|
|
264
|
+
try maybeThrowForClosedDatabase(database)
|
|
265
|
+
try maybeThrowForFinalizedStatement(statement)
|
|
266
|
+
for (key, param) in bindParams {
|
|
267
|
+
let index = try getBindParamIndex(statement: statement, key: key, shouldPassAsArray: shouldPassAsArray)
|
|
268
|
+
if index > 0 {
|
|
269
|
+
try bindStatementParam(statement: statement, with: param, at: index)
|
|
290
270
|
}
|
|
291
|
-
throw SQLiteErrorException(convertSqlLiteErrorToString(database))
|
|
292
271
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
private func objectGetAll(statement: NativeStatement, database: NativeDatabase, bindParams: [String: Any]) throws -> [ColumnValues] {
|
|
297
|
-
for (name, param) in bindParams {
|
|
298
|
-
let index = sqlite3_bind_parameter_index(statement.pointer, name.cString(using: .utf8))
|
|
272
|
+
for (key, param) in bindBlobParams {
|
|
273
|
+
let index = try getBindParamIndex(statement: statement, key: key, shouldPassAsArray: shouldPassAsArray)
|
|
299
274
|
if index > 0 {
|
|
300
275
|
try bindStatementParam(statement: statement, with: param, at: index)
|
|
301
276
|
}
|
|
302
277
|
}
|
|
278
|
+
|
|
303
279
|
var columnValuesList: [ColumnValues] = []
|
|
304
280
|
while true {
|
|
305
281
|
let ret = sqlite3_step(statement.pointer)
|
|
@@ -314,17 +290,24 @@ public final class SQLiteModuleNext: Module {
|
|
|
314
290
|
return columnValuesList
|
|
315
291
|
}
|
|
316
292
|
|
|
293
|
+
// swiftlint:enable line_length
|
|
294
|
+
|
|
317
295
|
private func reset(statement: NativeStatement, database: NativeDatabase) throws {
|
|
296
|
+
try maybeThrowForClosedDatabase(database)
|
|
297
|
+
try maybeThrowForFinalizedStatement(statement)
|
|
318
298
|
if sqlite3_reset(statement.pointer) != SQLITE_OK {
|
|
319
299
|
throw SQLiteErrorException(convertSqlLiteErrorToString(database))
|
|
320
300
|
}
|
|
321
301
|
}
|
|
322
302
|
|
|
323
303
|
private func finalize(statement: NativeStatement, database: NativeDatabase) throws {
|
|
304
|
+
try maybeThrowForClosedDatabase(database)
|
|
305
|
+
try maybeThrowForFinalizedStatement(statement)
|
|
324
306
|
maybeRemoveCachedStatement(database: database, statement: statement)
|
|
325
307
|
if sqlite3_finalize(statement.pointer) != SQLITE_OK {
|
|
326
308
|
throw SQLiteErrorException(convertSqlLiteErrorToString(database))
|
|
327
309
|
}
|
|
310
|
+
statement.isFinalized = true
|
|
328
311
|
}
|
|
329
312
|
|
|
330
313
|
private func convertSqlLiteErrorToString(_ db: NativeDatabase) -> String {
|
|
@@ -334,6 +317,7 @@ public final class SQLiteModuleNext: Module {
|
|
|
334
317
|
}
|
|
335
318
|
|
|
336
319
|
private func closeDatabase(_ db: NativeDatabase) throws {
|
|
320
|
+
try maybeThrowForClosedDatabase(db)
|
|
337
321
|
for removedStatement in maybeRemoveAllCachedStatements(database: db) {
|
|
338
322
|
sqlite3_finalize(removedStatement.pointer)
|
|
339
323
|
}
|
|
@@ -342,6 +326,7 @@ public final class SQLiteModuleNext: Module {
|
|
|
342
326
|
sqlite3_exec(db.pointer, "SELECT crsql_finalize()", nil, nil, nil)
|
|
343
327
|
}
|
|
344
328
|
let ret = sqlite3_close(db.pointer)
|
|
329
|
+
db.isClosed = true
|
|
345
330
|
|
|
346
331
|
if let index = contextPairs.firstIndex(where: {
|
|
347
332
|
guard let pair = $0.takeUnretainedValue() as? (SQLiteModuleNext, NativeDatabase) else {
|
|
@@ -366,6 +351,9 @@ public final class SQLiteModuleNext: Module {
|
|
|
366
351
|
throw DeleteDatabaseException(dbName)
|
|
367
352
|
}
|
|
368
353
|
|
|
354
|
+
if dbName == MEMORY_DB_NAME {
|
|
355
|
+
return
|
|
356
|
+
}
|
|
369
357
|
guard let path = pathForDatabaseName(name: dbName) else {
|
|
370
358
|
throw Exceptions.FileSystemModuleNotFound()
|
|
371
359
|
}
|
|
@@ -407,7 +395,8 @@ public final class SQLiteModuleNext: Module {
|
|
|
407
395
|
contextPair.toOpaque())
|
|
408
396
|
}
|
|
409
397
|
|
|
410
|
-
private func getColumnNames(statement: NativeStatement) -> ColumnNames {
|
|
398
|
+
private func getColumnNames(statement: NativeStatement) throws -> ColumnNames {
|
|
399
|
+
try maybeThrowForFinalizedStatement(statement)
|
|
411
400
|
let columnCount = Int(sqlite3_column_count(statement.pointer))
|
|
412
401
|
var columnNames: ColumnNames = Array(repeating: "", count: columnCount)
|
|
413
402
|
for i in 0..<columnCount {
|
|
@@ -417,6 +406,7 @@ public final class SQLiteModuleNext: Module {
|
|
|
417
406
|
}
|
|
418
407
|
|
|
419
408
|
private func getColumnValues(statement: NativeStatement) throws -> ColumnValues {
|
|
409
|
+
try maybeThrowForFinalizedStatement(statement)
|
|
420
410
|
let columnCount = Int(sqlite3_column_count(statement.pointer))
|
|
421
411
|
var columnValues: ColumnValues = Array(repeating: 0, count: columnCount)
|
|
422
412
|
for i in 0..<columnCount {
|
|
@@ -465,7 +455,7 @@ public final class SQLiteModuleNext: Module {
|
|
|
465
455
|
case let param as Double:
|
|
466
456
|
sqlite3_bind_double(instance, index, param)
|
|
467
457
|
case let param as String:
|
|
468
|
-
sqlite3_bind_text(instance, index, param,
|
|
458
|
+
sqlite3_bind_text(instance, index, param, -1, SQLITE_TRANSIENT)
|
|
469
459
|
case let param as Data:
|
|
470
460
|
_ = param.withUnsafeBytes {
|
|
471
461
|
sqlite3_bind_blob(instance, index, $0.baseAddress, Int32(param.count), SQLITE_TRANSIENT)
|
|
@@ -477,6 +467,32 @@ public final class SQLiteModuleNext: Module {
|
|
|
477
467
|
}
|
|
478
468
|
}
|
|
479
469
|
|
|
470
|
+
private func maybeThrowForClosedDatabase(_ database: NativeDatabase) throws {
|
|
471
|
+
if database.isClosed {
|
|
472
|
+
throw AccessClosedResourceException()
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
private func maybeThrowForFinalizedStatement(_ statement: NativeStatement) throws {
|
|
477
|
+
if statement.isFinalized {
|
|
478
|
+
throw AccessClosedResourceException()
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
@inline(__always)
|
|
483
|
+
private func getBindParamIndex(statement: NativeStatement, key: String, shouldPassAsArray: Bool) throws -> Int32 {
|
|
484
|
+
let index: Int32
|
|
485
|
+
if shouldPassAsArray {
|
|
486
|
+
guard let intKey = Int32(key) else {
|
|
487
|
+
throw InvalidBindParameterException()
|
|
488
|
+
}
|
|
489
|
+
index = intKey + 1
|
|
490
|
+
} else {
|
|
491
|
+
index = sqlite3_bind_parameter_index(statement.pointer, key.cString(using: .utf8))
|
|
492
|
+
}
|
|
493
|
+
return index
|
|
494
|
+
}
|
|
495
|
+
|
|
480
496
|
// MARK: - cachedDatabases managements
|
|
481
497
|
|
|
482
498
|
private func addCachedDatabase(_ database: NativeDatabase) {
|