@capacitor-community/sqlite 5.0.6 → 5.0.7-1
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
CHANGED
|
@@ -171,8 +171,11 @@ npm install --save better-sqlite3-multiple-ciphers
|
|
|
171
171
|
npm install --save electron-json-storage
|
|
172
172
|
npm install --save jszip
|
|
173
173
|
npm install --save node-fetch@2.6.7
|
|
174
|
+
npm install --save crypto
|
|
175
|
+
npm install --save crypto-js
|
|
174
176
|
npm install --save-dev @types/better-sqlite3
|
|
175
177
|
npm install --save-dev @types/electron-json-storage
|
|
178
|
+
npm install --save-dev @types/crypto-js
|
|
176
179
|
```
|
|
177
180
|
- **Important**: `node-fetch` version must be `<=2.6.7`; otherwise [you'll get an error](https://github.com/capacitor-community/sqlite/issues/349 "you'll get an error ERR_REQUIRE_ESM") running the app.
|
|
178
181
|
|
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
//
|
|
2
|
+
// UtilsDelete.swift
|
|
3
|
+
// CapacitorCommunitySqlite
|
|
4
|
+
//
|
|
5
|
+
// Created by Quéau Jean Pierre on 30/07/2023.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
enum UtilsDeleteError: Error {
|
|
10
|
+
case findReferencesAndUpdate(message: String)
|
|
11
|
+
case getReferences(message: String)
|
|
12
|
+
case getRefs(message: String)
|
|
13
|
+
case getUpdDelReturnedValues(message: String)
|
|
14
|
+
case getFirstPK(message: String)
|
|
15
|
+
case extractColumnNames(message: String)
|
|
16
|
+
case executeUpdateForDelete(message: String)
|
|
17
|
+
case extractForeignKeyInfo(message: String)
|
|
18
|
+
case searchForRelatedItems(message: String)
|
|
19
|
+
case upDateWhereForRestrict(message: String)
|
|
20
|
+
case upDateWhereForCascade(message: String)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// swiftlint:disable type_body_length
|
|
24
|
+
class UtilsDelete {
|
|
25
|
+
|
|
26
|
+
// MARK: - findReferencesAndUpdate
|
|
27
|
+
|
|
28
|
+
// swiftlint:disable function_body_length
|
|
29
|
+
// swiftlint:disable cyclomatic_complexity
|
|
30
|
+
class func findReferencesAndUpdate(mDB: Database, tableName: String,
|
|
31
|
+
whereStmt: String,
|
|
32
|
+
initColNames: [String],
|
|
33
|
+
values: [Any]) throws -> Bool {
|
|
34
|
+
do {
|
|
35
|
+
var retBool: Bool = true
|
|
36
|
+
let result = try getReferences(mDB: mDB,
|
|
37
|
+
tableName: tableName)
|
|
38
|
+
let references = result.retRefs
|
|
39
|
+
let tableNameWithRefs = result.tableWithRefs
|
|
40
|
+
if references.count <= 0 {
|
|
41
|
+
return retBool
|
|
42
|
+
}
|
|
43
|
+
if tableName == tableNameWithRefs {
|
|
44
|
+
return retBool
|
|
45
|
+
}
|
|
46
|
+
// Loop through references
|
|
47
|
+
for ref in references {
|
|
48
|
+
|
|
49
|
+
// Extract the FOREIGN KEY constraint info
|
|
50
|
+
// from the ref statement
|
|
51
|
+
let foreignKeyInfo = try UtilsSQLStatement
|
|
52
|
+
.extractForeignKeyInfo(from: ref)
|
|
53
|
+
// get the tableName of the references
|
|
54
|
+
guard let refTable = foreignKeyInfo["tableName"]
|
|
55
|
+
as? String else {
|
|
56
|
+
let msg = "findReferencesAndUpdate: no foreignKeyInfo " +
|
|
57
|
+
"tableName"
|
|
58
|
+
throw UtilsDeleteError
|
|
59
|
+
.findReferencesAndUpdate(message: msg)
|
|
60
|
+
}
|
|
61
|
+
if refTable.isEmpty || refTable != tableName {
|
|
62
|
+
continue
|
|
63
|
+
}
|
|
64
|
+
// get the with ref columnName
|
|
65
|
+
guard let withRefsNames = foreignKeyInfo["forKeys"]
|
|
66
|
+
as? [String] else {
|
|
67
|
+
|
|
68
|
+
let msg = "findReferencesAndUpdate: no foreignKeyInfo " +
|
|
69
|
+
"forKeys"
|
|
70
|
+
throw UtilsDeleteError
|
|
71
|
+
.findReferencesAndUpdate(message: msg)
|
|
72
|
+
}
|
|
73
|
+
guard let colNames = foreignKeyInfo["refKeys"]
|
|
74
|
+
as? [String] else {
|
|
75
|
+
let msg = "findReferencesAndUpdate: no foreignKeyInfo " +
|
|
76
|
+
"refKeys"
|
|
77
|
+
throw UtilsDeleteError
|
|
78
|
+
.findReferencesAndUpdate(message: msg)
|
|
79
|
+
}
|
|
80
|
+
if colNames.count != withRefsNames.count {
|
|
81
|
+
let msg = "findReferencesAndUpdate: no foreignKeyInfo " +
|
|
82
|
+
"colNames"
|
|
83
|
+
throw UtilsDeleteError
|
|
84
|
+
.findReferencesAndUpdate(message: msg)
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
guard let action = foreignKeyInfo["action"]
|
|
88
|
+
as? String else {
|
|
89
|
+
let msg = "findReferencesAndUpdate: no action"
|
|
90
|
+
throw UtilsDeleteError
|
|
91
|
+
.findReferencesAndUpdate(message: msg)
|
|
92
|
+
}
|
|
93
|
+
if action == "NO_ACTION" {
|
|
94
|
+
continue
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
var updTableName: String = tableNameWithRefs
|
|
98
|
+
var updColNames: [String] = withRefsNames
|
|
99
|
+
var results: (setStmt: String, uWhereStmt: String)
|
|
100
|
+
results.uWhereStmt = ""
|
|
101
|
+
results.setStmt = ""
|
|
102
|
+
if !checkValuesMatch(withRefsNames,
|
|
103
|
+
against: initColNames) {
|
|
104
|
+
// Search for related items in tableName
|
|
105
|
+
let result: (String,[[String: Any]]) = try UtilsDelete
|
|
106
|
+
.searchForRelatedItems(mDB: mDB,
|
|
107
|
+
updTableName: updTableName,
|
|
108
|
+
tableName: tableName,
|
|
109
|
+
whStmt: whereStmt,
|
|
110
|
+
withRefsNames: withRefsNames,
|
|
111
|
+
colNames: colNames,
|
|
112
|
+
values: values);
|
|
113
|
+
let key: String = result.0
|
|
114
|
+
let relatedItems: [Any] = result.1
|
|
115
|
+
if relatedItems.count == 0 && key.count <= 0 {
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// case no match
|
|
120
|
+
if updTableName != tableName {
|
|
121
|
+
switch action {
|
|
122
|
+
case "CASCADE":
|
|
123
|
+
// updTableName
|
|
124
|
+
// update all related element
|
|
125
|
+
// set sql_deleted = 1 and last_modified
|
|
126
|
+
// tableName
|
|
127
|
+
//update all by sending return true
|
|
128
|
+
results = try upDateWhereForCascade(
|
|
129
|
+
results: result)
|
|
130
|
+
|
|
131
|
+
case "RESTRICT":
|
|
132
|
+
// find for elements related in updTableName
|
|
133
|
+
// if some elements
|
|
134
|
+
// send a message
|
|
135
|
+
// do not update tableName
|
|
136
|
+
// return false
|
|
137
|
+
// If no related elements in updTableName
|
|
138
|
+
// return true to update tableName
|
|
139
|
+
results = try upDateWhereForRestrict(
|
|
140
|
+
results: result)
|
|
141
|
+
|
|
142
|
+
default:
|
|
143
|
+
// updTableName
|
|
144
|
+
// update the result_id result_slug to Null
|
|
145
|
+
// update the last_modified
|
|
146
|
+
// keep sql_deleted to 0
|
|
147
|
+
// return true to update tableName
|
|
148
|
+
results = try upDateWhereForDefault(
|
|
149
|
+
withRefsNames: withRefsNames,
|
|
150
|
+
results: result)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
} else {
|
|
155
|
+
let msg = "Not implemented. Please transfer your " +
|
|
156
|
+
"example to the maintener"
|
|
157
|
+
throw UtilsDeleteError
|
|
158
|
+
.findReferencesAndUpdate(message: msg)
|
|
159
|
+
}
|
|
160
|
+
if results.setStmt.count > 0 &&
|
|
161
|
+
results.uWhereStmt.count > 0 {
|
|
162
|
+
|
|
163
|
+
try executeUpdateForDelete(
|
|
164
|
+
mDB: mDB,
|
|
165
|
+
tableName: updTableName,
|
|
166
|
+
whereStmt: results.uWhereStmt,
|
|
167
|
+
setStmt: results.setStmt,
|
|
168
|
+
colNames: updColNames,
|
|
169
|
+
values: values)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return retBool
|
|
173
|
+
} catch UtilsDeleteError.upDateWhereForRestrict(let message) {
|
|
174
|
+
throw UtilsDeleteError
|
|
175
|
+
.findReferencesAndUpdate(message: message)
|
|
176
|
+
} catch UtilsSQLStatementError
|
|
177
|
+
.extractForeignKeyInfo(let message) {
|
|
178
|
+
throw UtilsDeleteError
|
|
179
|
+
.findReferencesAndUpdate(message: message)
|
|
180
|
+
} catch UtilsDeleteError.executeUpdateForDelete(let message) {
|
|
181
|
+
throw UtilsDeleteError
|
|
182
|
+
.findReferencesAndUpdate(message: message)
|
|
183
|
+
} catch UtilsSQLCipherError.prepareSQL(let message) {
|
|
184
|
+
throw UtilsDeleteError
|
|
185
|
+
.findReferencesAndUpdate(message: message)
|
|
186
|
+
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
187
|
+
throw UtilsDeleteError
|
|
188
|
+
.findReferencesAndUpdate(message: message)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// swiftlint:enable cyclomatic_complexity
|
|
192
|
+
// swiftlint:enable function_body_length
|
|
193
|
+
|
|
194
|
+
// MARK: - upDateWhereForDefault
|
|
195
|
+
|
|
196
|
+
class func upDateWhereForDefault(withRefsNames: [String],
|
|
197
|
+
results: (String,[[String:Any]]))
|
|
198
|
+
throws -> ((setStmt: String, uWhereStmt: String)) {
|
|
199
|
+
|
|
200
|
+
var setStmt = ""
|
|
201
|
+
var uWhereStmt = ""
|
|
202
|
+
let key: String = results.0
|
|
203
|
+
let relatedItems = results.1
|
|
204
|
+
|
|
205
|
+
var cols: [Any] = []
|
|
206
|
+
for relItem in relatedItems {
|
|
207
|
+
if let mVal = relItem[key] {
|
|
208
|
+
cols.append(mVal)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// create the set statement
|
|
212
|
+
for name in withRefsNames {
|
|
213
|
+
setStmt += "\(name) = NULL, "
|
|
214
|
+
}
|
|
215
|
+
setStmt += "sql_deleted = 0"
|
|
216
|
+
|
|
217
|
+
// create the where statement
|
|
218
|
+
uWhereStmt = "WHERE \(key) IN ("
|
|
219
|
+
for col in cols {
|
|
220
|
+
uWhereStmt += "\(col),"
|
|
221
|
+
}
|
|
222
|
+
if uWhereStmt.hasSuffix(",") {
|
|
223
|
+
uWhereStmt = String(uWhereStmt.dropLast())
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
uWhereStmt += ");"
|
|
227
|
+
|
|
228
|
+
return(setStmt, uWhereStmt)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// MARK: - upDateWhereForRestrict
|
|
232
|
+
|
|
233
|
+
class func upDateWhereForRestrict(results: (String,[[String: Any]]))
|
|
234
|
+
throws -> ((setStmt: String, uWhereStmt: String)) {
|
|
235
|
+
|
|
236
|
+
// Search for related items in tableName
|
|
237
|
+
let setStmt = ""
|
|
238
|
+
let uWhereStmt = ""
|
|
239
|
+
let relatedItems = results.1
|
|
240
|
+
|
|
241
|
+
if !relatedItems.isEmpty {
|
|
242
|
+
let msg = "Restrict mode related items exist" +
|
|
243
|
+
" please delete them first"
|
|
244
|
+
throw UtilsDeleteError
|
|
245
|
+
.upDateWhereForRestrict(message: msg)
|
|
246
|
+
}
|
|
247
|
+
return(setStmt, uWhereStmt)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// MARK: - upDateWhereForCascade
|
|
251
|
+
|
|
252
|
+
class func upDateWhereForCascade(results: (String,[[String:Any]]))
|
|
253
|
+
throws -> ((setStmt: String, uWhereStmt: String)) {
|
|
254
|
+
|
|
255
|
+
// Search for related items in tableName
|
|
256
|
+
var setStmt = ""
|
|
257
|
+
var uWhereStmt = ""
|
|
258
|
+
let key: String = results.0
|
|
259
|
+
let relatedItems = results.1
|
|
260
|
+
var cols: [Any] = []
|
|
261
|
+
for relItem in relatedItems {
|
|
262
|
+
if let mVal = relItem[key] {
|
|
263
|
+
cols.append(mVal)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
setStmt += "sql_deleted = 1"
|
|
267
|
+
// create the where statement
|
|
268
|
+
uWhereStmt = "WHERE \(key) IN ("
|
|
269
|
+
for col in cols {
|
|
270
|
+
uWhereStmt += "\(col),"
|
|
271
|
+
}
|
|
272
|
+
if uWhereStmt.hasSuffix(",") {
|
|
273
|
+
uWhereStmt = String(uWhereStmt.dropLast())
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
uWhereStmt += ");"
|
|
277
|
+
return (setStmt, uWhereStmt)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// MARK: - searchForRelatedItems
|
|
281
|
+
|
|
282
|
+
// swiftlint:disable function_parameter_count
|
|
283
|
+
class func searchForRelatedItems(mDB: Database,
|
|
284
|
+
updTableName: String,
|
|
285
|
+
tableName: String, whStmt: String,
|
|
286
|
+
withRefsNames: [String],
|
|
287
|
+
colNames: [String], values: [Any])
|
|
288
|
+
throws -> (String,[[String: Any]]) {
|
|
289
|
+
var relatedItems: [[String: Any]] = []
|
|
290
|
+
var key: String = ""
|
|
291
|
+
let t1Names = withRefsNames.map { "t1.\($0)" }
|
|
292
|
+
let t2Names = colNames.map { "t2.\($0)" }
|
|
293
|
+
|
|
294
|
+
do {
|
|
295
|
+
var whereClause = try UtilsSQLStatement
|
|
296
|
+
.addPrefixToWhereClause(whStmt, from: colNames,
|
|
297
|
+
to: withRefsNames,
|
|
298
|
+
prefix: "t2.")
|
|
299
|
+
if whereClause.hasSuffix(";") {
|
|
300
|
+
whereClause = String(whereClause.dropLast())
|
|
301
|
+
}
|
|
302
|
+
let resultString = zip(t1Names, t2Names)
|
|
303
|
+
.map {"\($0) = \($1)" }
|
|
304
|
+
.joined(separator: " AND ")
|
|
305
|
+
|
|
306
|
+
let sql = "SELECT t1.rowid FROM \(updTableName) t1 " +
|
|
307
|
+
"JOIN \(tableName) t2 ON \(resultString) " +
|
|
308
|
+
"WHERE \(whereClause) AND t1.sql_deleted = 0;"
|
|
309
|
+
var vals = try UtilsSQLCipher.querySQL(mDB: mDB, sql: sql,
|
|
310
|
+
values: values)
|
|
311
|
+
if vals.count > 1 {
|
|
312
|
+
if let mVals = vals[0]["ios_columns"] as? [String] {
|
|
313
|
+
key = mVals[0]
|
|
314
|
+
let keyToRemove = "ios_columns"
|
|
315
|
+
vals.removeAll { dict in
|
|
316
|
+
return dict.keys.contains(keyToRemove)
|
|
317
|
+
}
|
|
318
|
+
for val in vals {
|
|
319
|
+
relatedItems.append(val)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return (key, relatedItems)
|
|
324
|
+
} catch UtilsSQLStatementError.addPrefixToWhereClause(let message) {
|
|
325
|
+
throw UtilsDeleteError
|
|
326
|
+
.searchForRelatedItems(message: message)
|
|
327
|
+
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
328
|
+
throw UtilsDeleteError
|
|
329
|
+
.searchForRelatedItems(message: message)
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// swiftlint:enable function_parameter_count
|
|
333
|
+
|
|
334
|
+
// MARK: - executeUpdateForDelete
|
|
335
|
+
|
|
336
|
+
// swiftlint:disable function_parameter_count
|
|
337
|
+
class func executeUpdateForDelete(mDB: Database, tableName: String,
|
|
338
|
+
whereStmt: String, setStmt: String,
|
|
339
|
+
colNames: [String], values: [Any])
|
|
340
|
+
throws {
|
|
341
|
+
var lastId: Int64 = -1
|
|
342
|
+
//update sql_deleted for this references
|
|
343
|
+
let stmt = "UPDATE \(tableName) SET \(setStmt) \(whereStmt)"
|
|
344
|
+
var selValues: [Any] = []
|
|
345
|
+
if !values.isEmpty {
|
|
346
|
+
var arrVal: [String] = whereStmt
|
|
347
|
+
.components(separatedBy: "?")
|
|
348
|
+
if arrVal[arrVal.count - 1] == ";" {
|
|
349
|
+
arrVal.removeLast()
|
|
350
|
+
}
|
|
351
|
+
for (jdx, val) in arrVal.enumerated() {
|
|
352
|
+
for updVal in colNames {
|
|
353
|
+
let indices: [Int] = val.indicesOf(string: updVal)
|
|
354
|
+
if indices.count > 0 {
|
|
355
|
+
selValues.append(values[jdx])
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
let resp = try UtilsSQLCipher.prepareSQL(mDB: mDB, sql: stmt,
|
|
362
|
+
values: selValues,
|
|
363
|
+
fromJson: false, returnMode: "no")
|
|
364
|
+
lastId = resp.0
|
|
365
|
+
if lastId == -1 {
|
|
366
|
+
let msg = "UPDATE sql_deleted failed for " +
|
|
367
|
+
"table: \(tableName) "
|
|
368
|
+
throw UtilsDeleteError.executeUpdateForDelete(message: msg)
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// MARK: - getCurrentTimeAsInteger
|
|
374
|
+
|
|
375
|
+
class func getCurrentTimeAsInteger() -> Int {
|
|
376
|
+
let currentTime = Date().timeIntervalSince1970
|
|
377
|
+
print(">>>> in getCurrentTimeAsInteger currentTime: \(currentTime)")
|
|
378
|
+
return Int(currentTime)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// MARK: - checkValuesMatch
|
|
382
|
+
|
|
383
|
+
class func checkValuesMatch(_ array1: [String],
|
|
384
|
+
against array2: [String]) -> Bool {
|
|
385
|
+
for value in array1 {
|
|
386
|
+
if !array2.contains(value) {
|
|
387
|
+
return false
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return true
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// MARK: - getReferences
|
|
394
|
+
|
|
395
|
+
class func getReferences(mDB: Database, tableName: String)
|
|
396
|
+
throws -> (tableWithRefs: String, retRefs: [String]) {
|
|
397
|
+
// find the REFERENCES
|
|
398
|
+
var sqlStmt = "SELECT sql FROM sqlite_master "
|
|
399
|
+
sqlStmt += "WHERE sql LIKE('%FOREIGN KEY%') AND "
|
|
400
|
+
sqlStmt += "sql LIKE('%REFERENCES%') AND "
|
|
401
|
+
sqlStmt += "sql LIKE('%\(tableName)%') AND "
|
|
402
|
+
sqlStmt += "sql LIKE('%ON DELETE%');"
|
|
403
|
+
do {
|
|
404
|
+
var references: [[String: Any]] = try UtilsSQLCipher
|
|
405
|
+
.querySQL(mDB: mDB, sql: sqlStmt,values: [])
|
|
406
|
+
var retRefs = [String]()
|
|
407
|
+
var tableWithRefs: String = ""
|
|
408
|
+
if references.count > 1 {
|
|
409
|
+
references.removeFirst()
|
|
410
|
+
if let refValue = references[0]["sql"] as? String {
|
|
411
|
+
let result = try getRefs(sqlStatement: refValue)
|
|
412
|
+
retRefs = result.foreignKeys
|
|
413
|
+
tableWithRefs = result.tableName
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return (tableWithRefs, retRefs)
|
|
417
|
+
} catch UtilsDeleteError.getRefs(let message) {
|
|
418
|
+
throw UtilsDeleteError
|
|
419
|
+
.getReferences(message: message)
|
|
420
|
+
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
421
|
+
throw UtilsDeleteError
|
|
422
|
+
.getReferences(message: message)
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// MARK: - getRefs
|
|
427
|
+
|
|
428
|
+
class func getRefs(sqlStatement: String)
|
|
429
|
+
throws -> (tableName: String, foreignKeys: [String]) {
|
|
430
|
+
var tableName = ""
|
|
431
|
+
var foreignKeys = [String]()
|
|
432
|
+
let statement = UtilsSQLStatement
|
|
433
|
+
.flattenMultilineString(sqlStatement)
|
|
434
|
+
|
|
435
|
+
do {
|
|
436
|
+
// Regular expression pattern to match the table name
|
|
437
|
+
let tableNamePattern = #"CREATE\s+TABLE\s+(\w+)\s+\("#
|
|
438
|
+
let tableNameRegex = try NSRegularExpression(
|
|
439
|
+
pattern: tableNamePattern, options: [])
|
|
440
|
+
if let tableNameMatch = tableNameRegex
|
|
441
|
+
.firstMatch(in: statement, options: [],
|
|
442
|
+
range: NSRange(location: 0,
|
|
443
|
+
length: statement.utf16.count)) {
|
|
444
|
+
let tableNameRange = Range(tableNameMatch.range(
|
|
445
|
+
at: 1), in: statement)!
|
|
446
|
+
tableName = String(statement[tableNameRange])
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Regular expression pattern to match the FOREIGN KEY
|
|
450
|
+
// constraints
|
|
451
|
+
// swiftlint:disable line_length
|
|
452
|
+
let foreignKeyPattern = #"FOREIGN\s+KEY\s+\([^)]+\)\s+REFERENCES\s+(\w+)\s*\([^)]+\)\s+ON\s+DELETE\s+(CASCADE|RESTRICT|SET\s+DEFAULT|SET\s+NULL|NO\s+ACTION)"#
|
|
453
|
+
// swiftlint:enable line_length
|
|
454
|
+
|
|
455
|
+
let foreignKeyRegex = try NSRegularExpression(
|
|
456
|
+
pattern: foreignKeyPattern, options: [])
|
|
457
|
+
let foreignKeyMatches = foreignKeyRegex
|
|
458
|
+
.matches(in: statement, options: [],
|
|
459
|
+
range: NSRange(location: 0,
|
|
460
|
+
length: statement.utf16.count))
|
|
461
|
+
for foreignKeyMatch in foreignKeyMatches {
|
|
462
|
+
let foreignKeyRange = Range(
|
|
463
|
+
foreignKeyMatch.range(at: 0), in: statement)!
|
|
464
|
+
let foreignKey = String(statement[foreignKeyRange])
|
|
465
|
+
foreignKeys.append(foreignKey)
|
|
466
|
+
}
|
|
467
|
+
} catch {
|
|
468
|
+
let msg = "getRefs: Error creating regular expression: " +
|
|
469
|
+
"\(error)"
|
|
470
|
+
throw UtilsDeleteError.getRefs(message: msg)
|
|
471
|
+
}
|
|
472
|
+
return (tableName, foreignKeys)
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// MARK: - getUpdDelReturnedValues
|
|
476
|
+
|
|
477
|
+
class func getUpdDelReturnedValues(mDB: Database,
|
|
478
|
+
sqlStmt: String,
|
|
479
|
+
names: String )
|
|
480
|
+
throws -> [[String: Any]] {
|
|
481
|
+
var result: [[String: Any]] = []
|
|
482
|
+
let tableName = UtilsSQLStatement
|
|
483
|
+
.extractTableName(from: sqlStmt)
|
|
484
|
+
let whereClause = UtilsSQLStatement
|
|
485
|
+
.extractWhereClause(from: sqlStmt)
|
|
486
|
+
if let tblName = tableName {
|
|
487
|
+
if var wClause = whereClause {
|
|
488
|
+
if wClause.suffix(1) == ";" {
|
|
489
|
+
wClause = String(wClause.dropLast())
|
|
490
|
+
}
|
|
491
|
+
do {
|
|
492
|
+
var query: String = "SELECT \(names) FROM " +
|
|
493
|
+
"\(tblName) WHERE "
|
|
494
|
+
query += "\(wClause);"
|
|
495
|
+
result = try UtilsSQLCipher
|
|
496
|
+
.querySQL(mDB: mDB, sql: query, values: [])
|
|
497
|
+
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
498
|
+
throw UtilsDeleteError
|
|
499
|
+
.getUpdDelReturnedValues(message: message)
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return result
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
// swiftlint:enable type_body_length
|