@capacitor-community/sqlite 3.4.3-1 → 3.4.3-2
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 +33 -0
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLite.java +41 -2
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLitePlugin.java +26 -0
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/NotificationCenter.java +1 -1
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/Database.java +220 -7
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/ExportToJson.java +100 -3
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/ImportFromJson.java +37 -34
- package/dist/esm/definitions.d.ts +14 -0
- package/dist/esm/definitions.js +9 -17
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +1 -0
- package/dist/esm/web.js +11 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +22 -19
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +1035 -1032
- package/dist/plugin.js.map +1 -1
- package/electron/dist/plugin.js +13 -4
- package/electron/dist/plugin.js.map +1 -1
- package/ios/Plugin/CapacitorSQLite.swift +34 -1
- package/ios/Plugin/CapacitorSQLitePlugin.m +1 -0
- package/ios/Plugin/CapacitorSQLitePlugin.swift +25 -0
- package/ios/Plugin/Database.swift +29 -1
- package/ios/Plugin/Extensions/String.swift +8 -0
- package/ios/Plugin/ImportExportJson/ExportToJson.swift +154 -25
- package/ios/Plugin/ImportExportJson/ImportFromJson.swift +53 -27
- package/ios/Plugin/Utils/UtilsDrop.swift +2 -2
- package/ios/Plugin/Utils/UtilsSQLCipher.swift +277 -8
- package/ios/Plugin/Utils/UtilsUpgrade.swift +0 -1
- package/package.json +2 -2
|
@@ -13,6 +13,7 @@ enum UtilsSQLCipherError: Error {
|
|
|
13
13
|
case openOrCreateDatabase(message: String)
|
|
14
14
|
case bindFailed
|
|
15
15
|
case setForeignKeyConstraintsEnabled(message: String)
|
|
16
|
+
case getForeignKeysStateFailed(message: String)
|
|
16
17
|
case getVersion(message: String)
|
|
17
18
|
case setVersion(message: String)
|
|
18
19
|
case closeDB(message: String)
|
|
@@ -23,6 +24,9 @@ enum UtilsSQLCipherError: Error {
|
|
|
23
24
|
case commitTransaction(message: String)
|
|
24
25
|
case execute(message: String)
|
|
25
26
|
case prepareSQL(message: String)
|
|
27
|
+
case deleteSQL(message: String)
|
|
28
|
+
case findReferenciesAndUpdate(message: String)
|
|
29
|
+
case getReferencies(message: String)
|
|
26
30
|
case querySQL(message: String)
|
|
27
31
|
case fetchColumnInfo(message: String)
|
|
28
32
|
case deleteDB(message: String)
|
|
@@ -233,6 +237,40 @@ class UtilsSQLCipher {
|
|
|
233
237
|
|
|
234
238
|
}
|
|
235
239
|
|
|
240
|
+
// MARK: - GetForeignKeysState
|
|
241
|
+
|
|
242
|
+
class func getForeignKeysState(mDB: Database) throws -> Int {
|
|
243
|
+
var msg: String = "Error ForeignKeysState: "
|
|
244
|
+
if !mDB.isDBOpen() {
|
|
245
|
+
msg.append("Database not opened")
|
|
246
|
+
throw UtilsSQLCipherError.getForeignKeysStateFailed(message: msg)
|
|
247
|
+
}
|
|
248
|
+
var fkState: Int = 0
|
|
249
|
+
|
|
250
|
+
let sqltr: String = "PRAGMA foreign_keys;"
|
|
251
|
+
do {
|
|
252
|
+
var resForKeys = try UtilsSQLCipher.querySQL(mDB: mDB,
|
|
253
|
+
sql: sqltr,
|
|
254
|
+
values: [])
|
|
255
|
+
if resForKeys.count > 1 {
|
|
256
|
+
resForKeys.removeFirst()
|
|
257
|
+
guard let res: Int64 = resForKeys[0]["foreign_keys"]
|
|
258
|
+
as? Int64 else {
|
|
259
|
+
throw UtilsSQLCipherError.getForeignKeysStateFailed(
|
|
260
|
+
message: "Error get foreign keys failed")
|
|
261
|
+
}
|
|
262
|
+
if res > 0 {
|
|
263
|
+
fkState = Int(truncatingIfNeeded: res)
|
|
264
|
+
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return fkState
|
|
268
|
+
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
269
|
+
throw UtilsSQLCipherError.getForeignKeysStateFailed(
|
|
270
|
+
message: message)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
236
274
|
// MARK: - GetVersion
|
|
237
275
|
|
|
238
276
|
class func getVersion(mDB: Database) throws -> Int {
|
|
@@ -262,7 +300,7 @@ class UtilsSQLCipher {
|
|
|
262
300
|
}
|
|
263
301
|
return version
|
|
264
302
|
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
265
|
-
throw
|
|
303
|
+
throw UtilsSQLCipherError.getVersion(
|
|
266
304
|
message: message)
|
|
267
305
|
}
|
|
268
306
|
}
|
|
@@ -373,8 +411,9 @@ class UtilsSQLCipher {
|
|
|
373
411
|
// MARK: - PrepareSQL
|
|
374
412
|
|
|
375
413
|
// swiftlint:disable function_body_length
|
|
376
|
-
|
|
377
|
-
|
|
414
|
+
// swiftlint:disable cyclomatic_complexity
|
|
415
|
+
class func prepareSQL(mDB: Database, sql: String, values: [Any],
|
|
416
|
+
fromJson: Bool) throws -> Int64 {
|
|
378
417
|
var msg: String = "Error prepareSQL: "
|
|
379
418
|
if !mDB.isDBOpen() {
|
|
380
419
|
msg.append("Database not opened")
|
|
@@ -383,9 +422,19 @@ class UtilsSQLCipher {
|
|
|
383
422
|
var runSQLStatement: OpaquePointer?
|
|
384
423
|
var message: String = ""
|
|
385
424
|
var lastId: Int64 = -1
|
|
386
|
-
|
|
425
|
+
var sqlStmt = sql
|
|
426
|
+
// Check for DELETE statement
|
|
427
|
+
if !fromJson && sqlStmt.prefix(6).uppercased() == "DELETE" {
|
|
428
|
+
do {
|
|
429
|
+
sqlStmt = try deleteSQL(mDB: mDB, sql: sql,
|
|
430
|
+
values: values)
|
|
431
|
+
} catch UtilsSQLCipherError.deleteSQL(let message) {
|
|
432
|
+
let msg = "Error: prepareSQL \(message)"
|
|
433
|
+
throw UtilsSQLCipherError.prepareSQL(message: msg)
|
|
434
|
+
}
|
|
435
|
+
}
|
|
387
436
|
var returnCode: Int32 = sqlite3_prepare_v2(
|
|
388
|
-
mDB.mDb,
|
|
437
|
+
mDB.mDb, sqlStmt, -1, &runSQLStatement, nil)
|
|
389
438
|
if returnCode == SQLITE_OK {
|
|
390
439
|
if !values.isEmpty {
|
|
391
440
|
// do the binding of values
|
|
@@ -429,8 +478,198 @@ class UtilsSQLCipher {
|
|
|
429
478
|
return lastId
|
|
430
479
|
}
|
|
431
480
|
}
|
|
481
|
+
// swiftlint:enable cyclomatic_complexity
|
|
432
482
|
// swiftlint:enable function_body_length
|
|
433
483
|
|
|
484
|
+
// MARK: - deleteSQL
|
|
485
|
+
|
|
486
|
+
class func deleteSQL(mDB: Database, sql: String, values: [Any]) throws -> String {
|
|
487
|
+
var sqlStmt = sql
|
|
488
|
+
do {
|
|
489
|
+
let isLast: Bool = try UtilsJson.isLastModified(mDB: mDB)
|
|
490
|
+
if isLast {
|
|
491
|
+
if let range: Range<String.Index> = sql
|
|
492
|
+
.range(of: "WHERE", options: .caseInsensitive) {
|
|
493
|
+
let index: Int = sql
|
|
494
|
+
.distance(from: sql.startIndex, to: range.lowerBound)
|
|
495
|
+
let preStmt = String(sql.stringRange(fromIdx: 0,
|
|
496
|
+
toIdx: (index - 1)))
|
|
497
|
+
let clauseStmt = String(sql.stringRange(fromIdx: index,
|
|
498
|
+
toIdx: sql.count))
|
|
499
|
+
let tableName = (preStmt.deletingPrefix("DELETE FROM"))
|
|
500
|
+
.trimmingLeadingAndTrailingSpaces()
|
|
501
|
+
sqlStmt = "UPDATE \(tableName) SET sql_deleted = 1 "
|
|
502
|
+
sqlStmt += clauseStmt
|
|
503
|
+
// Find REFERENCIES if any and update the sql_deleted column
|
|
504
|
+
try findReferenciesAndUpdate(mDB: mDB,
|
|
505
|
+
tableName: tableName,
|
|
506
|
+
whereStmt: clauseStmt,
|
|
507
|
+
values: values)
|
|
508
|
+
} else {
|
|
509
|
+
let msg: String = "deleteSQL cannot find a WHERE clause"
|
|
510
|
+
throw UtilsSQLCipherError.deleteSQL(message: msg)
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return sqlStmt
|
|
514
|
+
} catch UtilsSQLCipherError.findReferenciesAndUpdate(let message) {
|
|
515
|
+
throw UtilsSQLCipherError.deleteSQL(message: message)
|
|
516
|
+
} catch UtilsJsonError.isLastModified(let message) {
|
|
517
|
+
throw UtilsSQLCipherError.deleteSQL(message: message)
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// MARK: - findReferencesAndUpdate
|
|
522
|
+
|
|
523
|
+
class func findReferenciesAndUpdate(mDB: Database, tableName: String,
|
|
524
|
+
whereStmt: String,
|
|
525
|
+
values: [Any]) throws {
|
|
526
|
+
do {
|
|
527
|
+
let referencies = try getReferencies(mDB: mDB,
|
|
528
|
+
tableName: tableName)
|
|
529
|
+
if referencies.count <= 0 {
|
|
530
|
+
return
|
|
531
|
+
}
|
|
532
|
+
// Loop through referencies
|
|
533
|
+
for ref in referencies {
|
|
534
|
+
// get the tableName of the references
|
|
535
|
+
let refTable: String = getReferencesTableName(value: ref)
|
|
536
|
+
if refTable.count <= 0 {
|
|
537
|
+
continue
|
|
538
|
+
}
|
|
539
|
+
// get the columnName
|
|
540
|
+
let colName: String = getReferencesColumnName(value: ref)
|
|
541
|
+
if colName.count <= 0 {
|
|
542
|
+
continue
|
|
543
|
+
}
|
|
544
|
+
// update the where clause
|
|
545
|
+
let uWhereStmt: String = updateWhere(whStmt: whereStmt,
|
|
546
|
+
colName: colName)
|
|
547
|
+
|
|
548
|
+
if uWhereStmt.count <= 0 {
|
|
549
|
+
continue
|
|
550
|
+
}
|
|
551
|
+
//update sql_deleted for this references
|
|
552
|
+
let stmt = "UPDATE \(refTable) SET sql_deleted = 1 " +
|
|
553
|
+
uWhereStmt
|
|
554
|
+
let lastId = try prepareSQL(mDB: mDB, sql: stmt,
|
|
555
|
+
values: values, fromJson: false)
|
|
556
|
+
if lastId == -1 {
|
|
557
|
+
let msg = "UPDATE sql_deleted failed for references " +
|
|
558
|
+
"table: \(refTable) "
|
|
559
|
+
throw UtilsSQLCipherError
|
|
560
|
+
.findReferenciesAndUpdate(message: msg)
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
return
|
|
564
|
+
} catch UtilsSQLCipherError.prepareSQL(let message) {
|
|
565
|
+
throw UtilsSQLCipherError
|
|
566
|
+
.findReferenciesAndUpdate(message: message)
|
|
567
|
+
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
568
|
+
throw UtilsSQLCipherError
|
|
569
|
+
.findReferenciesAndUpdate(message: message)
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// MARK: - getReferencies
|
|
575
|
+
|
|
576
|
+
class func getReferencies(mDB: Database, tableName: String)
|
|
577
|
+
throws -> [[String: Any]] {
|
|
578
|
+
// find the REFERENCIES
|
|
579
|
+
var sqlStmt = "SELECT sql FROM sqlite_master "
|
|
580
|
+
sqlStmt += "WHERE sql LIKE('%REFERENCES%') AND "
|
|
581
|
+
sqlStmt += "sql LIKE('%\(tableName)%') AND sql LIKE('%ON DELETE%');"
|
|
582
|
+
do {
|
|
583
|
+
var referencies: [[String: Any]] = try querySQL(mDB: mDB,
|
|
584
|
+
sql: sqlStmt,
|
|
585
|
+
values: [])
|
|
586
|
+
if referencies.count > 1 {
|
|
587
|
+
referencies.removeFirst()
|
|
588
|
+
}
|
|
589
|
+
return referencies
|
|
590
|
+
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
591
|
+
throw UtilsSQLCipherError
|
|
592
|
+
.getReferencies(message: message)
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// MARK: - getReferencesTableName
|
|
597
|
+
|
|
598
|
+
class func getReferencesTableName(value: [String: Any]) -> String {
|
|
599
|
+
|
|
600
|
+
var tableName: String = ""
|
|
601
|
+
if let refValue = value["sql"] as? String {
|
|
602
|
+
|
|
603
|
+
if let range: Range<String.Index> = refValue
|
|
604
|
+
.range(of: "CREATE TABLE", options: .caseInsensitive) {
|
|
605
|
+
let index: Int = refValue
|
|
606
|
+
.distance(from: refValue.startIndex, to: range.lowerBound)
|
|
607
|
+
let stmt = String(refValue.stringRange(fromIdx: index + 13,
|
|
608
|
+
toIdx: refValue.count))
|
|
609
|
+
if let oPar = stmt.firstIndex(of: "(") {
|
|
610
|
+
let idx: Int = stmt.distance(from: stmt.startIndex, to: oPar)
|
|
611
|
+
tableName = String(stmt.stringRange(fromIdx: 0, toIdx: idx))
|
|
612
|
+
.trimmingLeadingAndTrailingSpaces()
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
return tableName
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// MARK: - getReferencesColumnName
|
|
620
|
+
|
|
621
|
+
class func getReferencesColumnName(value: [String: Any]) -> String {
|
|
622
|
+
|
|
623
|
+
var colName: String = ""
|
|
624
|
+
if let refValue = value["sql"] as? String {
|
|
625
|
+
|
|
626
|
+
if let range: Range<String.Index> = refValue
|
|
627
|
+
.range(of: "FOREIGN KEY", options: .caseInsensitive) {
|
|
628
|
+
let index: Int = refValue
|
|
629
|
+
.distance(from: refValue.startIndex, to: range.lowerBound)
|
|
630
|
+
let stmt = String(refValue.stringRange(fromIdx: index + 12,
|
|
631
|
+
toIdx: refValue.count))
|
|
632
|
+
if let oPar = stmt.firstIndex(of: "(") {
|
|
633
|
+
let idxOPar: Int = stmt.distance(from: stmt.startIndex,
|
|
634
|
+
to: oPar) + 1
|
|
635
|
+
if let cPar = stmt.firstIndex(of: ")") {
|
|
636
|
+
let idxCPar: Int = stmt
|
|
637
|
+
.distance(from: stmt.startIndex,
|
|
638
|
+
to: cPar)
|
|
639
|
+
colName = String(stmt.stringRange(fromIdx: idxOPar,
|
|
640
|
+
toIdx: idxCPar))
|
|
641
|
+
.trimmingLeadingAndTrailingSpaces()
|
|
642
|
+
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
return colName
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
class func updateWhere(whStmt: String, colName: String) -> String {
|
|
652
|
+
var whereStmt = ""
|
|
653
|
+
if let range: Range<String.Index> = whStmt
|
|
654
|
+
.range(of: "WHERE", options: .caseInsensitive) {
|
|
655
|
+
let index: Int = whStmt
|
|
656
|
+
.distance(from: whStmt.startIndex, to: range.lowerBound)
|
|
657
|
+
let stmt = String(whStmt.stringRange(fromIdx: index + 6,
|
|
658
|
+
toIdx: whStmt.count))
|
|
659
|
+
if let fEqual = stmt.firstIndex(of: "=") {
|
|
660
|
+
let idxfEqual: Int = stmt.distance(from: stmt.startIndex,
|
|
661
|
+
to: fEqual)
|
|
662
|
+
let whereColName = String(stmt.stringRange(fromIdx: 0,
|
|
663
|
+
toIdx: idxfEqual))
|
|
664
|
+
.trimmingLeadingAndTrailingSpaces()
|
|
665
|
+
whereStmt = whStmt.replacingOccurrences(of: whereColName, with: colName)
|
|
666
|
+
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
return whereStmt
|
|
671
|
+
}
|
|
672
|
+
|
|
434
673
|
// MARK: - querySQL
|
|
435
674
|
|
|
436
675
|
class func querySQL(mDB: Database, sql: String,
|
|
@@ -565,8 +804,34 @@ class UtilsSQLCipher {
|
|
|
565
804
|
msg.append("Database not opened")
|
|
566
805
|
throw UtilsSQLCipherError.execute(message: msg)
|
|
567
806
|
}
|
|
807
|
+
var sqlStmt = sql
|
|
808
|
+
if sql.localizedCaseInsensitiveContains("DELETE FROM") {
|
|
809
|
+
sqlStmt = sqlStmt.replacingOccurrences(of: "\n",
|
|
810
|
+
with: "")
|
|
811
|
+
var stmtArr = sqlStmt.components(separatedBy: ";")
|
|
812
|
+
stmtArr.removeLast()
|
|
813
|
+
var resArr: [String] = []
|
|
814
|
+
for stmt in stmtArr {
|
|
815
|
+
let trimStmt = stmt
|
|
816
|
+
.trimmingLeadingAndTrailingSpaces().prefix(11).uppercased()
|
|
817
|
+
if trimStmt == "DELETE FROM" &&
|
|
818
|
+
stmt.localizedCaseInsensitiveContains("WHERE") {
|
|
819
|
+
let whereStmt = stmt.trimmingLeadingAndTrailingSpaces()
|
|
820
|
+
do {
|
|
821
|
+
let rStmt: String = try deleteSQL(mDB: mDB, sql: whereStmt, values: [])
|
|
822
|
+
resArr.append(rStmt)
|
|
823
|
+
} catch UtilsSQLCipherError.deleteSQL(let message) {
|
|
824
|
+
let msg = "Error: execute \(message)"
|
|
825
|
+
throw UtilsSQLCipherError.execute(message: msg)
|
|
826
|
+
}
|
|
827
|
+
} else {
|
|
828
|
+
resArr.append(String(stmt))
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
sqlStmt = resArr.joined(separator: ";")
|
|
832
|
+
}
|
|
568
833
|
|
|
569
|
-
let returnCode: Int32 = sqlite3_exec(mDB.mDb,
|
|
834
|
+
let returnCode: Int32 = sqlite3_exec(mDB.mDb, sqlStmt, nil,
|
|
570
835
|
nil, nil)
|
|
571
836
|
if returnCode != SQLITE_OK {
|
|
572
837
|
let errmsg: String = String(
|
|
@@ -633,7 +898,7 @@ class UtilsSQLCipher {
|
|
|
633
898
|
for vals in arrValues {
|
|
634
899
|
lastId = try UtilsSQLCipher
|
|
635
900
|
.prepareSQL(mDB: mDB, sql: sql,
|
|
636
|
-
values: vals)
|
|
901
|
+
values: vals, fromJson: false)
|
|
637
902
|
if lastId == -1 {
|
|
638
903
|
let message: String = "lastId < 0"
|
|
639
904
|
throw UtilsSQLCipherError
|
|
@@ -643,7 +908,8 @@ class UtilsSQLCipher {
|
|
|
643
908
|
}
|
|
644
909
|
} else {
|
|
645
910
|
lastId = try UtilsSQLCipher
|
|
646
|
-
.prepareSQL(mDB: mDB, sql: sql, values: values
|
|
911
|
+
.prepareSQL(mDB: mDB, sql: sql, values: values,
|
|
912
|
+
fromJson: false)
|
|
647
913
|
if lastId == -1 {
|
|
648
914
|
let message: String = "lastId < 0"
|
|
649
915
|
throw UtilsSQLCipherError.executeSet(
|
|
@@ -741,6 +1007,9 @@ class UtilsSQLCipher {
|
|
|
741
1007
|
}
|
|
742
1008
|
|
|
743
1009
|
}
|
|
1010
|
+
|
|
1011
|
+
// MARK: - parse
|
|
1012
|
+
|
|
744
1013
|
class func parse(mVar: Any) -> Bool {
|
|
745
1014
|
var ret: Bool = false
|
|
746
1015
|
if mVar is NSArray {
|
|
@@ -15,7 +15,6 @@ enum UtilsUpgradeError: Error {
|
|
|
15
15
|
case backupTableFailed(message: String)
|
|
16
16
|
case getTableColumnNamesFailed(message: String)
|
|
17
17
|
case updateDatabaseVersionFailed(message: String)
|
|
18
|
-
case getDatabaseVersionFailed(message: String)
|
|
19
18
|
case findCommonColumnsFailed(message: String)
|
|
20
19
|
case arrayIntersectionFailed(message: String)
|
|
21
20
|
case updateNewTablesDataFailed(message: String)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor-community/sqlite",
|
|
3
|
-
"version": "3.4.3-
|
|
3
|
+
"version": "3.4.3-2",
|
|
4
4
|
"description": "Community plugin for native & electron SQLite databases",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -93,6 +93,6 @@
|
|
|
93
93
|
}
|
|
94
94
|
},
|
|
95
95
|
"dependencies": {
|
|
96
|
-
"jeep-sqlite": "^1.
|
|
96
|
+
"jeep-sqlite": "^1.5.0"
|
|
97
97
|
}
|
|
98
98
|
}
|