@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.
Files changed (33) hide show
  1. package/README.md +46 -4
  2. package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLite.java +41 -2
  3. package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLitePlugin.java +26 -0
  4. package/android/src/main/java/com/getcapacitor/community/database/sqlite/NotificationCenter.java +1 -1
  5. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/Database.java +220 -7
  6. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/ExportToJson.java +102 -86
  7. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/ImportFromJson.java +127 -38
  8. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/UtilsJson.java +90 -0
  9. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsUpgrade.java +8 -4
  10. package/dist/esm/definitions.d.ts +17 -1
  11. package/dist/esm/definitions.js +22 -28
  12. package/dist/esm/definitions.js.map +1 -1
  13. package/dist/esm/web.d.ts +20 -11
  14. package/dist/esm/web.js +288 -473
  15. package/dist/esm/web.js.map +1 -1
  16. package/dist/plugin.cjs.js +286 -477
  17. package/dist/plugin.cjs.js.map +1 -1
  18. package/dist/plugin.js +1036 -1227
  19. package/dist/plugin.js.map +1 -1
  20. package/electron/dist/plugin.js +589 -744
  21. package/electron/dist/plugin.js.map +1 -1
  22. package/ios/Plugin/CapacitorSQLite.swift +34 -1
  23. package/ios/Plugin/CapacitorSQLitePlugin.m +1 -0
  24. package/ios/Plugin/CapacitorSQLitePlugin.swift +25 -0
  25. package/ios/Plugin/Database.swift +29 -1
  26. package/ios/Plugin/Extensions/String.swift +8 -0
  27. package/ios/Plugin/ImportExportJson/ExportToJson.swift +190 -32
  28. package/ios/Plugin/ImportExportJson/ImportFromJson.swift +73 -38
  29. package/ios/Plugin/Utils/UtilsDrop.swift +2 -2
  30. package/ios/Plugin/Utils/UtilsJson.swift +68 -1
  31. package/ios/Plugin/Utils/UtilsSQLCipher.swift +277 -29
  32. package/ios/Plugin/Utils/UtilsUpgrade.swift +33 -13
  33. 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 == 5 || res.count == 6 || res.count == 7 {
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.getTablesFull(
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.getTablesFull(
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.getTablesFull(
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
- " > \(syncDate);"
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.getTablesFull(
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.getTablesFull(
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 <= 1 ||
475
- (!isSchema && !isIndexes && !isValues) {
476
- throw ExportToJsonError.getTablesPartial(
477
- message: "Error table \(tableName) is not a jsonTable")
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
- var resSyncDate = try UtilsSQLCipher.querySQL(
534
- mDB: mDB, sql: query, values: [])
535
- if resSyncDate.count > 1 {
536
- resSyncDate.removeFirst()
537
- guard let res: Int64 = resSyncDate[0]["sync_date"] as?
538
- Int64 else {
539
- throw ExportToJsonError.getSyncDate(
540
- message: "Error get sync date failed")
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
- if res > 0 {ret = res}
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
- // if types[jpos] == "INTEGER" {
1006
- if values[pos][names[jpos]] is String {
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 Double {
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 <= OLD.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
- let rowValues = UtilsJson.getValuesFromRow(
426
+ var rowValues = UtilsJson.getValuesFromRow(
431
427
  rowValues: row)
432
- let lastId: Int64 = try UtilsSQLCipher.prepareSQL(
433
- mDB: mDB, sql: stmt, values: rowValues)
434
- if lastId < 0 {
435
- throw ImportFromJsonError.createTableData(
436
- message: "lastId < 0")
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 ImportFromJsonError.createRowStatement(
439
- let message) {
440
- throw ImportFromJsonError.createTableData(
441
- message: message)
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
- // Update
503
- let setString: String = UtilsJson.setNameForUpdate(
504
- names: jsonNamesTypes.names)
505
- if setString.count == 0 {
506
- var message: String = "importFromJson: Table "
507
- message.append("\(tableName) values row ")
508
- message.append("\(pos) not set to String")
509
- throw ImportFromJsonError.createRowStatement(
510
- message: message)
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
- stmt = "UPDATE \(tableName) SET \(setString) WHERE "
514
- if let rwValue = row[0].value as? String {
515
- stmt += "\(jsonNamesTypes.names[0]) = '\(rwValue)';"
516
- } else if let rwValue = row[0].value as? Int {
517
- stmt += "\(jsonNamesTypes.names[0]) = \(rwValue);"
518
- } else {
519
- var msg: String = "importFromJson: Table "
520
- msg.append("\(tableName) values row[0]does not exist")
521
- throw ImportFromJsonError.createRowStatement(
522
- message: message)
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