@capacitor-community/sqlite 3.4.2-5 → 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 +46 -4
- 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 +102 -86
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/ImportFromJson.java +127 -38
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/UtilsJson.java +90 -0
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsUpgrade.java +8 -4
- package/dist/esm/definitions.d.ts +17 -1
- package/dist/esm/definitions.js +22 -28
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +20 -11
- package/dist/esm/web.js +288 -473
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +286 -477
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +1036 -1227
- package/dist/plugin.js.map +1 -1
- package/electron/dist/plugin.js +589 -744
- 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 +190 -32
- package/ios/Plugin/ImportExportJson/ImportFromJson.swift +73 -38
- package/ios/Plugin/Utils/UtilsDrop.swift +2 -2
- package/ios/Plugin/Utils/UtilsJson.swift +68 -1
- package/ios/Plugin/Utils/UtilsSQLCipher.swift +277 -29
- package/ios/Plugin/Utils/UtilsUpgrade.swift +33 -13
- package/package.json +6 -6
|
@@ -959,7 +959,13 @@ enum CapacitorSQLiteError: Error {
|
|
|
959
959
|
do {
|
|
960
960
|
let res: [String: Any] = try
|
|
961
961
|
mDb.exportToJson(expMode: expMode)
|
|
962
|
-
if res.count ==
|
|
962
|
+
if res.count == 0 {
|
|
963
|
+
var msg: String = "return Object is empty "
|
|
964
|
+
msg.append("No data to synchronize")
|
|
965
|
+
throw CapacitorSQLiteError.failed(message: msg)
|
|
966
|
+
|
|
967
|
+
} else if res.count == 5 || res.count == 6 ||
|
|
968
|
+
res.count == 7 {
|
|
963
969
|
return res
|
|
964
970
|
} else {
|
|
965
971
|
var msg: String = "return Object is not a "
|
|
@@ -981,6 +987,33 @@ enum CapacitorSQLiteError: Error {
|
|
|
981
987
|
}
|
|
982
988
|
}
|
|
983
989
|
|
|
990
|
+
// MARK: - deleteExportedRows
|
|
991
|
+
|
|
992
|
+
@objc func deleteExportedRows(_ dbName: String) throws {
|
|
993
|
+
if isInit {
|
|
994
|
+
let mDbName = CapacitorSQLite.getDatabaseName(dbName: dbName)
|
|
995
|
+
guard let mDb: Database = dbDict[mDbName] else {
|
|
996
|
+
let msg = "Connection to \(mDbName) not available"
|
|
997
|
+
throw CapacitorSQLiteError.failed(message: msg)
|
|
998
|
+
}
|
|
999
|
+
if mDb.isDBOpen() {
|
|
1000
|
+
do {
|
|
1001
|
+
try mDb.deleteExportedRows()
|
|
1002
|
+
} catch DatabaseError.deleteExportedRows(let message) {
|
|
1003
|
+
throw CapacitorSQLiteError.failed(message: message)
|
|
1004
|
+
} catch let error {
|
|
1005
|
+
let msg: String = "\(error)"
|
|
1006
|
+
throw CapacitorSQLiteError.failed(message: msg)
|
|
1007
|
+
}
|
|
1008
|
+
} else {
|
|
1009
|
+
let msg = "Database \(mDbName) not opened"
|
|
1010
|
+
throw CapacitorSQLiteError.failed(message: msg)
|
|
1011
|
+
}
|
|
1012
|
+
} else {
|
|
1013
|
+
throw CapacitorSQLiteError.failed(message: initMessage)
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
984
1017
|
// MARK: - createSyncTable
|
|
985
1018
|
|
|
986
1019
|
@objc func createSyncTable(_ dbName: String) throws -> NSNumber {
|
|
@@ -24,6 +24,7 @@ CAP_PLUGIN(CapacitorSQLitePlugin, "CapacitorSQLite",
|
|
|
24
24
|
CAP_PLUGIN_METHOD(importFromJson, CAPPluginReturnPromise);
|
|
25
25
|
CAP_PLUGIN_METHOD(isJsonValid, CAPPluginReturnPromise);
|
|
26
26
|
CAP_PLUGIN_METHOD(exportToJson, CAPPluginReturnPromise);
|
|
27
|
+
CAP_PLUGIN_METHOD(deleteExportedRows, CAPPluginReturnPromise);
|
|
27
28
|
CAP_PLUGIN_METHOD(createSyncTable, CAPPluginReturnPromise);
|
|
28
29
|
CAP_PLUGIN_METHOD(setSyncDate, CAPPluginReturnPromise);
|
|
29
30
|
CAP_PLUGIN_METHOD(getSyncDate, CAPPluginReturnPromise);
|
|
@@ -937,6 +937,31 @@ public class CapacitorSQLitePlugin: CAPPlugin {
|
|
|
937
937
|
|
|
938
938
|
}
|
|
939
939
|
|
|
940
|
+
// MARK: - DeleteExportedRows
|
|
941
|
+
|
|
942
|
+
@objc func deleteExportedRows(_ call: CAPPluginCall) {
|
|
943
|
+
guard let dbName = call.options["database"]
|
|
944
|
+
as? String else {
|
|
945
|
+
let msg = "DeleteExportedRows: Must provide a database name"
|
|
946
|
+
retHandler.rResult(call: call, message: msg)
|
|
947
|
+
return
|
|
948
|
+
}
|
|
949
|
+
do {
|
|
950
|
+
try implementation?.deleteExportedRows(dbName)
|
|
951
|
+
retHandler.rResult(call: call)
|
|
952
|
+
return
|
|
953
|
+
} catch CapacitorSQLiteError.failed(let message) {
|
|
954
|
+
let msg = "exportToJson: \(message)"
|
|
955
|
+
retHandler.rResult(call: call, message: msg)
|
|
956
|
+
return
|
|
957
|
+
} catch let error {
|
|
958
|
+
let msg = "exportToJson: \(error)"
|
|
959
|
+
retHandler.rResult(call: call, message: msg)
|
|
960
|
+
return
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
}
|
|
964
|
+
|
|
940
965
|
// MARK: - CreateSyncTable
|
|
941
966
|
|
|
942
967
|
@objc func createSyncTable(_ call: CAPPluginCall) {
|
|
@@ -24,6 +24,7 @@ enum DatabaseError: Error {
|
|
|
24
24
|
case exportToJson(message: String)
|
|
25
25
|
case importFromJson(message: String)
|
|
26
26
|
case getTableNames(message: String)
|
|
27
|
+
case deleteExportedRows(message: String)
|
|
27
28
|
}
|
|
28
29
|
// swiftlint:disable file_length
|
|
29
30
|
// swiftlint:disable type_body_length
|
|
@@ -360,7 +361,8 @@ class Database {
|
|
|
360
361
|
// Execute the query
|
|
361
362
|
do {
|
|
362
363
|
lastId = try UtilsSQLCipher
|
|
363
|
-
.prepareSQL(mDB: self, sql: sql, values: values
|
|
364
|
+
.prepareSQL(mDB: self, sql: sql, values: values,
|
|
365
|
+
fromJson: false)
|
|
364
366
|
} catch UtilsSQLCipherError.prepareSQL(let message) {
|
|
365
367
|
if transaction {
|
|
366
368
|
do {
|
|
@@ -551,17 +553,35 @@ class Database {
|
|
|
551
553
|
var retObj: [String: Any] = [:]
|
|
552
554
|
|
|
553
555
|
do {
|
|
556
|
+
let date = Date()
|
|
557
|
+
let syncTime: Int = Int(date.timeIntervalSince1970)
|
|
558
|
+
// Set the last exported date
|
|
559
|
+
try ExportToJson.setLastExportDate(mDB: self, sTime: syncTime)
|
|
560
|
+
// Launch the export process
|
|
554
561
|
let data: [String: Any] = [
|
|
555
562
|
"dbName": dbName, "encrypted": self.encrypted,
|
|
556
563
|
"expMode": expMode, "version": dbVersion]
|
|
557
564
|
retObj = try ExportToJson
|
|
558
565
|
.createExportObject(mDB: self, data: data)
|
|
566
|
+
} catch ExportToJsonError.setLastExportDate(let message) {
|
|
567
|
+
throw DatabaseError.exportToJson(message: message)
|
|
559
568
|
} catch ExportToJsonError.createExportObject(let message) {
|
|
560
569
|
throw DatabaseError.exportToJson(message: message)
|
|
561
570
|
}
|
|
562
571
|
return retObj
|
|
563
572
|
}
|
|
564
573
|
|
|
574
|
+
// MARK: - DeleteExportedRows()
|
|
575
|
+
|
|
576
|
+
func deleteExportedRows() throws {
|
|
577
|
+
|
|
578
|
+
do {
|
|
579
|
+
try ExportToJson.delExportedRows(mDB: self)
|
|
580
|
+
} catch ExportToJsonError.delExportedRows(let message) {
|
|
581
|
+
throw DatabaseError.exportToJson(message: message)
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
565
585
|
// MARK: - ImportFromJson
|
|
566
586
|
|
|
567
587
|
func importFromJson(jsonSQLite: JsonSQLite)
|
|
@@ -570,6 +590,10 @@ class Database {
|
|
|
570
590
|
|
|
571
591
|
// Create the Database Schema
|
|
572
592
|
do {
|
|
593
|
+
// PRAGMA foreign_keys = OFF;
|
|
594
|
+
try UtilsSQLCipher
|
|
595
|
+
.setForeignKeyConstraintsEnabled(mDB: self,
|
|
596
|
+
toggle: false)
|
|
573
597
|
if jsonSQLite.tables.count > 0 {
|
|
574
598
|
changes = try ImportFromJson
|
|
575
599
|
.createDatabaseSchema(mDB: self,
|
|
@@ -587,6 +611,10 @@ class Database {
|
|
|
587
611
|
.createViews(mDB: self, views: mViews)
|
|
588
612
|
}
|
|
589
613
|
}
|
|
614
|
+
// PRAGMA foreign_keys = ON;
|
|
615
|
+
try UtilsSQLCipher
|
|
616
|
+
.setForeignKeyConstraintsEnabled(mDB: self,
|
|
617
|
+
toggle: true)
|
|
590
618
|
|
|
591
619
|
return ["changes": changes]
|
|
592
620
|
} catch ImportFromJsonError.createDatabaseSchema(let message) {
|
|
@@ -27,4 +27,12 @@ extension String {
|
|
|
27
27
|
let stopIndex = self.index(self.startIndex, offsetBy: toIdx)
|
|
28
28
|
return self[startIndex..<stopIndex]
|
|
29
29
|
}
|
|
30
|
+
public func deletingPrefix(_ prefix: String) -> String {
|
|
31
|
+
guard self.hasPrefix(prefix) else { return self }
|
|
32
|
+
return String(self.dropFirst(prefix.count))
|
|
33
|
+
}
|
|
34
|
+
public func trimmingLeadingAndTrailingSpaces(using characterSet: CharacterSet = .whitespacesAndNewlines) -> String {
|
|
35
|
+
return trimmingCharacters(in: characterSet)
|
|
36
|
+
}
|
|
37
|
+
|
|
30
38
|
}
|
|
@@ -27,10 +27,21 @@ enum ExportToJsonError: Error {
|
|
|
27
27
|
case createRowValues(message: String)
|
|
28
28
|
case modEmbeddedParentheses(message: String)
|
|
29
29
|
case getViews(message: String)
|
|
30
|
-
|
|
30
|
+
case setLastExportDate(message: String)
|
|
31
|
+
case getLastExportDate(message: String)
|
|
32
|
+
case delExportedRows(message: String)
|
|
31
33
|
|
|
34
|
+
}
|
|
35
|
+
var REALAFFINITY: [String] = ["REAL", "DOUBLE", "DOUBLE PRECISION", "FLOAT"]
|
|
36
|
+
var INTEGERAFFINITY: [String] = ["INTEGER", "INT", "TINYINT", "SMALLINT",
|
|
37
|
+
"MEDIUMINT", "BIGINT", "UNSIGNED BIG INT",
|
|
38
|
+
"INT2", "INT8"]
|
|
39
|
+
var TEXTAFFINITY: [String] = ["TEXT", "CHARACTER", "VARCHAR", "VARYING CHARACTER",
|
|
40
|
+
"NCHAR", "NATIVE CHARACTER", "NVARCHAR", "CLOB"]
|
|
41
|
+
var BLOBAFFINITY: [String] = ["BLOB"]
|
|
42
|
+
var NUMERICAFFINITY: [String] = ["NUMERIC", "DECIMAL", "BOOLEAN", "DATE",
|
|
43
|
+
"DATETIME"]
|
|
32
44
|
class ExportToJson {
|
|
33
|
-
|
|
34
45
|
// MARK: - JsonNotifications - NotifyExportProgressEvent
|
|
35
46
|
|
|
36
47
|
class func notifyExportProgressEvent(msg: String) {
|
|
@@ -40,6 +51,124 @@ class ExportToJson {
|
|
|
40
51
|
userInfo: vId)
|
|
41
52
|
}
|
|
42
53
|
|
|
54
|
+
// MARK: - ExportToJson - GetLastExportDate
|
|
55
|
+
|
|
56
|
+
class func getLastExportDate(mDB: Database) throws -> Int64 {
|
|
57
|
+
var ret: Int64 = -1
|
|
58
|
+
let query: String = "SELECT sync_date FROM sync_table WHERE id = 2;"
|
|
59
|
+
do {
|
|
60
|
+
let isExists: Bool = try UtilsJson.isTableExists(
|
|
61
|
+
mDB: mDB, tableName: "sync_table")
|
|
62
|
+
if isExists {
|
|
63
|
+
var resSyncDate = try UtilsSQLCipher.querySQL(
|
|
64
|
+
mDB: mDB, sql: query, values: [])
|
|
65
|
+
if resSyncDate.count > 1 {
|
|
66
|
+
resSyncDate.removeFirst()
|
|
67
|
+
guard let res: Int64 = resSyncDate[0]["sync_date"] as?
|
|
68
|
+
Int64 else {
|
|
69
|
+
throw ExportToJsonError.getLastExportDate(
|
|
70
|
+
message: "Error get sync date failed")
|
|
71
|
+
}
|
|
72
|
+
if res > 0 {ret = res}
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
let msg = "No sync_table available"
|
|
76
|
+
throw ExportToJsonError.getLastExportDate(message: msg)
|
|
77
|
+
}
|
|
78
|
+
} catch UtilsJsonError.tableNotExists(let message) {
|
|
79
|
+
throw ExportToJsonError.getLastExportDate(message: message)
|
|
80
|
+
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
81
|
+
throw ExportToJsonError.getLastExportDate(
|
|
82
|
+
message: "Error get last export date failed : \(message)")
|
|
83
|
+
}
|
|
84
|
+
return ret
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// MARK: - ExportToJson - SetLastExportDate
|
|
89
|
+
|
|
90
|
+
class func setLastExportDate(mDB: Database, sTime: Int) throws {
|
|
91
|
+
do {
|
|
92
|
+
let isExists: Bool = try UtilsJson.isTableExists(
|
|
93
|
+
mDB: mDB, tableName: "sync_table")
|
|
94
|
+
if !isExists {
|
|
95
|
+
let msg = "No sync_table available"
|
|
96
|
+
throw ExportToJsonError.setLastExportDate(message: msg)
|
|
97
|
+
}
|
|
98
|
+
var stmt: String = ""
|
|
99
|
+
let res = try getLastExportDate(mDB: mDB)
|
|
100
|
+
if res > 0 {
|
|
101
|
+
stmt = "UPDATE sync_table SET sync_date = \(sTime) " +
|
|
102
|
+
"WHERE id = 2;"
|
|
103
|
+
} else {
|
|
104
|
+
stmt = "INSERT INTO sync_table (sync_date) VALUES (\(sTime));"
|
|
105
|
+
}
|
|
106
|
+
let lastId: Int64 = try UtilsSQLCipher.prepareSQL(
|
|
107
|
+
mDB: mDB, sql: stmt, values: [], fromJson: false)
|
|
108
|
+
if lastId < 0 {
|
|
109
|
+
throw ExportToJsonError.setLastExportDate(
|
|
110
|
+
message: "lastId < 0")
|
|
111
|
+
}
|
|
112
|
+
return
|
|
113
|
+
} catch UtilsSQLCipherError.prepareSQL(let message) { throw ExportToJsonError.setLastExportDate(message: message)
|
|
114
|
+
} catch UtilsJsonError.tableNotExists(let message) {
|
|
115
|
+
throw ExportToJsonError.setLastExportDate(message: message)
|
|
116
|
+
} catch ExportToJsonError.getLastExportDate(let message) {
|
|
117
|
+
throw ExportToJsonError.setLastExportDate(message: message)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// MARK: - ExportToJson - DelExportedRows
|
|
123
|
+
|
|
124
|
+
class func delExportedRows(mDB: Database) throws {
|
|
125
|
+
do {
|
|
126
|
+
// check if synchronization table exists
|
|
127
|
+
let isExists: Bool = try UtilsJson.isTableExists(
|
|
128
|
+
mDB: mDB, tableName: "sync_table")
|
|
129
|
+
if !isExists {
|
|
130
|
+
let msg = "No sync_table available"
|
|
131
|
+
throw ExportToJsonError.delExportedRows(message: msg)
|
|
132
|
+
}
|
|
133
|
+
// get the last export date
|
|
134
|
+
let lastExportDate = try getLastExportDate(mDB: mDB)
|
|
135
|
+
if lastExportDate < 0 {
|
|
136
|
+
let msg = "No last exported date available"
|
|
137
|
+
throw ExportToJsonError.delExportedRows(message: msg)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// get the table' name list
|
|
141
|
+
let tableList: [String] = try mDB.getTableNames()
|
|
142
|
+
if tableList.count == 0 {
|
|
143
|
+
let msg = "No table's names returned"
|
|
144
|
+
throw ExportToJsonError.delExportedRows(message: msg)
|
|
145
|
+
}
|
|
146
|
+
// Loop through the tables
|
|
147
|
+
for table in tableList {
|
|
148
|
+
var lastId: Int64 = -1
|
|
149
|
+
// define the delete statement
|
|
150
|
+
let delStmt = "DELETE FROM \(table) WHERE sql_deleted = 1 " +
|
|
151
|
+
"AND last_modified < \(lastExportDate);"
|
|
152
|
+
lastId = try UtilsSQLCipher.prepareSQL(mDB: mDB, sql: delStmt,
|
|
153
|
+
values: [],
|
|
154
|
+
fromJson: true)
|
|
155
|
+
if lastId < 0 {
|
|
156
|
+
let msg = "DelExportedRows: lastId < 0"
|
|
157
|
+
throw ExportToJsonError.delExportedRows(message: msg)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return
|
|
161
|
+
} catch UtilsJsonError.tableNotExists(let message) {
|
|
162
|
+
throw ExportToJsonError.delExportedRows(message: message)
|
|
163
|
+
} catch ExportToJsonError.getLastExportDate(let message) {
|
|
164
|
+
throw ExportToJsonError.delExportedRows(message: message)
|
|
165
|
+
} catch DatabaseError.getTableNames(let message) {
|
|
166
|
+
throw ExportToJsonError.delExportedRows(message: message)
|
|
167
|
+
} catch UtilsSQLCipherError.prepareSQL(let message) {
|
|
168
|
+
throw ExportToJsonError.delExportedRows(message: message)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
43
172
|
// MARK: - ExportToJson - CreateExportObject
|
|
44
173
|
|
|
45
174
|
// swiftlint:disable function_body_length
|
|
@@ -427,17 +556,17 @@ class ExportToJson {
|
|
|
427
556
|
table: table)
|
|
428
557
|
guard let isSch: Bool = result["isSchema"] as? Bool
|
|
429
558
|
else {
|
|
430
|
-
throw ExportToJsonError.
|
|
559
|
+
throw ExportToJsonError.getTablesPartial(
|
|
431
560
|
message: "Error did not find isSchema")
|
|
432
561
|
}
|
|
433
562
|
guard let isIdxes: Bool = result["isIndexes"] as?
|
|
434
563
|
Bool else {
|
|
435
|
-
throw ExportToJsonError.
|
|
564
|
+
throw ExportToJsonError.getTablesPartial(
|
|
436
565
|
message: "Error did not find isIndexes")
|
|
437
566
|
}
|
|
438
567
|
guard let retTable: [String: Any] = result["table"]
|
|
439
568
|
as? [String: Any] else {
|
|
440
|
-
throw ExportToJsonError.
|
|
569
|
+
throw ExportToJsonError.getTablesPartial(
|
|
441
570
|
message: "Error did not find table")
|
|
442
571
|
}
|
|
443
572
|
isSchema = isSch
|
|
@@ -452,18 +581,18 @@ class ExportToJson {
|
|
|
452
581
|
let query: String = modTables[tableName] == "Create"
|
|
453
582
|
? "SELECT * FROM \(tableName);"
|
|
454
583
|
: "SELECT * FROM \(tableName) WHERE last_modified" +
|
|
455
|
-
"
|
|
584
|
+
" >= \(syncDate);"
|
|
456
585
|
result = try ExportToJson
|
|
457
586
|
.getValues(mDB: mDB, stmt: query,
|
|
458
587
|
table: table)
|
|
459
588
|
guard let isValues: Bool = result["isValues"] as? Bool
|
|
460
589
|
else {
|
|
461
|
-
throw ExportToJsonError.
|
|
590
|
+
throw ExportToJsonError.getTablesPartial(
|
|
462
591
|
message: "Error did not find isValues")
|
|
463
592
|
}
|
|
464
593
|
guard let retTable1: [String: Any] = result["table"]
|
|
465
594
|
as? [String: Any] else {
|
|
466
|
-
throw ExportToJsonError.
|
|
595
|
+
throw ExportToJsonError.getTablesPartial(
|
|
467
596
|
message: "Error did not find table")
|
|
468
597
|
}
|
|
469
598
|
table = retTable1
|
|
@@ -471,15 +600,13 @@ class ExportToJson {
|
|
|
471
600
|
var tableKeys: [String] = []
|
|
472
601
|
tableKeys.append(contentsOf: table.keys)
|
|
473
602
|
|
|
474
|
-
if tableKeys.count
|
|
475
|
-
(
|
|
476
|
-
|
|
477
|
-
|
|
603
|
+
if tableKeys.count >= 1 &&
|
|
604
|
+
(isSchema || isIndexes || isValues) {
|
|
605
|
+
tables.append(table)
|
|
606
|
+
msg = "Partial: Table \(tableName) data export completed " +
|
|
607
|
+
"\(iTable)/\(resTables.count) ..."
|
|
608
|
+
notifyExportProgressEvent(msg: msg)
|
|
478
609
|
}
|
|
479
|
-
tables.append(table)
|
|
480
|
-
msg = "Partial: Table \(tableName) data export completed " +
|
|
481
|
-
"\(iTable)/\(resTables.count) ..."
|
|
482
|
-
notifyExportProgressEvent(msg: msg)
|
|
483
610
|
|
|
484
611
|
}
|
|
485
612
|
} catch ExportToJsonError.getSchemaIndexes(let message) {
|
|
@@ -528,19 +655,28 @@ class ExportToJson {
|
|
|
528
655
|
|
|
529
656
|
class func getSyncDate(mDB: Database) throws -> Int64 {
|
|
530
657
|
var ret: Int64 = -1
|
|
531
|
-
let query: String = "SELECT sync_date FROM sync_table;"
|
|
658
|
+
let query: String = "SELECT sync_date FROM sync_table WHERE id = 1;"
|
|
532
659
|
do {
|
|
533
|
-
|
|
534
|
-
mDB: mDB,
|
|
535
|
-
if
|
|
536
|
-
resSyncDate.
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
660
|
+
let isExists: Bool = try UtilsJson.isTableExists(
|
|
661
|
+
mDB: mDB, tableName: "sync_table")
|
|
662
|
+
if isExists {
|
|
663
|
+
var resSyncDate = try UtilsSQLCipher.querySQL(
|
|
664
|
+
mDB: mDB, sql: query, values: [])
|
|
665
|
+
if resSyncDate.count > 1 {
|
|
666
|
+
resSyncDate.removeFirst()
|
|
667
|
+
guard let res: Int64 = resSyncDate[0]["sync_date"] as?
|
|
668
|
+
Int64 else {
|
|
669
|
+
throw ExportToJsonError.getSyncDate(
|
|
670
|
+
message: "Error get sync date failed")
|
|
671
|
+
}
|
|
672
|
+
if res > 0 {ret = res}
|
|
541
673
|
}
|
|
542
|
-
|
|
674
|
+
} else {
|
|
675
|
+
throw ExportToJsonError.getSyncDate(
|
|
676
|
+
message: "Error no sync_table available")
|
|
543
677
|
}
|
|
678
|
+
} catch UtilsJsonError.tableNotExists(let message) {
|
|
679
|
+
throw ExportToJsonError.getSyncDate(message: message)
|
|
544
680
|
} catch UtilsSQLCipherError.querySQL(let message) {
|
|
545
681
|
throw ExportToJsonError.getSyncDate(
|
|
546
682
|
message: "Error get sync date failed : \(message)")
|
|
@@ -588,7 +724,7 @@ class ExportToJson {
|
|
|
588
724
|
.getTablesModified(message: msg)
|
|
589
725
|
}
|
|
590
726
|
query = "SELECT count(*) AS count FROM \(tableName) "
|
|
591
|
-
query.append("WHERE last_modified
|
|
727
|
+
query.append("WHERE last_modified >= ")
|
|
592
728
|
query.append("\(syncDate);")
|
|
593
729
|
resQuery = try UtilsSQLCipher.querySQL(
|
|
594
730
|
mDB: mDB, sql: query, values: [])
|
|
@@ -996,14 +1132,19 @@ class ExportToJson {
|
|
|
996
1132
|
|
|
997
1133
|
// MARK: - ExportToJson - CreateRowValues
|
|
998
1134
|
|
|
1135
|
+
// swiftlint:disable function_body_length
|
|
1136
|
+
// swiftlint:disable cyclomatic_complexity
|
|
999
1137
|
class func createRowValues(values: [[String: Any]], pos: Int,
|
|
1000
1138
|
names: [String],
|
|
1001
1139
|
types: [String] ) throws -> [Any] {
|
|
1002
1140
|
var row: [Any] = []
|
|
1003
1141
|
for jpos in 0..<names.count {
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1142
|
+
if values[pos][names[jpos]] is String && (TEXTAFFINITY
|
|
1143
|
+
.contains(types[jpos].components(separatedBy: "(")[0]
|
|
1144
|
+
.uppercased())
|
|
1145
|
+
|| BLOBAFFINITY.contains(types[jpos].uppercased())
|
|
1146
|
+
|| NUMERICAFFINITY.contains(types[jpos].uppercased())
|
|
1147
|
+
) {
|
|
1007
1148
|
guard let val = values[pos][names[jpos]] as? String
|
|
1008
1149
|
else {
|
|
1009
1150
|
throw ExportToJsonError.createValues(
|
|
@@ -1017,14 +1158,29 @@ class ExportToJson {
|
|
|
1017
1158
|
message: "Error value must be NSNull")
|
|
1018
1159
|
}
|
|
1019
1160
|
row.append(val)
|
|
1020
|
-
} else if values[pos][names[jpos]] is Int64
|
|
1161
|
+
} else if values[pos][names[jpos]] is Int64 && (
|
|
1162
|
+
INTEGERAFFINITY.contains(types[jpos].uppercased()) ||
|
|
1163
|
+
NUMERICAFFINITY.contains(types[jpos].uppercased())) {
|
|
1021
1164
|
guard let val = values[pos][names[jpos]] as? Int64
|
|
1022
1165
|
else {
|
|
1023
1166
|
throw ExportToJsonError.createValues(
|
|
1024
1167
|
message: "Error value must be Int64")
|
|
1025
1168
|
}
|
|
1026
1169
|
row.append(val)
|
|
1027
|
-
} else if values[pos][names[jpos]] is
|
|
1170
|
+
} else if values[pos][names[jpos]] is Int64 && (
|
|
1171
|
+
REALAFFINITY.contains(types[jpos].uppercased()) ||
|
|
1172
|
+
NUMERICAFFINITY.contains(types[jpos]
|
|
1173
|
+
.components(separatedBy: "(")[0].uppercased())) {
|
|
1174
|
+
guard let val = values[pos][names[jpos]] as? Int64
|
|
1175
|
+
else {
|
|
1176
|
+
throw ExportToJsonError.createValues(
|
|
1177
|
+
message: "Error value must be double")
|
|
1178
|
+
}
|
|
1179
|
+
row.append(Double(val))
|
|
1180
|
+
} else if values[pos][names[jpos]] is Double && (
|
|
1181
|
+
REALAFFINITY.contains(types[jpos].uppercased()) ||
|
|
1182
|
+
NUMERICAFFINITY.contains(types[jpos]
|
|
1183
|
+
.components(separatedBy: "(")[0].uppercased())) {
|
|
1028
1184
|
guard let val = values[pos][names[jpos]] as? Double
|
|
1029
1185
|
else {
|
|
1030
1186
|
throw ExportToJsonError.createValues(
|
|
@@ -1040,6 +1196,8 @@ class ExportToJson {
|
|
|
1040
1196
|
}
|
|
1041
1197
|
return row
|
|
1042
1198
|
}
|
|
1199
|
+
// swiftlint:enable cyclomatic_complexity
|
|
1200
|
+
// swiftlint:enable function_body_length
|
|
1043
1201
|
|
|
1044
1202
|
}
|
|
1045
1203
|
// swiftlint:enable type_body_length
|
|
@@ -46,15 +46,9 @@ class ImportFromJson {
|
|
|
46
46
|
try UtilsSQLCipher.setVersion(mDB: mDB,
|
|
47
47
|
version: version)
|
|
48
48
|
if jsonSQLite.mode == "full" {
|
|
49
|
-
try UtilsSQLCipher
|
|
50
|
-
.setForeignKeyConstraintsEnabled(mDB: mDB,
|
|
51
|
-
toggle: false)
|
|
52
49
|
// Drop All Tables, Indexes and Triggers
|
|
53
50
|
try _ = UtilsDrop.dropAll(mDB: mDB)
|
|
54
51
|
}
|
|
55
|
-
try UtilsSQLCipher
|
|
56
|
-
.setForeignKeyConstraintsEnabled(mDB: mDB,
|
|
57
|
-
toggle: true)
|
|
58
52
|
// create database schema
|
|
59
53
|
changes = try ImportFromJson
|
|
60
54
|
.createSchema(mDB: mDB,
|
|
@@ -236,7 +230,7 @@ class ImportFromJson {
|
|
|
236
230
|
stmt.append(" AFTER UPDATE ON ")
|
|
237
231
|
stmt.append(tableName)
|
|
238
232
|
stmt.append(" FOR EACH ROW ")
|
|
239
|
-
stmt.append("WHEN NEW.last_modified
|
|
233
|
+
stmt.append("WHEN NEW.last_modified < OLD.last_modified ")
|
|
240
234
|
stmt.append("BEGIN UPDATE ")
|
|
241
235
|
stmt.append(tableName)
|
|
242
236
|
stmt.append(" SET last_modified = (strftime('%s','now')) ")
|
|
@@ -409,6 +403,8 @@ class ImportFromJson {
|
|
|
409
403
|
// Check row validity
|
|
410
404
|
let row: [UncertainValue<String, Int, Double>] =
|
|
411
405
|
mValues[jpos]
|
|
406
|
+
var isRun: Bool = true
|
|
407
|
+
|
|
412
408
|
/* Remove types checking for allowing RDBMS Types
|
|
413
409
|
do {
|
|
414
410
|
try UtilsJson.checkRowValidity(
|
|
@@ -427,21 +423,31 @@ class ImportFromJson {
|
|
|
427
423
|
.createRowStatement(mDB: mDB, data: data,
|
|
428
424
|
row: row,
|
|
429
425
|
jsonNamesTypes: jsonNamesTypes)
|
|
430
|
-
|
|
426
|
+
var rowValues = UtilsJson.getValuesFromRow(
|
|
431
427
|
rowValues: row)
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
428
|
+
isRun = try UtilsJson.checkUpdate(mDB: mDB, stmt: stmt,
|
|
429
|
+
values: rowValues,
|
|
430
|
+
tableName: tableName,
|
|
431
|
+
names: jsonNamesTypes.names,
|
|
432
|
+
types: jsonNamesTypes.types)
|
|
433
|
+
|
|
434
|
+
if isRun {
|
|
435
|
+
if stmt.prefix(6) == "DELETE" {
|
|
436
|
+
rowValues = []
|
|
437
|
+
}
|
|
438
|
+
let lastId: Int64 = try UtilsSQLCipher.prepareSQL(
|
|
439
|
+
mDB: mDB, sql: stmt, values: rowValues, fromJson: true)
|
|
440
|
+
if lastId < 0 {
|
|
441
|
+
throw ImportFromJsonError.createTableData(
|
|
442
|
+
message: "lastId < 0")
|
|
443
|
+
}
|
|
437
444
|
}
|
|
438
|
-
} catch
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
445
|
+
} catch UtilsJsonError.checkUpdate(let message) {
|
|
446
|
+
throw ImportFromJsonError.createTableData(message: message)
|
|
447
|
+
} catch ImportFromJsonError.createRowStatement(let message) {
|
|
448
|
+
throw ImportFromJsonError.createTableData(message: message)
|
|
442
449
|
} catch UtilsSQLCipherError.prepareSQL(let message) {
|
|
443
|
-
throw ImportFromJsonError.createTableData(
|
|
444
|
-
message: message)
|
|
450
|
+
throw ImportFromJsonError.createTableData(message: message)
|
|
445
451
|
}
|
|
446
452
|
}
|
|
447
453
|
return
|
|
@@ -451,6 +457,7 @@ class ImportFromJson {
|
|
|
451
457
|
// MARK: - ImportFromJson - createRowStatement
|
|
452
458
|
|
|
453
459
|
// swiftlint:disable function_body_length
|
|
460
|
+
// swiftlint:disable cyclomatic_complexity
|
|
454
461
|
class func createRowStatement(
|
|
455
462
|
mDB: Database,
|
|
456
463
|
data: [String: Any],
|
|
@@ -499,31 +506,59 @@ class ImportFromJson {
|
|
|
499
506
|
stmt = "INSERT INTO \(tableName) (\(nameString)) VALUES "
|
|
500
507
|
stmt.append("(\(questionMarkString));")
|
|
501
508
|
} else {
|
|
502
|
-
|
|
503
|
-
let
|
|
504
|
-
names:
|
|
505
|
-
if
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
509
|
+
var isUpdate: Bool = true
|
|
510
|
+
let idxDelete: Int = jsonNamesTypes
|
|
511
|
+
.names.firstIndex(where: {$0 == "sql_deleted"}) ?? -1
|
|
512
|
+
if idxDelete >= 0 {
|
|
513
|
+
if let delValue = row[idxDelete].value as? Int {
|
|
514
|
+
if delValue == 1 {
|
|
515
|
+
isUpdate = false
|
|
516
|
+
stmt = "DELETE FROM \(tableName) WHERE "
|
|
517
|
+
if let rwValue = row[0].value as? String {
|
|
518
|
+
stmt += "\(jsonNamesTypes.names[0]) = '\(rwValue)';"
|
|
519
|
+
} else if let rwValue = row[0].value as? Int {
|
|
520
|
+
stmt += "\(jsonNamesTypes.names[0]) = \(rwValue);"
|
|
521
|
+
} else {
|
|
522
|
+
var msg: String = "importFromJson: Table "
|
|
523
|
+
msg.append("\(tableName) values row[0]does not exist")
|
|
524
|
+
throw ImportFromJsonError.createRowStatement(
|
|
525
|
+
message: message)
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
511
529
|
}
|
|
530
|
+
if isUpdate {
|
|
531
|
+
// Update
|
|
532
|
+
let setString: String = UtilsJson.setNameForUpdate(
|
|
533
|
+
names: jsonNamesTypes.names)
|
|
534
|
+
if setString.count == 0 {
|
|
535
|
+
var message: String = "importFromJson: Table "
|
|
536
|
+
message.append("\(tableName) values row ")
|
|
537
|
+
message.append("\(pos) not set to String")
|
|
538
|
+
throw ImportFromJsonError.createRowStatement(
|
|
539
|
+
message: message)
|
|
540
|
+
}
|
|
512
541
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
542
|
+
stmt = "UPDATE \(tableName) SET \(setString) WHERE "
|
|
543
|
+
if let rwValue = row[0].value as? String {
|
|
544
|
+
stmt += "\(jsonNamesTypes.names[0]) = '\(rwValue)';"
|
|
545
|
+
} else if let rwValue = row[0].value as? Int {
|
|
546
|
+
stmt += "\(jsonNamesTypes.names[0]) = \(rwValue);"
|
|
547
|
+
} else {
|
|
548
|
+
var msg: String = "importFromJson: Table "
|
|
549
|
+
msg.append("\(tableName) values row[0]does not exist")
|
|
550
|
+
throw ImportFromJsonError.createRowStatement(
|
|
551
|
+
message: message)
|
|
552
|
+
}
|
|
523
553
|
}
|
|
524
554
|
}
|
|
525
555
|
return stmt
|
|
526
556
|
}
|
|
557
|
+
// swiftlint:enable cyclomatic_complexity
|
|
558
|
+
// swiftlint:enable function_body_length
|
|
559
|
+
|
|
560
|
+
// MARK: - ImportFromJson - createViews
|
|
561
|
+
|
|
527
562
|
// swiftlint:disable function_body_length
|
|
528
563
|
class func createViews(mDB: Database, views: [JsonView]) throws -> Int {
|
|
529
564
|
var changes: Int = 0
|