@capacitor-community/sqlite 5.5.2 → 5.6.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/README.md +2 -0
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLite.java +1 -1
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/Database.java +216 -219
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/ExportToJson.java +1 -1
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/ImportFromJson.java +103 -102
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsFile.java +1 -1
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsMigrate.java +1 -1
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsSQLStatement.java +1 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web-typeorm-utils/database.d.ts +21 -0
- package/dist/esm/web-typeorm-utils/database.js +91 -0
- package/dist/esm/web-typeorm-utils/database.js.map +1 -0
- package/dist/esm/web-typeorm-utils/utilsSQLite.d.ts +28 -0
- package/dist/esm/web-typeorm-utils/utilsSQLite.js +233 -0
- package/dist/esm/web-typeorm-utils/utilsSQLite.js.map +1 -0
- package/dist/esm/web.d.ts +4 -2
- package/dist/esm/web.js +210 -56
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +519 -49
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +519 -49
- package/dist/plugin.js.map +1 -1
- package/electron/dist/plugin.js +11 -5
- package/electron/dist/plugin.js.map +1 -1
- package/ios/Plugin/CapacitorSQLite.swift +3 -4
- package/ios/Plugin/Utils/UtilsDelete.swift +1 -1
- package/ios/Plugin/Utils/UtilsSQLCipher.swift +1 -2
- package/ios/Plugin/Utils/UtilsSQLStatement.swift +35 -37
- package/package.json +6 -6
- package/src/definitions.ts +0 -1
- package/src/web-typeorm-utils/database.ts +111 -0
- package/src/web-typeorm-utils/utilsSQLite.ts +249 -0
- package/src/web.ts +212 -62
|
@@ -1012,7 +1012,6 @@ enum CapacitorSQLiteError: Error {
|
|
|
1012
1012
|
|
|
1013
1013
|
// MARK: - deleteDatabase
|
|
1014
1014
|
|
|
1015
|
-
// swiftlint:disable function_body_length
|
|
1016
1015
|
// swiftlint:disable cyclomatic_complexity
|
|
1017
1016
|
@objc func deleteDatabase(_ dbName: String, readonly: Bool) throws {
|
|
1018
1017
|
guard isInit else {
|
|
@@ -1032,8 +1031,9 @@ enum CapacitorSQLiteError: Error {
|
|
|
1032
1031
|
if !mDb.isDBOpen() {
|
|
1033
1032
|
// check the state of the DB
|
|
1034
1033
|
let state: State = UtilsSQLCipher.getDatabaseState(databaseLocation: databaseLocation, databaseName: "\(mDbName)SQLite.db", account: account)
|
|
1035
|
-
if !isEncryption &&
|
|
1036
|
-
|
|
1034
|
+
if !isEncryption &&
|
|
1035
|
+
(state.rawValue == "ENCRYPTEDGLOBALSECRET" ||
|
|
1036
|
+
state.rawValue == "ENCRYPTEDSECRET") {
|
|
1037
1037
|
var msg = "Cannot delete an Encrypted database with "
|
|
1038
1038
|
msg += "No Encryption set in capacitor.config"
|
|
1039
1039
|
throw CapacitorSQLiteError.failed(message: msg)
|
|
@@ -1067,7 +1067,6 @@ enum CapacitorSQLiteError: Error {
|
|
|
1067
1067
|
}
|
|
1068
1068
|
}
|
|
1069
1069
|
// swiftlint:enable cyclomatic_complexity
|
|
1070
|
-
// swiftlint:enable function_body_length
|
|
1071
1070
|
|
|
1072
1071
|
// MARK: - isJsonValid
|
|
1073
1072
|
|
|
@@ -290,7 +290,7 @@ class UtilsDelete {
|
|
|
290
290
|
var relatedItems: [[String: Any]] = []
|
|
291
291
|
var key: String = ""
|
|
292
292
|
let t1Names = withRefsNames.map { "t1.\($0)" }
|
|
293
|
-
let t2Names = colNames.map{ "t2.\($0)" }
|
|
293
|
+
let t2Names = colNames.map { "t2.\($0)" }
|
|
294
294
|
|
|
295
295
|
do {
|
|
296
296
|
var whereClause = try UtilsSQLStatement
|
|
@@ -447,7 +447,7 @@ class UtilsSQLCipher {
|
|
|
447
447
|
msg.append("Database not opened")
|
|
448
448
|
throw UtilsSQLCipherError.prepareSQL(message: msg)
|
|
449
449
|
}
|
|
450
|
-
// let systemVersion = UIDevice.current.systemVersion
|
|
450
|
+
// let systemVersion = UIDevice.current.systemVersion
|
|
451
451
|
var runSQLStatement: OpaquePointer?
|
|
452
452
|
var message: String = ""
|
|
453
453
|
var lastId: Int64 = -1
|
|
@@ -554,7 +554,6 @@ class UtilsSQLCipher {
|
|
|
554
554
|
return (lastId, result)
|
|
555
555
|
}
|
|
556
556
|
}
|
|
557
|
-
|
|
558
557
|
|
|
559
558
|
// MARK: - returningWorkAround
|
|
560
559
|
|
|
@@ -327,51 +327,49 @@ class UtilsSQLStatement {
|
|
|
327
327
|
|
|
328
328
|
class func isReturning(sqlStmt: String) -> (Bool, String, String) {
|
|
329
329
|
var stmt = sqlStmt.replacingOccurrences(of: "\n", with: "")
|
|
330
|
-
|
|
330
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
331
331
|
if stmt.hasSuffix(";") {
|
|
332
332
|
// Remove the suffix
|
|
333
333
|
stmt = String(stmt.dropLast())
|
|
334
|
-
|
|
334
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
335
335
|
}
|
|
336
336
|
|
|
337
|
-
switch
|
|
338
|
-
|
|
339
|
-
|
|
337
|
+
switch stmt.prefix(6).uppercased() {
|
|
338
|
+
|
|
339
|
+
case "INSERT":
|
|
340
340
|
if let valuesIndex = stmt.range(of: "VALUES", options: .caseInsensitive)?.lowerBound,
|
|
341
341
|
let closingParenthesisIndex = stmt.range(of: ")", options: .backwards, range: valuesIndex..<stmt.endIndex)?.upperBound {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
342
|
+
guard closingParenthesisIndex < stmt.endIndex else {
|
|
343
|
+
stmt += ";"
|
|
344
|
+
return (false, stmt, "")
|
|
345
|
+
}
|
|
346
346
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
347
|
+
let intParenthesisValue = stmt.distance(from: stmt.startIndex, to: closingParenthesisIndex)
|
|
348
|
+
let substringAfterValues = stmt[closingParenthesisIndex...]
|
|
349
|
+
var resultString = String(substringAfterValues)
|
|
350
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
351
|
+
if resultString.count > 0 && !resultString.hasSuffix(";") {
|
|
352
|
+
resultString += ";"
|
|
353
|
+
}
|
|
354
354
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
355
|
+
let substringStartToEndParenthesis = stmt[...closingParenthesisIndex]
|
|
356
|
+
let stmtString = String(substringStartToEndParenthesis)
|
|
357
|
+
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
358
|
+
.appending(";")
|
|
359
359
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
}
|
|
360
|
+
if substringAfterValues.lowercased().contains("returning") {
|
|
361
|
+
return (true, stmtString, resultString)
|
|
362
|
+
} else {
|
|
363
|
+
return (false, stmt, "")
|
|
365
364
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
365
|
+
}
|
|
366
|
+
return (false, stmt, "")
|
|
367
|
+
|
|
368
|
+
case "DELETE", "UPDATE":
|
|
370
369
|
let words = stmt.components(separatedBy: .whitespacesAndNewlines)
|
|
371
370
|
var wordsBeforeReturning: [String] = []
|
|
372
371
|
var returningString: [String] = []
|
|
373
372
|
|
|
374
|
-
|
|
375
373
|
var isReturningOutsideMessage = false
|
|
376
374
|
for word in words {
|
|
377
375
|
if word.lowercased() == "returning" {
|
|
@@ -387,7 +385,7 @@ class UtilsSQLStatement {
|
|
|
387
385
|
let joinedWords = wordsBeforeReturning.joined(separator: " ") + ";"
|
|
388
386
|
var joinedReturningString = returningString.joined(separator: " ")
|
|
389
387
|
if joinedReturningString.count > 0 &&
|
|
390
|
-
|
|
388
|
+
!joinedReturningString.hasSuffix(";") {
|
|
391
389
|
joinedReturningString += ";"
|
|
392
390
|
}
|
|
393
391
|
|
|
@@ -395,11 +393,11 @@ class UtilsSQLStatement {
|
|
|
395
393
|
} else {
|
|
396
394
|
return (false, stmt, "")
|
|
397
395
|
}
|
|
398
|
-
|
|
399
|
-
|
|
396
|
+
|
|
397
|
+
default:
|
|
400
398
|
return (false, stmt, "")
|
|
401
399
|
}
|
|
402
|
-
|
|
400
|
+
|
|
403
401
|
}
|
|
404
402
|
|
|
405
403
|
// MARK: - wordsAfter
|
|
@@ -410,13 +408,13 @@ class UtilsSQLStatement {
|
|
|
410
408
|
}
|
|
411
409
|
return Array(words.suffix(from: index + 1))
|
|
412
410
|
}
|
|
413
|
-
|
|
411
|
+
|
|
414
412
|
// MARK: - getStmtAndRetColNames
|
|
415
413
|
|
|
416
414
|
class func getStmtAndRetColNames(sqlStmt: String, retMode: String)
|
|
417
415
|
-> [String: String] {
|
|
418
416
|
var retStmtNames: [String: String] = [:]
|
|
419
|
-
|
|
417
|
+
|
|
420
418
|
let (isReturning, stmt, suffix) = isReturning(sqlStmt: sqlStmt)
|
|
421
419
|
retStmtNames["stmt"] = stmt
|
|
422
420
|
retStmtNames["names"] = ""
|
|
@@ -426,7 +424,7 @@ class UtilsSQLStatement {
|
|
|
426
424
|
let substring = suffix[returningIndex.upperBound...]
|
|
427
425
|
|
|
428
426
|
let names =
|
|
429
|
-
|
|
427
|
+
"\(substring)".trimmingLeadingAndTrailingSpaces()
|
|
430
428
|
if names.suffix(1) == ";" {
|
|
431
429
|
retStmtNames["names"] = String(names.dropLast())
|
|
432
430
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor-community/sqlite",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.6.0",
|
|
4
4
|
"description": "Community plugin for native & electron SQLite databases",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
"prepublishOnly": "npm run build && npm run build-electron && npm run docgen"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@capacitor/android": "^5.
|
|
63
|
-
"@capacitor/cli": "^5.
|
|
64
|
-
"@capacitor/core": "^5.
|
|
62
|
+
"@capacitor/android": "^5.6.0",
|
|
63
|
+
"@capacitor/cli": "^5.6.0",
|
|
64
|
+
"@capacitor/core": "^5.6.0",
|
|
65
65
|
"@capacitor/docgen": "^0.0.17",
|
|
66
|
-
"@capacitor/ios": "^5.
|
|
66
|
+
"@capacitor/ios": "^5.6.0",
|
|
67
67
|
"@ionic/eslint-config": "^0.3.0",
|
|
68
68
|
"@ionic/prettier-config": "^1.0.1",
|
|
69
69
|
"@ionic/swiftlint-config": "^1.1.2",
|
|
@@ -97,6 +97,6 @@
|
|
|
97
97
|
}
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
|
-
"jeep-sqlite": "^2.5.
|
|
100
|
+
"jeep-sqlite": "^2.5.9"
|
|
101
101
|
}
|
|
102
102
|
}
|
package/src/definitions.ts
CHANGED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/************************************************
|
|
2
|
+
* Only to be used to run TypeOrm Cli
|
|
3
|
+
* migration:generate
|
|
4
|
+
* A in-memory database is used
|
|
5
|
+
************************************************
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { capSQLiteChanges, capSQLiteValues } from '../definitions';
|
|
9
|
+
|
|
10
|
+
import { UtilsSQLite } from './utilsSQLite';
|
|
11
|
+
|
|
12
|
+
export class Database {
|
|
13
|
+
private _isDBOpen: boolean;
|
|
14
|
+
private wasmPath = 'assets';
|
|
15
|
+
private sqliteUtil: UtilsSQLite = new UtilsSQLite();
|
|
16
|
+
private typeOrmDBFolder = this.sqliteUtil.getTypeOrmDBFolder();
|
|
17
|
+
private dbPath = '';
|
|
18
|
+
public mDb: any;
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
this.mDb = null;
|
|
22
|
+
this._isDBOpen = false;
|
|
23
|
+
}
|
|
24
|
+
public async open(dbName: string): Promise<void> {
|
|
25
|
+
try {
|
|
26
|
+
this.dbPath = this.sqliteUtil.getTypeOrmDBPath(
|
|
27
|
+
this.typeOrmDBFolder,
|
|
28
|
+
`${dbName}SQLite.db`,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
this.mDb = await this.sqliteUtil.openOrCreateDatabase(
|
|
32
|
+
this.wasmPath,
|
|
33
|
+
this.dbPath,
|
|
34
|
+
);
|
|
35
|
+
this._isDBOpen = true;
|
|
36
|
+
return Promise.resolve();
|
|
37
|
+
} catch (err) {
|
|
38
|
+
return Promise.reject(`Open: ${err}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
public async close(): Promise<void> {
|
|
42
|
+
try {
|
|
43
|
+
if (this._isDBOpen) {
|
|
44
|
+
await this.sqliteUtil.saveDatabase(this.mDb, this.dbPath);
|
|
45
|
+
await this.mDb.close();
|
|
46
|
+
}
|
|
47
|
+
return Promise.resolve();
|
|
48
|
+
} catch (err) {
|
|
49
|
+
return Promise.reject(`Close: ${err}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public async executeSQL(statements: string): Promise<number> {
|
|
54
|
+
let changes = -1;
|
|
55
|
+
try {
|
|
56
|
+
if (this._isDBOpen) {
|
|
57
|
+
const initChanges = await this.sqliteUtil.dbChanges(this.mDb);
|
|
58
|
+
changes = await this.sqliteUtil.execute(this.mDb, statements);
|
|
59
|
+
if (changes < 0) {
|
|
60
|
+
return Promise.reject(new Error('ExecuteSQL: changes < 0'));
|
|
61
|
+
}
|
|
62
|
+
changes = (await this.sqliteUtil.dbChanges(this.mDb)) - initChanges;
|
|
63
|
+
}
|
|
64
|
+
return Promise.resolve(changes);
|
|
65
|
+
} catch (err) {
|
|
66
|
+
return Promise.reject(`ExecuteSQL: ${err}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
public async run(
|
|
70
|
+
statement: string,
|
|
71
|
+
values: any[],
|
|
72
|
+
returnMode: string,
|
|
73
|
+
): Promise<capSQLiteChanges> {
|
|
74
|
+
const retRes: any = { changes: -1, lastId: -1 };
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
if (this._isDBOpen) {
|
|
78
|
+
const initChanges = await this.sqliteUtil.dbChanges(this.mDb);
|
|
79
|
+
const retObj = await this.sqliteUtil.run(
|
|
80
|
+
this.mDb,
|
|
81
|
+
statement,
|
|
82
|
+
values,
|
|
83
|
+
returnMode,
|
|
84
|
+
);
|
|
85
|
+
const lastId = retObj['lastId'];
|
|
86
|
+
if (lastId < 0) {
|
|
87
|
+
return Promise.reject(new Error('RunSQL: lastId < 0'));
|
|
88
|
+
}
|
|
89
|
+
const changes =
|
|
90
|
+
(await this.sqliteUtil.dbChanges(this.mDb)) - initChanges;
|
|
91
|
+
retRes.changes = changes;
|
|
92
|
+
retRes.lastId = lastId;
|
|
93
|
+
retRes.values = retObj['values'] ? retObj['values'] : [];
|
|
94
|
+
}
|
|
95
|
+
return Promise.resolve({ changes: retRes });
|
|
96
|
+
} catch (err) {
|
|
97
|
+
return Promise.reject(`Run: ${err}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
public async selectSQL(sql: string, values: any[]): Promise<capSQLiteValues> {
|
|
101
|
+
let retArr: any[] = [];
|
|
102
|
+
try {
|
|
103
|
+
if (this._isDBOpen) {
|
|
104
|
+
retArr = await this.sqliteUtil.queryAll(this.mDb, sql, values);
|
|
105
|
+
}
|
|
106
|
+
return Promise.resolve({ values: retArr });
|
|
107
|
+
} catch (err) {
|
|
108
|
+
return Promise.reject(`SelectSQL: ${err}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/************************************************
|
|
2
|
+
* Only to be used to run TypeOrm Cli
|
|
3
|
+
* migration:generate
|
|
4
|
+
* A in-memory database is used
|
|
5
|
+
************************************************
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export class UtilsSQLite {
|
|
9
|
+
public initSqlJs: any;
|
|
10
|
+
public FS: any;
|
|
11
|
+
public OS: any;
|
|
12
|
+
public Path: any;
|
|
13
|
+
private isExists = false;
|
|
14
|
+
private retExists = { isExists: false, pathWasm: '' };
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
this.initSqlJs = require('sql.js');
|
|
18
|
+
this.OS = require('os');
|
|
19
|
+
this.FS = require('fs');
|
|
20
|
+
this.Path = require('path');
|
|
21
|
+
}
|
|
22
|
+
public getTypeOrmDBFolder(): string {
|
|
23
|
+
// Find the index of the "node_modules" string in the path
|
|
24
|
+
const nodeModulesIndex = __dirname.indexOf('node_modules');
|
|
25
|
+
|
|
26
|
+
// Extract the part of the path before "node_modules"
|
|
27
|
+
const outputPath = __dirname.slice(0, nodeModulesIndex);
|
|
28
|
+
|
|
29
|
+
// Extract the App name
|
|
30
|
+
const appName = this.Path.basename(outputPath);
|
|
31
|
+
|
|
32
|
+
// Get the Documents path
|
|
33
|
+
const documentsDirectory = this.Path.join(this.OS.homedir(), 'Documents');
|
|
34
|
+
|
|
35
|
+
// Add "CapacitorSQLite" and appName
|
|
36
|
+
const outputFolderPath = this.Path.join(
|
|
37
|
+
documentsDirectory,
|
|
38
|
+
'CapacitorSQLite',
|
|
39
|
+
appName,
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Ensure the output folder exists
|
|
43
|
+
this.FS.mkdirSync(outputFolderPath, { recursive: true });
|
|
44
|
+
return outputFolderPath;
|
|
45
|
+
}
|
|
46
|
+
public getTypeOrmDBPath(outputFolderPath: string, dbName: string): string {
|
|
47
|
+
return this.Path.resolve(outputFolderPath, dbName);
|
|
48
|
+
}
|
|
49
|
+
public async checkFileExistence(wasmPath: string): Promise<any> {
|
|
50
|
+
// check if a public folder exists
|
|
51
|
+
const folder = (await this.checkFolderExistence('public'))
|
|
52
|
+
? 'public'
|
|
53
|
+
: 'src';
|
|
54
|
+
const pathWasm = this.Path.join(folder, wasmPath);
|
|
55
|
+
const retObj: any = {};
|
|
56
|
+
retObj.pathWasm = pathWasm;
|
|
57
|
+
try {
|
|
58
|
+
if (this.FS.existsSync(pathWasm)) {
|
|
59
|
+
retObj.isExists = true;
|
|
60
|
+
return Promise.resolve(retObj);
|
|
61
|
+
} else {
|
|
62
|
+
retObj.isExists = false;
|
|
63
|
+
return Promise.resolve(retObj);
|
|
64
|
+
}
|
|
65
|
+
} catch (err) {
|
|
66
|
+
retObj.isExists = false;
|
|
67
|
+
return Promise.resolve(retObj);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
public async checkFolderExistence(folder: string): Promise<boolean> {
|
|
71
|
+
try {
|
|
72
|
+
if (this.FS.existsSync(folder)) {
|
|
73
|
+
return Promise.resolve(true);
|
|
74
|
+
} else {
|
|
75
|
+
return Promise.resolve(false);
|
|
76
|
+
}
|
|
77
|
+
} catch (err) {
|
|
78
|
+
return Promise.resolve(false);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
public async openOrCreateDatabase(
|
|
82
|
+
wasmPath: string,
|
|
83
|
+
databasePath: string,
|
|
84
|
+
): Promise<any> {
|
|
85
|
+
let mDB: any;
|
|
86
|
+
const msg = 'OpenOrCreateDatabase';
|
|
87
|
+
try {
|
|
88
|
+
this.retExists = await this.checkFileExistence(wasmPath);
|
|
89
|
+
this.isExists = this.retExists.isExists;
|
|
90
|
+
} catch (err) {
|
|
91
|
+
this.isExists = false;
|
|
92
|
+
}
|
|
93
|
+
if (!this.isExists) {
|
|
94
|
+
return Promise.reject(msg + ' No sql-wasm.wasm found in ' + wasmPath);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const config = {
|
|
99
|
+
locateFile: (file: any) => `${this.retExists.pathWasm}/${file}`,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const SQL = await this.initSqlJs(config);
|
|
103
|
+
// Check if the database exists
|
|
104
|
+
if (!this.FS.existsSync(databasePath)) {
|
|
105
|
+
mDB = new SQL.Database();
|
|
106
|
+
} else {
|
|
107
|
+
// Read the database file from the local disk
|
|
108
|
+
const fileBuffer = this.FS.readFileSync(databasePath);
|
|
109
|
+
// Create a new database instance
|
|
110
|
+
mDB = new SQL.Database(fileBuffer);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return Promise.resolve(mDB);
|
|
114
|
+
} catch (err: any) {
|
|
115
|
+
return Promise.reject(msg + ' open database failed');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
public async saveDatabase(mDb: any, outputPath: string): Promise<void> {
|
|
119
|
+
try {
|
|
120
|
+
// Export the modified database to a Uint8Array
|
|
121
|
+
const data = mDb.export();
|
|
122
|
+
|
|
123
|
+
// Write the Uint8Array to a file on the local disk
|
|
124
|
+
this.FS.writeFileSync(outputPath, Buffer.from(data));
|
|
125
|
+
|
|
126
|
+
return Promise.resolve();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
return Promise.reject(error);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
public closeDB(mDB: any): Promise<void> {
|
|
132
|
+
const msg = 'closeDB';
|
|
133
|
+
try {
|
|
134
|
+
mDB.close();
|
|
135
|
+
return Promise.resolve();
|
|
136
|
+
} catch (err: any) {
|
|
137
|
+
const errmsg = err.message ? err.message : err;
|
|
138
|
+
return Promise.reject(`${msg} ${errmsg}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
public async dbChanges(mDB: any): Promise<number> {
|
|
142
|
+
const SELECT_CHANGE = 'SELECT total_changes()';
|
|
143
|
+
let changes = 0;
|
|
144
|
+
try {
|
|
145
|
+
const res = mDB.exec(SELECT_CHANGE);
|
|
146
|
+
// process the row here
|
|
147
|
+
changes = res[0].values[0][0];
|
|
148
|
+
return Promise.resolve(changes);
|
|
149
|
+
} catch (err: any) {
|
|
150
|
+
const errmsg = err.message ? err.message : err;
|
|
151
|
+
return Promise.reject(`DbChanges failed: ${errmsg}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
public async getLastId(mDB: any): Promise<number> {
|
|
155
|
+
const SELECT_LAST_ID = 'SELECT last_insert_rowid()';
|
|
156
|
+
let lastId = -1;
|
|
157
|
+
try {
|
|
158
|
+
const res = mDB.exec(SELECT_LAST_ID);
|
|
159
|
+
// process the row here
|
|
160
|
+
lastId = res[0].values[0][0];
|
|
161
|
+
return Promise.resolve(lastId);
|
|
162
|
+
} catch (err: any) {
|
|
163
|
+
const errmsg = err.message ? err.message : err;
|
|
164
|
+
return Promise.reject(new Error(`GetLastId failed: ${errmsg}`));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
public async execute(mDB: any, sql: string): Promise<number> {
|
|
168
|
+
try {
|
|
169
|
+
mDB.exec(sql);
|
|
170
|
+
const changes = await this.dbChanges(mDB);
|
|
171
|
+
return Promise.resolve(changes);
|
|
172
|
+
} catch (err: any) {
|
|
173
|
+
const errmsg = err.message ? err.message : err;
|
|
174
|
+
return Promise.reject(new Error(`Execute failed: ${errmsg}`));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
public async run(
|
|
178
|
+
mDB: any,
|
|
179
|
+
statement: string,
|
|
180
|
+
values: any[],
|
|
181
|
+
returnMode: string,
|
|
182
|
+
): Promise<any> {
|
|
183
|
+
let res: any;
|
|
184
|
+
let retValues: any[] = [];
|
|
185
|
+
const retObj: any = {};
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
if (values.length > 0) {
|
|
189
|
+
res = mDB.exec(statement, values);
|
|
190
|
+
} else {
|
|
191
|
+
res = mDB.exec(statement);
|
|
192
|
+
}
|
|
193
|
+
if (returnMode === 'all' || returnMode === 'one') {
|
|
194
|
+
if (res && res.length > 0) {
|
|
195
|
+
retValues = this.getReturnedValues(res[0], returnMode);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const lastId = await this.getLastId(mDB);
|
|
199
|
+
retObj['lastId'] = lastId;
|
|
200
|
+
if (retValues != null && retValues.length > 0)
|
|
201
|
+
retObj['values'] = retValues;
|
|
202
|
+
return Promise.resolve(retObj);
|
|
203
|
+
} catch (err: any) {
|
|
204
|
+
const errmsg = err.message ? err.message : err;
|
|
205
|
+
return Promise.reject(new Error(`Run failed: ${errmsg}`));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
public getReturnedValues(result: any, returnMode: string): any[] {
|
|
209
|
+
const retValues: any[] = [];
|
|
210
|
+
for (const values of result.values) {
|
|
211
|
+
const row: any = {};
|
|
212
|
+
|
|
213
|
+
for (let j = 0; j < result.columns.length; j++) {
|
|
214
|
+
row[result.columns[j]] = values[j];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
retValues.push(row);
|
|
218
|
+
|
|
219
|
+
if (returnMode === 'one') {
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return retValues;
|
|
224
|
+
}
|
|
225
|
+
public async queryAll(mDB: any, sql: string, values: any[]): Promise<any[]> {
|
|
226
|
+
try {
|
|
227
|
+
let retArr: any[] = [];
|
|
228
|
+
if (values != null && values.length > 0) {
|
|
229
|
+
retArr = mDB.exec(sql, values);
|
|
230
|
+
} else {
|
|
231
|
+
retArr = mDB.exec(sql);
|
|
232
|
+
}
|
|
233
|
+
if (retArr.length == 0) return Promise.resolve([]);
|
|
234
|
+
|
|
235
|
+
const result = retArr[0].values.map((entry: any[]) => {
|
|
236
|
+
const obj: any = {};
|
|
237
|
+
retArr[0].columns.forEach((column: string, index: number) => {
|
|
238
|
+
obj[`${column}`] = entry[index];
|
|
239
|
+
});
|
|
240
|
+
return obj;
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return Promise.resolve(result);
|
|
244
|
+
} catch (err: any) {
|
|
245
|
+
const errmsg = err.message ? err.message : err;
|
|
246
|
+
return Promise.reject(new Error(`queryAll: ${errmsg}`));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|