@capacitor-community/sqlite 5.0.6 → 5.0.7-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 +3 -0
- package/electron/dist/plugin.js +594 -175
- package/electron/dist/plugin.js.map +1 -1
- package/ios/Plugin/Utils/UtilsDelete.swift +506 -0
- package/ios/Plugin/Utils/UtilsSQLCipher.swift +173 -476
- package/ios/Plugin/Utils/UtilsSQLStatement.swift +450 -0
- package/package.json +2 -2
|
@@ -25,9 +25,6 @@ enum UtilsSQLCipherError: Error {
|
|
|
25
25
|
case execute(message: String)
|
|
26
26
|
case prepareSQL(message: String)
|
|
27
27
|
case deleteSQL(message: String)
|
|
28
|
-
case findReferencesAndUpdate(message: String)
|
|
29
|
-
case getReferences(message: String)
|
|
30
|
-
case getRefs(message: String)
|
|
31
28
|
case querySQL(message: String)
|
|
32
29
|
case fetchColumnInfo(message: String)
|
|
33
30
|
case deleteDB(message: String)
|
|
@@ -38,8 +35,6 @@ enum UtilsSQLCipherError: Error {
|
|
|
38
35
|
case openDBStoredPassword(message: String)
|
|
39
36
|
case openDBGlobalPassword(message: String)
|
|
40
37
|
case returningWorkAround(message: String)
|
|
41
|
-
case getUpdDelReturnedValues(message: String)
|
|
42
|
-
case getFirstPK(message: String)
|
|
43
38
|
}
|
|
44
39
|
enum State: String {
|
|
45
40
|
case DOESNOTEXIST, UNENCRYPTED, ENCRYPTEDSECRET,
|
|
@@ -51,6 +46,8 @@ enum State: String {
|
|
|
51
46
|
// swiftlint:disable type_body_length
|
|
52
47
|
class UtilsSQLCipher {
|
|
53
48
|
|
|
49
|
+
// MARK: - getDatabaseState
|
|
50
|
+
|
|
54
51
|
class func getDatabaseState(databaseLocation: String,
|
|
55
52
|
databaseName: String,
|
|
56
53
|
account: String) -> State {
|
|
@@ -62,17 +59,22 @@ class UtilsSQLCipher {
|
|
|
62
59
|
do {
|
|
63
60
|
try openDBNoPassword(dBPath: path)
|
|
64
61
|
return State.UNENCRYPTED
|
|
65
|
-
} catch UtilsSQLCipherError
|
|
62
|
+
} catch UtilsSQLCipherError
|
|
63
|
+
.openDBNoPassword(let message) {
|
|
66
64
|
if message == "Open" {
|
|
67
65
|
do {
|
|
68
|
-
try openDBStoredPassword(dBPath: path,
|
|
66
|
+
try openDBStoredPassword(dBPath: path,
|
|
67
|
+
account: account)
|
|
69
68
|
return State.ENCRYPTEDSECRET
|
|
70
|
-
} catch UtilsSQLCipherError
|
|
69
|
+
} catch UtilsSQLCipherError
|
|
70
|
+
.openDBStoredPassword(let message) {
|
|
71
71
|
if message == "Open" {
|
|
72
72
|
do {
|
|
73
|
-
try openDBGlobalPassword(
|
|
73
|
+
try openDBGlobalPassword(
|
|
74
|
+
dBPath: path)
|
|
74
75
|
return State.ENCRYPTEDGLOBALSECRET
|
|
75
|
-
} catch UtilsSQLCipherError
|
|
76
|
+
} catch UtilsSQLCipherError
|
|
77
|
+
.openDBGlobalPassword(let message) {
|
|
76
78
|
if message == "Open" {
|
|
77
79
|
return State.UNKNOWN
|
|
78
80
|
} else {
|
|
@@ -95,6 +97,9 @@ class UtilsSQLCipher {
|
|
|
95
97
|
return State.UNKNOWN
|
|
96
98
|
}
|
|
97
99
|
}
|
|
100
|
+
|
|
101
|
+
// MARK: - openDBNoPassword
|
|
102
|
+
|
|
98
103
|
class func openDBNoPassword(dBPath: String) throws {
|
|
99
104
|
do {
|
|
100
105
|
let oDb: OpaquePointer? = try openOrCreateDatabase(
|
|
@@ -105,24 +110,35 @@ class UtilsSQLCipher {
|
|
|
105
110
|
} catch UtilsSQLCipherError.openOrCreateDatabase(_) {
|
|
106
111
|
throw UtilsSQLCipherError.openDBNoPassword(message: "Open")
|
|
107
112
|
} catch UtilsSQLCipherError.close(_) {
|
|
108
|
-
throw UtilsSQLCipherError
|
|
113
|
+
throw UtilsSQLCipherError
|
|
114
|
+
.openDBNoPassword(message: "Close")
|
|
109
115
|
}
|
|
110
116
|
|
|
111
117
|
}
|
|
112
|
-
|
|
118
|
+
|
|
119
|
+
// MARK: - openDBStoredPassword
|
|
120
|
+
|
|
121
|
+
class func openDBStoredPassword(dBPath: String, account: String)
|
|
122
|
+
throws {
|
|
113
123
|
do {
|
|
114
|
-
let password: String = UtilsSecret
|
|
124
|
+
let password: String = UtilsSecret
|
|
125
|
+
.getPassphrase(account: account)
|
|
115
126
|
let oDb: OpaquePointer? = try openOrCreateDatabase(
|
|
116
127
|
filename: dBPath, password: password, readonly: true)
|
|
117
128
|
try close(oDB: oDb)
|
|
118
129
|
return
|
|
119
130
|
} catch UtilsSQLCipherError.openOrCreateDatabase(_) {
|
|
120
|
-
throw UtilsSQLCipherError
|
|
131
|
+
throw UtilsSQLCipherError
|
|
132
|
+
.openDBStoredPassword(message: "Open")
|
|
121
133
|
} catch UtilsSQLCipherError.close(_) {
|
|
122
|
-
throw UtilsSQLCipherError
|
|
134
|
+
throw UtilsSQLCipherError
|
|
135
|
+
.openDBStoredPassword(message: "Close")
|
|
123
136
|
}
|
|
124
137
|
|
|
125
138
|
}
|
|
139
|
+
|
|
140
|
+
// MARK: - openDBGlobalPassword
|
|
141
|
+
|
|
126
142
|
class func openDBGlobalPassword(dBPath: String) throws {
|
|
127
143
|
do {
|
|
128
144
|
let globalData: GlobalSQLite = GlobalSQLite()
|
|
@@ -132,9 +148,11 @@ class UtilsSQLCipher {
|
|
|
132
148
|
try close(oDB: oDb)
|
|
133
149
|
return
|
|
134
150
|
} catch UtilsSQLCipherError.openOrCreateDatabase(_) {
|
|
135
|
-
throw UtilsSQLCipherError
|
|
151
|
+
throw UtilsSQLCipherError
|
|
152
|
+
.openDBGlobalPassword(message: "Open")
|
|
136
153
|
} catch UtilsSQLCipherError.close(_) {
|
|
137
|
-
throw UtilsSQLCipherError
|
|
154
|
+
throw UtilsSQLCipherError
|
|
155
|
+
.openDBGlobalPassword(message: "Close")
|
|
138
156
|
}
|
|
139
157
|
|
|
140
158
|
}
|
|
@@ -159,13 +177,15 @@ class UtilsSQLCipher {
|
|
|
159
177
|
if sqlite3_exec(mDB, keyStatementString, nil, nil, nil)
|
|
160
178
|
!= SQLITE_OK {
|
|
161
179
|
let msg: String = "Wrong Secret"
|
|
162
|
-
throw UtilsSQLCipherError
|
|
180
|
+
throw UtilsSQLCipherError
|
|
181
|
+
.openOrCreateDatabase(message: msg)
|
|
163
182
|
}
|
|
164
183
|
}
|
|
165
184
|
let retB: Bool = checkDB(mDB: mDB)
|
|
166
185
|
if !retB {
|
|
167
186
|
let msg: String = "Cannot open the DB"
|
|
168
|
-
throw UtilsSQLCipherError
|
|
187
|
+
throw UtilsSQLCipherError
|
|
188
|
+
.openOrCreateDatabase(message: msg)
|
|
169
189
|
}
|
|
170
190
|
return mDB
|
|
171
191
|
} else {
|
|
@@ -186,6 +206,7 @@ class UtilsSQLCipher {
|
|
|
186
206
|
}
|
|
187
207
|
return ret
|
|
188
208
|
}
|
|
209
|
+
|
|
189
210
|
// MARK: - ChangePassword
|
|
190
211
|
|
|
191
212
|
class func changePassword(filename: String, password: String,
|
|
@@ -247,7 +268,8 @@ class UtilsSQLCipher {
|
|
|
247
268
|
var msg: String = "Error ForeignKeysState: "
|
|
248
269
|
if !mDB.isDBOpen() {
|
|
249
270
|
msg.append("Database not opened")
|
|
250
|
-
throw UtilsSQLCipherError
|
|
271
|
+
throw UtilsSQLCipherError
|
|
272
|
+
.getForeignKeysStateFailed(message: msg)
|
|
251
273
|
}
|
|
252
274
|
var fkState: Int = 0
|
|
253
275
|
|
|
@@ -260,7 +282,8 @@ class UtilsSQLCipher {
|
|
|
260
282
|
resForKeys.removeFirst()
|
|
261
283
|
guard let res: Int64 = resForKeys[0]["foreign_keys"]
|
|
262
284
|
as? Int64 else {
|
|
263
|
-
throw UtilsSQLCipherError
|
|
285
|
+
throw UtilsSQLCipherError
|
|
286
|
+
.getForeignKeysStateFailed(
|
|
264
287
|
message: "Error get foreign keys failed")
|
|
265
288
|
}
|
|
266
289
|
if res > 0 {
|
|
@@ -417,7 +440,8 @@ class UtilsSQLCipher {
|
|
|
417
440
|
// swiftlint:disable function_body_length
|
|
418
441
|
// swiftlint:disable cyclomatic_complexity
|
|
419
442
|
class func prepareSQL(mDB: Database, sql: String, values: [Any],
|
|
420
|
-
fromJson: Bool, returnMode: String)
|
|
443
|
+
fromJson: Bool, returnMode: String)
|
|
444
|
+
throws -> (Int64, [[String: Any]]) {
|
|
421
445
|
var msg: String = "Error prepareSQL: "
|
|
422
446
|
if !mDB.isDBOpen() {
|
|
423
447
|
msg.append("Database not opened")
|
|
@@ -442,8 +466,9 @@ class UtilsSQLCipher {
|
|
|
442
466
|
|
|
443
467
|
if (retMode == "no" || retMode.prefix(2) == "wA") &&
|
|
444
468
|
sqlStmt.uppercased().contains("RETURNING") {
|
|
445
|
-
let stmtNames =
|
|
446
|
-
|
|
469
|
+
let stmtNames = UtilsSQLStatement
|
|
470
|
+
.getStmtAndRetColNames(sqlStmt: sqlStmt,
|
|
471
|
+
retMode: retMode)
|
|
447
472
|
sqlStmt = stmtNames["stmt"] ?? sqlStmt
|
|
448
473
|
names = stmtNames["names"] ?? ""
|
|
449
474
|
}
|
|
@@ -487,22 +512,27 @@ class UtilsSQLCipher {
|
|
|
487
512
|
} else {
|
|
488
513
|
if retMode.prefix(2) == "wA" {
|
|
489
514
|
do {
|
|
490
|
-
result = try UtilsSQLCipher
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
515
|
+
result = try UtilsSQLCipher
|
|
516
|
+
.returningWorkAround(
|
|
517
|
+
mDB: mDB,
|
|
518
|
+
runSQLStatement: runSQLStatement,
|
|
519
|
+
sqlStmt: sqlStmt,
|
|
520
|
+
names: names, returnMode: retMode)
|
|
494
521
|
} catch UtilsSQLCipherError
|
|
495
522
|
.returningWorkAround(let message) {
|
|
496
|
-
throw UtilsSQLCipherError
|
|
523
|
+
throw UtilsSQLCipherError
|
|
524
|
+
.prepareSQL(message: message)
|
|
497
525
|
}
|
|
498
526
|
} else {
|
|
499
527
|
|
|
500
528
|
do {
|
|
501
529
|
result = try UtilsSQLCipher.fetchColumnInfo(
|
|
502
|
-
handle: runSQLStatement,
|
|
530
|
+
handle: runSQLStatement,
|
|
531
|
+
returnMode: retMode)
|
|
503
532
|
} catch UtilsSQLCipherError
|
|
504
533
|
.fetchColumnInfo(let message) {
|
|
505
|
-
throw UtilsSQLCipherError
|
|
534
|
+
throw UtilsSQLCipherError
|
|
535
|
+
.prepareSQL(message: message)
|
|
506
536
|
}
|
|
507
537
|
}
|
|
508
538
|
}
|
|
@@ -527,44 +557,26 @@ class UtilsSQLCipher {
|
|
|
527
557
|
}
|
|
528
558
|
}
|
|
529
559
|
|
|
530
|
-
// MARK: - getStmtAndRetColNames
|
|
531
|
-
|
|
532
|
-
class func getStmtAndRetColNames(sqlStmt: String, retMode: String) -> [String: String] {
|
|
533
|
-
let retWord = "RETURNING"
|
|
534
|
-
|
|
535
|
-
var retStmtNames: [String: String] = [:]
|
|
536
|
-
retStmtNames["stmt"] = sqlStmt
|
|
537
|
-
retStmtNames["names"] = ""
|
|
538
|
-
if let range = sqlStmt.uppercased().range(of: retWord) {
|
|
539
|
-
let prefix = sqlStmt.prefix(upTo: range.lowerBound)
|
|
540
|
-
retStmtNames["stmt"] = "\(prefix);"
|
|
541
|
-
retStmtNames["names"] = ""
|
|
542
|
-
if retMode.prefix(2) == "wA" {
|
|
543
|
-
let suffix = sqlStmt.suffix(from: range.upperBound)
|
|
544
|
-
let names = "\(suffix)".trimmingLeadingAndTrailingSpaces()
|
|
545
|
-
if names.suffix(1) == ";" {
|
|
546
|
-
retStmtNames["names"] = String(names.dropLast())
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
}
|
|
551
|
-
return retStmtNames
|
|
552
|
-
}
|
|
553
|
-
|
|
554
560
|
// MARK: - returningWorkAround
|
|
555
561
|
|
|
556
|
-
class func returningWorkAround(mDB: Database,
|
|
562
|
+
class func returningWorkAround(mDB: Database,
|
|
563
|
+
runSQLStatement: OpaquePointer?,
|
|
557
564
|
sqlStmt: String, names: String,
|
|
558
|
-
returnMode: String)
|
|
565
|
+
returnMode: String)
|
|
566
|
+
throws -> [[String: Any]] {
|
|
559
567
|
var result: [[String: Any]] = []
|
|
560
568
|
let initLastId = Int64(sqlite3_last_insert_rowid(mDB.mDb))
|
|
561
|
-
if sqlStmt.prefix(6).uppercased() == "DELETE" &&
|
|
569
|
+
if sqlStmt.prefix(6).uppercased() == "DELETE" &&
|
|
570
|
+
names.count > 0 {
|
|
562
571
|
do {
|
|
563
|
-
result = try
|
|
564
|
-
|
|
565
|
-
|
|
572
|
+
result = try UtilsDelete
|
|
573
|
+
.getUpdDelReturnedValues(mDB: mDB,
|
|
574
|
+
sqlStmt: sqlStmt,
|
|
575
|
+
names: names )
|
|
576
|
+
} catch UtilsDeleteError
|
|
566
577
|
.getUpdDelReturnedValues(let message) {
|
|
567
|
-
throw UtilsSQLCipherError
|
|
578
|
+
throw UtilsSQLCipherError
|
|
579
|
+
.returningWorkAround(message: message)
|
|
568
580
|
}
|
|
569
581
|
}
|
|
570
582
|
let returnCode: Int32 = sqlite3_step(runSQLStatement)
|
|
@@ -573,34 +585,42 @@ class UtilsSQLCipher {
|
|
|
573
585
|
cString: sqlite3_errmsg(mDB.mDb))
|
|
574
586
|
var message = "Error: prepareSQL step failed rc: "
|
|
575
587
|
message.append("\(returnCode) message: \(errmsg)")
|
|
576
|
-
throw UtilsSQLCipherError
|
|
588
|
+
throw UtilsSQLCipherError
|
|
589
|
+
.returningWorkAround(message: message)
|
|
577
590
|
|
|
578
591
|
}
|
|
579
592
|
if sqlStmt.prefix(6).uppercased() == "INSERT" {
|
|
580
593
|
let lastId = Int64(sqlite3_last_insert_rowid(mDB.mDb))
|
|
581
|
-
let tableName =
|
|
594
|
+
let tableName = UtilsSQLStatement
|
|
595
|
+
.extractTableName(from: sqlStmt)
|
|
582
596
|
if let tblName = tableName {
|
|
583
|
-
var query = "SELECT \(names) FROM \(tblName)
|
|
597
|
+
var query = "SELECT \(names) FROM \(tblName) " +
|
|
598
|
+
"WHERE rowid "
|
|
584
599
|
if returnMode == "wAone" {
|
|
585
600
|
query += "= \(initLastId + 1);"
|
|
586
601
|
} else {
|
|
587
602
|
query += "BETWEEN \(initLastId + 1) AND \(lastId);"
|
|
588
603
|
}
|
|
589
604
|
do {
|
|
590
|
-
result = try querySQL(mDB: mDB, sql: query,
|
|
605
|
+
result = try querySQL(mDB: mDB, sql: query,
|
|
606
|
+
values: [])
|
|
591
607
|
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
592
|
-
throw UtilsSQLCipherError
|
|
608
|
+
throw UtilsSQLCipherError
|
|
609
|
+
.returningWorkAround(message: message)
|
|
593
610
|
}
|
|
594
611
|
|
|
595
612
|
}
|
|
596
613
|
|
|
597
614
|
} else if sqlStmt.prefix(6).uppercased() == "UPDATE" {
|
|
598
615
|
do {
|
|
599
|
-
result = try
|
|
600
|
-
|
|
601
|
-
|
|
616
|
+
result = try UtilsDelete
|
|
617
|
+
.getUpdDelReturnedValues(mDB: mDB,
|
|
618
|
+
sqlStmt: sqlStmt,
|
|
619
|
+
names: names )
|
|
620
|
+
} catch UtilsDeleteError
|
|
602
621
|
.getUpdDelReturnedValues(let message) {
|
|
603
|
-
throw UtilsSQLCipherError
|
|
622
|
+
throw UtilsSQLCipherError
|
|
623
|
+
.returningWorkAround(message: message)
|
|
604
624
|
}
|
|
605
625
|
|
|
606
626
|
}
|
|
@@ -608,107 +628,66 @@ class UtilsSQLCipher {
|
|
|
608
628
|
return result
|
|
609
629
|
}
|
|
610
630
|
|
|
611
|
-
// MARK: - getUpdDelReturnedValues
|
|
612
|
-
|
|
613
|
-
class func getUpdDelReturnedValues(mDB: Database, sqlStmt: String,
|
|
614
|
-
names: String ) throws -> [[String: Any]] {
|
|
615
|
-
var result: [[String: Any]] = []
|
|
616
|
-
let tableName = extractTableName(from: sqlStmt)
|
|
617
|
-
let whereClause = extractWhereClause(from: sqlStmt)
|
|
618
|
-
if let tblName = tableName {
|
|
619
|
-
if var wClause = whereClause {
|
|
620
|
-
if wClause.suffix(1) == ";" {
|
|
621
|
-
wClause = String(wClause.dropLast())
|
|
622
|
-
}
|
|
623
|
-
do {
|
|
624
|
-
var query: String = "SELECT \(names) FROM \(tblName) WHERE "
|
|
625
|
-
query += "\(wClause);"
|
|
626
|
-
result = try querySQL(mDB: mDB, sql: query, values: [])
|
|
627
|
-
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
628
|
-
throw UtilsSQLCipherError.getUpdDelReturnedValues(message: message)
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
return result
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
// MARK: - extractTableName
|
|
636
|
-
|
|
637
|
-
class func extractTableName(from statement: String) -> String? {
|
|
638
|
-
let pattern = "(?:INSERT\\s+INTO|UPDATE|DELETE\\s+FROM)\\s+([^\\s]+)"
|
|
639
|
-
guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { return nil }
|
|
640
|
-
|
|
641
|
-
let range = NSRange(location: 0, length: statement.count)
|
|
642
|
-
if let match = regex.firstMatch(in: statement, options: [], range: range) {
|
|
643
|
-
let tableNameRange = match.range(at: 1)
|
|
644
|
-
if let tableNameRange = Range(tableNameRange, in: statement) {
|
|
645
|
-
let tableName = String(statement[tableNameRange])
|
|
646
|
-
return tableName
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
return nil
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
// MARK: - extractWhereClause
|
|
654
|
-
|
|
655
|
-
class func extractWhereClause(from statement: String) -> String? {
|
|
656
|
-
let pattern = "WHERE(.+?)(?:ORDER\\s+BY|LIMIT|$)"
|
|
657
|
-
guard let regex = try? NSRegularExpression(
|
|
658
|
-
pattern: pattern,
|
|
659
|
-
options: [.caseInsensitive, .dotMatchesLineSeparators]) else {
|
|
660
|
-
return nil
|
|
661
|
-
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
let range = NSRange(location: 0, length: statement.count)
|
|
665
|
-
if let match = regex.firstMatch(in: statement, options: [], range: range) {
|
|
666
|
-
let whereClauseRange = match.range(at: 1)
|
|
667
|
-
if let whereClauseRange = Range(whereClauseRange, in: statement) {
|
|
668
|
-
let whereClause = String(statement[whereClauseRange])
|
|
669
|
-
return whereClause.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
return nil
|
|
674
|
-
}
|
|
675
|
-
|
|
676
631
|
// swiftlint:enable cyclomatic_complexity
|
|
677
632
|
// swiftlint:enable function_body_length
|
|
678
633
|
|
|
679
634
|
// MARK: - deleteSQL
|
|
680
635
|
|
|
681
|
-
class func deleteSQL(mDB: Database, sql: String, values: [Any])
|
|
636
|
+
class func deleteSQL(mDB: Database, sql: String, values: [Any])
|
|
637
|
+
throws -> String {
|
|
682
638
|
var sqlStmt = sql
|
|
683
639
|
do {
|
|
684
640
|
let isLast: Bool = try UtilsJson.isLastModified(mDB: mDB)
|
|
685
641
|
let isDel: Bool = try UtilsJson.isSqlDeleted(mDB: mDB)
|
|
686
642
|
if isLast && isDel {
|
|
687
|
-
// Replace DELETE by UPDATE
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
.
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
tableName: tableName,
|
|
703
|
-
whereStmt: clauseStmt,
|
|
704
|
-
values: values)
|
|
705
|
-
} else {
|
|
706
|
-
let msg: String = "deleteSQL cannot find a WHERE clause"
|
|
643
|
+
// Replace DELETE by UPDATE
|
|
644
|
+
// set sql_deleted to 1 and the last_modified to
|
|
645
|
+
// timenow
|
|
646
|
+
guard let whereClause =
|
|
647
|
+
UtilsSQLStatement.extractWhereClause(from: sqlStmt)
|
|
648
|
+
else {
|
|
649
|
+
let msg: String = "deleteSQL cannot find a " +
|
|
650
|
+
"WHERE clause"
|
|
651
|
+
throw UtilsSQLCipherError.deleteSQL(message: msg)
|
|
652
|
+
}
|
|
653
|
+
guard let tableName =
|
|
654
|
+
UtilsSQLStatement.extractTableName(from: sqlStmt)
|
|
655
|
+
else {
|
|
656
|
+
let msg: String = "deleteSQL cannot find a " +
|
|
657
|
+
"WHERE clause"
|
|
707
658
|
throw UtilsSQLCipherError.deleteSQL(message: msg)
|
|
708
659
|
}
|
|
660
|
+
guard let colNames = try? UtilsSQLStatement
|
|
661
|
+
.extractColumnNames(from: whereClause)
|
|
662
|
+
else {
|
|
663
|
+
let msg = "Did not find column names in the" +
|
|
664
|
+
"WHERE Statement"
|
|
665
|
+
throw UtilsSQLCipherError.deleteSQL(message: msg)
|
|
666
|
+
}
|
|
667
|
+
let curTime = UtilsDelete.getCurrentTimeAsInteger()
|
|
668
|
+
|
|
669
|
+
let setStmt = "sql_deleted = 1"
|
|
670
|
+
// Find REFERENCIES if any and update the sql_deleted
|
|
671
|
+
// column
|
|
672
|
+
let hasToUpdate: Bool = try UtilsDelete
|
|
673
|
+
.findReferencesAndUpdate(mDB: mDB,
|
|
674
|
+
tableName: tableName,
|
|
675
|
+
whereStmt: whereClause,
|
|
676
|
+
initColNames: colNames,
|
|
677
|
+
values: values)
|
|
678
|
+
if hasToUpdate {
|
|
679
|
+
let whereStmt = whereClause.hasSuffix(";")
|
|
680
|
+
? String(whereClause.dropLast())
|
|
681
|
+
: whereClause
|
|
682
|
+
sqlStmt = "UPDATE \(tableName) SET \(setStmt) " +
|
|
683
|
+
"WHERE \(whereStmt) " +
|
|
684
|
+
"AND sql_deleted = 0;"
|
|
685
|
+
} else {
|
|
686
|
+
sqlStmt = ""
|
|
687
|
+
}
|
|
709
688
|
}
|
|
710
689
|
return sqlStmt
|
|
711
|
-
} catch
|
|
690
|
+
} catch UtilsDeleteError.findReferencesAndUpdate(let message) {
|
|
712
691
|
throw UtilsSQLCipherError.deleteSQL(message: message)
|
|
713
692
|
} catch UtilsJsonError.isLastModified(let message) {
|
|
714
693
|
throw UtilsSQLCipherError.deleteSQL(message: message)
|
|
@@ -717,306 +696,6 @@ class UtilsSQLCipher {
|
|
|
717
696
|
}
|
|
718
697
|
}
|
|
719
698
|
|
|
720
|
-
// MARK: - findReferencesAndUpdate
|
|
721
|
-
|
|
722
|
-
// swiftlint:disable function_body_length
|
|
723
|
-
// swiftlint:disable cyclomatic_complexity
|
|
724
|
-
class func findReferencesAndUpdate(mDB: Database, tableName: String,
|
|
725
|
-
whereStmt: String,
|
|
726
|
-
values: [Any]) throws {
|
|
727
|
-
var lastId: Int64 = -1
|
|
728
|
-
do {
|
|
729
|
-
var references = try getReferences(mDB: mDB,
|
|
730
|
-
tableName: tableName)
|
|
731
|
-
if references.count <= 0 {
|
|
732
|
-
return
|
|
733
|
-
}
|
|
734
|
-
guard let tableNameWithRefs = references.last else {
|
|
735
|
-
return
|
|
736
|
-
}
|
|
737
|
-
references.removeLast()
|
|
738
|
-
// Loop through references
|
|
739
|
-
for ref in references {
|
|
740
|
-
// get the tableName of the references
|
|
741
|
-
let refTable: String = getReferencesTableName(value: ref)
|
|
742
|
-
if refTable.count <= 0 {
|
|
743
|
-
continue
|
|
744
|
-
}
|
|
745
|
-
// get the with ref columnName
|
|
746
|
-
let withRefsNames: [String] = getWithRefsColumnName(value: ref)
|
|
747
|
-
if withRefsNames.count <= 0 {
|
|
748
|
-
continue
|
|
749
|
-
}
|
|
750
|
-
// get the columnName
|
|
751
|
-
let colNames: [String] = getReferencesColumnName(value: ref)
|
|
752
|
-
if colNames.count <= 0 {
|
|
753
|
-
continue
|
|
754
|
-
}
|
|
755
|
-
// update the where clause
|
|
756
|
-
let uWhereStmt: String = updateWhere(whStmt: whereStmt,
|
|
757
|
-
withRefs: withRefsNames,
|
|
758
|
-
colNames: colNames)
|
|
759
|
-
|
|
760
|
-
if uWhereStmt.count <= 0 {
|
|
761
|
-
continue
|
|
762
|
-
}
|
|
763
|
-
var updTableName: String = tableNameWithRefs
|
|
764
|
-
var updColNames: [String] = colNames
|
|
765
|
-
if tableNameWithRefs == tableName {
|
|
766
|
-
updTableName = refTable
|
|
767
|
-
updColNames = withRefsNames
|
|
768
|
-
}
|
|
769
|
-
//update sql_deleted for this references
|
|
770
|
-
let stmt = "UPDATE \(updTableName) SET sql_deleted = 1 " +
|
|
771
|
-
uWhereStmt
|
|
772
|
-
var selValues: [Any] = []
|
|
773
|
-
if !values.isEmpty {
|
|
774
|
-
var arrVal: [String] = whereStmt.components(separatedBy: "?")
|
|
775
|
-
if arrVal[arrVal.count - 1] == ";" {
|
|
776
|
-
arrVal.removeLast()
|
|
777
|
-
}
|
|
778
|
-
for (jdx, val) in arrVal.enumerated() {
|
|
779
|
-
for updVal in updColNames {
|
|
780
|
-
let indices: [Int] = val.indicesOf(string: updVal)
|
|
781
|
-
if indices.count > 0 {
|
|
782
|
-
selValues.append(values[jdx])
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
let resp = try prepareSQL(mDB: mDB, sql: stmt,
|
|
789
|
-
values: selValues,
|
|
790
|
-
fromJson: false, returnMode: "no")
|
|
791
|
-
lastId = resp.0
|
|
792
|
-
if lastId == -1 {
|
|
793
|
-
let msg = "UPDATE sql_deleted failed for references " +
|
|
794
|
-
"table: \(refTable) "
|
|
795
|
-
throw UtilsSQLCipherError
|
|
796
|
-
.findReferencesAndUpdate(message: msg)
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
return
|
|
800
|
-
} catch UtilsSQLCipherError.prepareSQL(let message) {
|
|
801
|
-
throw UtilsSQLCipherError
|
|
802
|
-
.findReferencesAndUpdate(message: message)
|
|
803
|
-
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
804
|
-
throw UtilsSQLCipherError
|
|
805
|
-
.findReferencesAndUpdate(message: message)
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
}
|
|
809
|
-
// swiftlint:enable cyclomatic_complexity
|
|
810
|
-
// swiftlint:enable function_body_length
|
|
811
|
-
|
|
812
|
-
// MARK: - getReferences
|
|
813
|
-
|
|
814
|
-
class func getReferences(mDB: Database, tableName: String)
|
|
815
|
-
throws -> [String] {
|
|
816
|
-
// find the REFERENCES
|
|
817
|
-
var sqlStmt = "SELECT sql FROM sqlite_master "
|
|
818
|
-
sqlStmt += "WHERE sql LIKE('%FOREIGN KEY%') AND "
|
|
819
|
-
sqlStmt += "sql LIKE('%REFERENCES%') AND "
|
|
820
|
-
sqlStmt += "sql LIKE('%\(tableName)%') AND sql LIKE('%ON DELETE%');"
|
|
821
|
-
do {
|
|
822
|
-
var references: [[String: Any]] = try querySQL(mDB: mDB,
|
|
823
|
-
sql: sqlStmt,
|
|
824
|
-
values: [])
|
|
825
|
-
var retRefs: [String] = []
|
|
826
|
-
if references.count > 1 {
|
|
827
|
-
references.removeFirst()
|
|
828
|
-
if let refValue = references[0]["sql"] as? String {
|
|
829
|
-
retRefs = try getRefs(str: refValue)
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
return retRefs
|
|
833
|
-
} catch UtilsSQLCipherError.getRefs(let message) {
|
|
834
|
-
throw UtilsSQLCipherError
|
|
835
|
-
.getReferences(message: message)
|
|
836
|
-
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
837
|
-
throw UtilsSQLCipherError
|
|
838
|
-
.getReferences(message: message)
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
class func getRefs(str: String) throws -> [String] {
|
|
842
|
-
var retRefs: [String] = []
|
|
843
|
-
let indicesFK: [Int] = str.indicesOf(string: "FOREIGN KEY")
|
|
844
|
-
let indicesOD: [Int] = str.indicesOf(string: "ON DELETE")
|
|
845
|
-
if indicesFK.count > 0 && indicesOD.count > 0
|
|
846
|
-
&& indicesFK.count != indicesOD.count {
|
|
847
|
-
let msg: String = "Indices of FOREIGN KEY and ON DELETE not equal"
|
|
848
|
-
throw UtilsSQLCipherError.getRefs(message: msg)
|
|
849
|
-
|
|
850
|
-
}
|
|
851
|
-
for (idx, iFK) in indicesFK.enumerated() {
|
|
852
|
-
let ref: String = String(str.stringRange(fromIdx: iFK + 11,
|
|
853
|
-
toIdx: indicesOD[idx]))
|
|
854
|
-
.trimmingLeadingAndTrailingSpaces()
|
|
855
|
-
retRefs.append(ref)
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
if let range: Range<String.Index> = str
|
|
859
|
-
.range(of: "CREATE TABLE", options: .caseInsensitive) {
|
|
860
|
-
let index: Int = str
|
|
861
|
-
.distance(from: str.startIndex, to: range.lowerBound)
|
|
862
|
-
let stmt = String(str.stringRange(fromIdx: index + 13,
|
|
863
|
-
toIdx: str.count))
|
|
864
|
-
if let oPar = stmt.firstIndex(of: "(") {
|
|
865
|
-
let idx: Int = stmt.distance(from: stmt.startIndex, to: oPar)
|
|
866
|
-
let tableName: String = String(stmt.stringRange(fromIdx: 0,
|
|
867
|
-
toIdx: idx))
|
|
868
|
-
.trimmingLeadingAndTrailingSpaces()
|
|
869
|
-
retRefs.append(tableName)
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
return retRefs
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
// MARK: - getReferencesTableName
|
|
877
|
-
|
|
878
|
-
class func getReferencesTableName(value: String) -> String {
|
|
879
|
-
|
|
880
|
-
var tableName: String = ""
|
|
881
|
-
if value.isEmpty {
|
|
882
|
-
return tableName
|
|
883
|
-
}
|
|
884
|
-
let indicesRef: [Int] = value.indicesOf(string: "REFERENCES")
|
|
885
|
-
if indicesRef.count > 0 {
|
|
886
|
-
let val: String = String(value.stringRange(
|
|
887
|
-
fromIdx: indicesRef[0] + 10,
|
|
888
|
-
toIdx: value.count))
|
|
889
|
-
if let oPar = val.firstIndex(of: "(") {
|
|
890
|
-
let idx: Int = val.distance(from: val.startIndex, to: oPar)
|
|
891
|
-
tableName = String(val.stringRange(fromIdx: 0,
|
|
892
|
-
toIdx: idx))
|
|
893
|
-
.trimmingLeadingAndTrailingSpaces()
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
return tableName
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
// MARK: - getWithRefColumnName
|
|
900
|
-
|
|
901
|
-
class func getWithRefsColumnName(value: String) -> [String] {
|
|
902
|
-
|
|
903
|
-
var colNames: [String] = []
|
|
904
|
-
if value.isEmpty {
|
|
905
|
-
return colNames
|
|
906
|
-
}
|
|
907
|
-
let indicesRef: [Int] = value.indicesOf(string: "REFERENCES")
|
|
908
|
-
if indicesRef.count > 0 {
|
|
909
|
-
let val: String = String(value.stringRange(
|
|
910
|
-
fromIdx: 0,
|
|
911
|
-
toIdx: indicesRef[0] - 1))
|
|
912
|
-
if let oPar = val.firstIndex(of: "(") {
|
|
913
|
-
let idxOPar: Int = val.distance(from: val.startIndex, to: oPar)
|
|
914
|
-
if let cPar = val.firstIndex(of: ")") {
|
|
915
|
-
let idxCPar: Int = val.distance(from: val.startIndex,
|
|
916
|
-
to: cPar)
|
|
917
|
-
|
|
918
|
-
let colStr: String = String(val
|
|
919
|
-
.stringRange(fromIdx: idxOPar + 1,
|
|
920
|
-
toIdx: idxCPar))
|
|
921
|
-
.trimmingLeadingAndTrailingSpaces()
|
|
922
|
-
colNames = colStr.split(separator: ",").map(String.init)
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
return colNames
|
|
927
|
-
}
|
|
928
|
-
// MARK: - getReferencesColumnName
|
|
929
|
-
|
|
930
|
-
class func getReferencesColumnName(value: String) -> [String] {
|
|
931
|
-
|
|
932
|
-
var colNames: [String] = []
|
|
933
|
-
if value.isEmpty {
|
|
934
|
-
return colNames
|
|
935
|
-
}
|
|
936
|
-
let indicesRef: [Int] = value.indicesOf(string: "REFERENCES")
|
|
937
|
-
if indicesRef.count > 0 {
|
|
938
|
-
let val: String = String(value.stringRange(
|
|
939
|
-
fromIdx: indicesRef[0] + 10,
|
|
940
|
-
toIdx: value.count))
|
|
941
|
-
if let oPar = val.firstIndex(of: "(") {
|
|
942
|
-
let idxOPar: Int = val.distance(from: val.startIndex, to: oPar)
|
|
943
|
-
if let cPar = val.firstIndex(of: ")") {
|
|
944
|
-
let idxCPar: Int = val.distance(from: val.startIndex,
|
|
945
|
-
to: cPar)
|
|
946
|
-
|
|
947
|
-
let colStr: String = String(val
|
|
948
|
-
.stringRange(fromIdx: idxOPar + 1,
|
|
949
|
-
toIdx: idxCPar))
|
|
950
|
-
.trimmingLeadingAndTrailingSpaces()
|
|
951
|
-
colNames = colStr.split(separator: ",").map(String.init)
|
|
952
|
-
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
return colNames
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
// swiftlint:disable function_body_length
|
|
960
|
-
class func updateWhere(whStmt: String, withRefs: [String],
|
|
961
|
-
colNames: [String]) -> String {
|
|
962
|
-
var whereStmt = ""
|
|
963
|
-
if whStmt.count > 0 {
|
|
964
|
-
let indicesWhere: [Int] = whStmt.indicesOf(string: "WHERE")
|
|
965
|
-
if indicesWhere.count == 0 {
|
|
966
|
-
return whereStmt
|
|
967
|
-
}
|
|
968
|
-
var stmt: String = String(whStmt.stringRange(
|
|
969
|
-
fromIdx: indicesWhere[0] + 6,
|
|
970
|
-
toIdx: whStmt.count))
|
|
971
|
-
if withRefs.count == colNames.count {
|
|
972
|
-
for (idx, wRf) in withRefs.enumerated() {
|
|
973
|
-
var colType: String = "withRefsNames"
|
|
974
|
-
var idxs: [Int] = stmt.indicesOf(string: wRf)
|
|
975
|
-
if idxs.count == 0 {
|
|
976
|
-
idxs = stmt.indicesOf(string: colNames[idx])
|
|
977
|
-
colType = "colNames"
|
|
978
|
-
}
|
|
979
|
-
if idxs.count > 0 {
|
|
980
|
-
var valStr: String = ""
|
|
981
|
-
let indicesEqual: [Int] = stmt
|
|
982
|
-
.indicesOf(string: "=",
|
|
983
|
-
fromIdx: idxs[0])
|
|
984
|
-
|
|
985
|
-
if indicesEqual.count > 0 {
|
|
986
|
-
let indicesAnd: [Int] = stmt
|
|
987
|
-
.indicesOf(string: "AND",
|
|
988
|
-
fromIdx: indicesEqual[0])
|
|
989
|
-
if indicesAnd.count > 0 {
|
|
990
|
-
valStr = String(stmt.stringRange(
|
|
991
|
-
fromIdx: indicesEqual[0] + 1,
|
|
992
|
-
toIdx: indicesAnd[0] - 1))
|
|
993
|
-
stmt = String(stmt.stringRange(
|
|
994
|
-
fromIdx: indicesAnd[0] + 3,
|
|
995
|
-
toIdx: stmt.count))
|
|
996
|
-
} else {
|
|
997
|
-
valStr = String(stmt.stringRange(
|
|
998
|
-
fromIdx: indicesEqual[0] + 1,
|
|
999
|
-
toIdx: stmt.count))
|
|
1000
|
-
}
|
|
1001
|
-
if idx > 0 {
|
|
1002
|
-
whereStmt += " AND "
|
|
1003
|
-
}
|
|
1004
|
-
if colType == "withRefsNames" {
|
|
1005
|
-
whereStmt += colNames[idx] + " = " + valStr
|
|
1006
|
-
} else {
|
|
1007
|
-
whereStmt += withRefs[idx] + " = " + valStr
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
}
|
|
1013
|
-
whereStmt = "WHERE " + whereStmt
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
return whereStmt
|
|
1017
|
-
}
|
|
1018
|
-
// swiftlint:enable function_body_length
|
|
1019
|
-
|
|
1020
699
|
// MARK: - querySQL
|
|
1021
700
|
|
|
1022
701
|
class func querySQL(mDB: Database, sql: String,
|
|
@@ -1044,7 +723,8 @@ class UtilsSQLCipher {
|
|
|
1044
723
|
handle: selectSQLStatement, returnMode: "all")
|
|
1045
724
|
} catch UtilsSQLCipherError
|
|
1046
725
|
.fetchColumnInfo(let message) {
|
|
1047
|
-
throw UtilsSQLCipherError
|
|
726
|
+
throw UtilsSQLCipherError
|
|
727
|
+
.querySQL(message: message)
|
|
1048
728
|
}
|
|
1049
729
|
}
|
|
1050
730
|
} else {
|
|
@@ -1071,7 +751,8 @@ class UtilsSQLCipher {
|
|
|
1071
751
|
|
|
1072
752
|
// swiftlint:disable function_body_length
|
|
1073
753
|
// swiftlint:disable cyclomatic_complexity
|
|
1074
|
-
class func fetchColumnInfo(handle: OpaquePointer?,
|
|
754
|
+
class func fetchColumnInfo(handle: OpaquePointer?,
|
|
755
|
+
returnMode: String)
|
|
1075
756
|
throws -> [[String: Any]] {
|
|
1076
757
|
var result: [[String: Any]] = []
|
|
1077
758
|
var columnCount: Int32 = 0
|
|
@@ -1099,17 +780,20 @@ class UtilsSQLCipher {
|
|
|
1099
780
|
}
|
|
1100
781
|
switch sqlite3_column_type(handle, Int32(index)) {
|
|
1101
782
|
case SQLITE_INTEGER:
|
|
1102
|
-
let val: Int64 = sqlite3_column_int64(handle,
|
|
783
|
+
let val: Int64 = sqlite3_column_int64(handle,
|
|
784
|
+
index)
|
|
1103
785
|
rowData[String(cString: name)] = val
|
|
1104
786
|
case SQLITE_FLOAT:
|
|
1105
|
-
let val: Double = sqlite3_column_double(handle,
|
|
787
|
+
let val: Double = sqlite3_column_double(handle,
|
|
788
|
+
index)
|
|
1106
789
|
rowData[String(cString: name)] = val
|
|
1107
790
|
case SQLITE_BLOB:
|
|
1108
|
-
if let dataBlob = sqlite3_column_blob(handle,
|
|
1109
|
-
|
|
791
|
+
if let dataBlob = sqlite3_column_blob(handle,
|
|
792
|
+
index) {
|
|
793
|
+
let dataBlobLength = sqlite3_column_bytes(
|
|
794
|
+
handle, index)
|
|
1110
795
|
let data = Data(bytes: dataBlob,
|
|
1111
796
|
count: Int(dataBlobLength))
|
|
1112
|
-
// rowData[String(cString: name)] = data.base64EncodedString()
|
|
1113
797
|
rowData[String(cString: name)] = data.bytes
|
|
1114
798
|
} else {
|
|
1115
799
|
rowData[String(cString: name)] = NSNull()
|
|
@@ -1126,7 +810,8 @@ class UtilsSQLCipher {
|
|
|
1126
810
|
case SQLITE_NULL:
|
|
1127
811
|
rowData[String(cString: name)] = NSNull()
|
|
1128
812
|
case let type:
|
|
1129
|
-
var message = "Error: fetchColumnInfo
|
|
813
|
+
var message = "Error: fetchColumnInfo " +
|
|
814
|
+
"column_type \(type) "
|
|
1130
815
|
message.append("failed")
|
|
1131
816
|
throw UtilsSQLCipherError
|
|
1132
817
|
.fetchColumnInfo(message: message)
|
|
@@ -1165,14 +850,20 @@ class UtilsSQLCipher {
|
|
|
1165
850
|
var resArr: [String] = []
|
|
1166
851
|
for stmt in stmtArr {
|
|
1167
852
|
let trimStmt = stmt
|
|
1168
|
-
.trimmingLeadingAndTrailingSpaces().prefix(11)
|
|
853
|
+
.trimmingLeadingAndTrailingSpaces().prefix(11)
|
|
854
|
+
.uppercased()
|
|
1169
855
|
if trimStmt == "DELETE FROM" &&
|
|
1170
856
|
stmt.localizedCaseInsensitiveContains("WHERE") {
|
|
1171
|
-
let whereStmt = stmt
|
|
857
|
+
let whereStmt = stmt
|
|
858
|
+
.trimmingLeadingAndTrailingSpaces()
|
|
1172
859
|
do {
|
|
1173
|
-
let rStmt: String = try deleteSQL(
|
|
1174
|
-
|
|
1175
|
-
|
|
860
|
+
let rStmt: String = try deleteSQL(
|
|
861
|
+
mDB: mDB, sql: whereStmt, values: [])
|
|
862
|
+
if !rStmt.isEmpty {
|
|
863
|
+
resArr.append(rStmt)
|
|
864
|
+
}
|
|
865
|
+
} catch UtilsSQLCipherError
|
|
866
|
+
.deleteSQL(let message) {
|
|
1176
867
|
let msg = "Error: execute \(message)"
|
|
1177
868
|
throw UtilsSQLCipherError.execute(message: msg)
|
|
1178
869
|
}
|
|
@@ -1182,7 +873,7 @@ class UtilsSQLCipher {
|
|
|
1182
873
|
}
|
|
1183
874
|
sqlStmt = resArr.joined(separator: ";")
|
|
1184
875
|
}
|
|
1185
|
-
|
|
876
|
+
let curTime = UtilsDelete.getCurrentTimeAsInteger()
|
|
1186
877
|
let returnCode: Int32 = sqlite3_exec(mDB.mDb, sqlStmt, nil,
|
|
1187
878
|
nil, nil)
|
|
1188
879
|
if returnCode != SQLITE_OK {
|
|
@@ -1198,7 +889,8 @@ class UtilsSQLCipher {
|
|
|
1198
889
|
|
|
1199
890
|
// MARK: - DeleteDB
|
|
1200
891
|
|
|
1201
|
-
class func deleteDB(databaseLocation: String,
|
|
892
|
+
class func deleteDB(databaseLocation: String,
|
|
893
|
+
databaseName: String) throws {
|
|
1202
894
|
do {
|
|
1203
895
|
let dir: URL = try UtilsFile
|
|
1204
896
|
.getFolderURL(folderPath: databaseLocation)
|
|
@@ -1225,7 +917,8 @@ class UtilsSQLCipher {
|
|
|
1225
917
|
// MARK: - ExecuteSet
|
|
1226
918
|
|
|
1227
919
|
// swiftlint:disable function_body_length
|
|
1228
|
-
class func executeSet(mDB: Database, set: [[String: Any]],
|
|
920
|
+
class func executeSet(mDB: Database, set: [[String: Any]],
|
|
921
|
+
returnMode: String)
|
|
1229
922
|
throws -> (Int64, [[String: Any]]) {
|
|
1230
923
|
var msg: String = "Error executeSet: "
|
|
1231
924
|
if !mDB.isDBOpen() {
|
|
@@ -1247,13 +940,17 @@ class UtilsSQLCipher {
|
|
|
1247
940
|
message: "No values given")
|
|
1248
941
|
}
|
|
1249
942
|
var respSet: [[String: Any]] = []
|
|
1250
|
-
|
|
943
|
+
var isArray = false
|
|
944
|
+
if values.count > 0 {
|
|
945
|
+
isArray = UtilsSQLCipher.parse(mVar: values[0])
|
|
946
|
+
}
|
|
1251
947
|
if isArray {
|
|
1252
948
|
if let arrValues = values as? [[Any]] {
|
|
1253
949
|
for vals in arrValues {
|
|
1254
950
|
let resp = try UtilsSQLCipher
|
|
1255
951
|
.prepareSQL(mDB: mDB, sql: sql,
|
|
1256
|
-
values: vals,
|
|
952
|
+
values: vals,
|
|
953
|
+
fromJson: false,
|
|
1257
954
|
returnMode: returnMode)
|
|
1258
955
|
lastId = resp.0
|
|
1259
956
|
respSet = resp.1
|