@capacitor-community/sqlite 5.0.5-1 → 5.0.5

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 (35) hide show
  1. package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLite.java +109 -156
  2. package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLitePlugin.java +81 -249
  3. package/android/src/main/java/com/getcapacitor/community/database/sqlite/NotificationCenter.java +1 -1
  4. package/android/src/main/java/com/getcapacitor/community/database/sqlite/RetHandler.java +0 -12
  5. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/Database.java +175 -40
  6. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/ExportToJson.java +141 -135
  7. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/ImportFromJson.java +2 -1
  8. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsBiometric.java +0 -4
  9. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsFile.java +30 -18
  10. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsMigrate.java +12 -4
  11. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsNCDatabase.java +4 -1
  12. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsSQLCipher.java +8 -6
  13. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsSQLite.java +14 -28
  14. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsSecret.java +0 -1
  15. package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/UtilsUpgrade.java +0 -1
  16. package/dist/esm/definitions.d.ts +25 -4
  17. package/dist/esm/definitions.js +42 -19
  18. package/dist/esm/definitions.js.map +1 -1
  19. package/dist/plugin.cjs.js +42 -19
  20. package/dist/plugin.cjs.js.map +1 -1
  21. package/dist/plugin.js +42 -19
  22. package/dist/plugin.js.map +1 -1
  23. package/electron/dist/plugin.js +197 -125
  24. package/electron/dist/plugin.js.map +1 -1
  25. package/ios/Plugin/CapacitorSQLite.swift +8 -4
  26. package/ios/Plugin/CapacitorSQLitePlugin.swift +6 -3
  27. package/ios/Plugin/Database.swift +28 -14
  28. package/ios/Plugin/ImportExportJson/ExportToJson.swift +10 -5
  29. package/ios/Plugin/ImportExportJson/ImportFromJson.swift +4 -2
  30. package/ios/Plugin/Utils/UtilsDownloadFromHTTP.swift +61 -61
  31. package/ios/Plugin/Utils/UtilsDrop.swift +2 -1
  32. package/ios/Plugin/Utils/UtilsSQLCipher.swift +255 -23
  33. package/ios/Plugin/Utils/UtilsUpgrade.swift +0 -1
  34. package/package.json +2 -2
  35. package/src/definitions.ts +67 -18
@@ -37,6 +37,9 @@ enum UtilsSQLCipherError: Error {
37
37
  case openDBNoPassword(message: String)
38
38
  case openDBStoredPassword(message: String)
39
39
  case openDBGlobalPassword(message: String)
40
+ case returningWorkAround(message: String)
41
+ case getUpdDelReturnedValues(message: String)
42
+ case getFirstPK(message: String)
40
43
  }
41
44
  enum State: String {
42
45
  case DOESNOTEXIST, UNENCRYPTED, ENCRYPTEDSECRET,
@@ -414,20 +417,40 @@ class UtilsSQLCipher {
414
417
  // swiftlint:disable function_body_length
415
418
  // swiftlint:disable cyclomatic_complexity
416
419
  class func prepareSQL(mDB: Database, sql: String, values: [Any],
417
- fromJson: Bool) throws -> Int64 {
420
+ fromJson: Bool, returnMode: String) throws -> (Int64, [[String: Any]]) {
418
421
  var msg: String = "Error prepareSQL: "
419
422
  if !mDB.isDBOpen() {
420
423
  msg.append("Database not opened")
421
424
  throw UtilsSQLCipherError.prepareSQL(message: msg)
422
425
  }
426
+ let systemVersion = UIDevice.current.systemVersion
423
427
  var runSQLStatement: OpaquePointer?
424
428
  var message: String = ""
425
429
  var lastId: Int64 = -1
426
430
  var sqlStmt = sql
431
+ var names: String = ""
432
+ var result: [[String: Any]] = []
433
+ var retMode: String
434
+ if #available(iOS 15, *) {
435
+ retMode = returnMode
436
+ } else {
437
+ retMode = returnMode
438
+ if retMode != "no" {
439
+ retMode = "wA\(retMode)"
440
+ }
441
+ }
442
+
443
+ if (retMode == "no" || retMode.prefix(2) == "wA") &&
444
+ sqlStmt.uppercased().contains("RETURNING") {
445
+ let stmtNames = getStmtAndRetColNames(sqlStmt: sqlStmt,
446
+ retMode: retMode)
447
+ sqlStmt = stmtNames["stmt"] ?? sqlStmt
448
+ names = stmtNames["names"] ?? ""
449
+ }
427
450
  // Check for DELETE statement
428
451
  if !fromJson && sqlStmt.prefix(6).uppercased() == "DELETE" {
429
452
  do {
430
- sqlStmt = try deleteSQL(mDB: mDB, sql: sql,
453
+ sqlStmt = try deleteSQL(mDB: mDB, sql: sqlStmt,
431
454
  values: values)
432
455
  } catch UtilsSQLCipherError.deleteSQL(let message) {
433
456
  let msg = "Error: prepareSQL \(message)"
@@ -438,6 +461,7 @@ class UtilsSQLCipher {
438
461
  mDB.mDb, sqlStmt, -1, &runSQLStatement, nil)
439
462
  if returnCode == SQLITE_OK {
440
463
  if !values.isEmpty {
464
+ // retMode = "no"
441
465
  // do the binding of values
442
466
  var idx: Int = 1
443
467
  for value in values {
@@ -452,12 +476,35 @@ class UtilsSQLCipher {
452
476
  if message.count > 0 { break }
453
477
  }
454
478
  }
455
- returnCode = sqlite3_step(runSQLStatement)
456
- if returnCode != SQLITE_DONE {
457
- let errmsg: String = String(
458
- cString: sqlite3_errmsg(mDB.mDb))
459
- message = "Error: prepareSQL step failed rc: "
460
- message.append("\(returnCode) message: \(errmsg)")
479
+ if retMode == "no" {
480
+ returnCode = sqlite3_step(runSQLStatement)
481
+ if returnCode != SQLITE_DONE {
482
+ let errmsg: String = String(
483
+ cString: sqlite3_errmsg(mDB.mDb))
484
+ message = "Error: prepareSQL step failed rc: "
485
+ message.append("\(returnCode) message: \(errmsg)")
486
+ }
487
+ } else {
488
+ if retMode.prefix(2) == "wA" {
489
+ do {
490
+ result = try UtilsSQLCipher.returningWorkAround(
491
+ mDB: mDB,
492
+ runSQLStatement: runSQLStatement, sqlStmt: sqlStmt,
493
+ names: names, returnMode: retMode)
494
+ } catch UtilsSQLCipherError
495
+ .returningWorkAround(let message) {
496
+ throw UtilsSQLCipherError.prepareSQL(message: message)
497
+ }
498
+ } else {
499
+
500
+ do {
501
+ result = try UtilsSQLCipher.fetchColumnInfo(
502
+ handle: runSQLStatement, returnMode: retMode)
503
+ } catch UtilsSQLCipherError
504
+ .fetchColumnInfo(let message) {
505
+ throw UtilsSQLCipherError.prepareSQL(message: message)
506
+ }
507
+ }
461
508
  }
462
509
  } else {
463
510
  let errmsg: String = String(
@@ -476,9 +523,156 @@ class UtilsSQLCipher {
476
523
  throw UtilsSQLCipherError.prepareSQL(message: message)
477
524
  } else {
478
525
  lastId = Int64(sqlite3_last_insert_rowid(mDB.mDb))
479
- return lastId
526
+ return (lastId, result)
480
527
  }
481
528
  }
529
+
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
+ // MARK: - returningWorkAround
555
+
556
+ class func returningWorkAround(mDB: Database, runSQLStatement: OpaquePointer?,
557
+ sqlStmt: String, names: String,
558
+ returnMode: String) throws -> [[String: Any]] {
559
+ var result: [[String: Any]] = []
560
+ let initLastId = Int64(sqlite3_last_insert_rowid(mDB.mDb))
561
+ if sqlStmt.prefix(6).uppercased() == "DELETE" && names.count > 0 {
562
+ do {
563
+ result = try getUpdDelReturnedValues(mDB: mDB, sqlStmt: sqlStmt,
564
+ names: names )
565
+ } catch UtilsSQLCipherError
566
+ .getUpdDelReturnedValues(let message) {
567
+ throw UtilsSQLCipherError.returningWorkAround(message: message)
568
+ }
569
+ }
570
+ let returnCode: Int32 = sqlite3_step(runSQLStatement)
571
+ if returnCode != SQLITE_DONE {
572
+ let errmsg: String = String(
573
+ cString: sqlite3_errmsg(mDB.mDb))
574
+ var message = "Error: prepareSQL step failed rc: "
575
+ message.append("\(returnCode) message: \(errmsg)")
576
+ throw UtilsSQLCipherError.returningWorkAround(message: message)
577
+
578
+ }
579
+ if sqlStmt.prefix(6).uppercased() == "INSERT" {
580
+ let lastId = Int64(sqlite3_last_insert_rowid(mDB.mDb))
581
+ let tableName = extractTableName(from: sqlStmt)
582
+ if let tblName = tableName {
583
+ var query = "SELECT \(names) FROM \(tblName) WHERE rowid "
584
+ if returnMode == "wAone" {
585
+ query += "= \(initLastId + 1);"
586
+ } else {
587
+ query += "BETWEEN \(initLastId + 1) AND \(lastId);"
588
+ }
589
+ do {
590
+ result = try querySQL(mDB: mDB, sql: query, values: [])
591
+ } catch UtilsSQLCipherError.querySQL(let message) {
592
+ throw UtilsSQLCipherError.returningWorkAround(message: message)
593
+ }
594
+
595
+ }
596
+
597
+ } else if sqlStmt.prefix(6).uppercased() == "UPDATE" {
598
+ do {
599
+ result = try getUpdDelReturnedValues(mDB: mDB, sqlStmt: sqlStmt,
600
+ names: names )
601
+ } catch UtilsSQLCipherError
602
+ .getUpdDelReturnedValues(let message) {
603
+ throw UtilsSQLCipherError.returningWorkAround(message: message)
604
+ }
605
+
606
+ }
607
+
608
+ return result
609
+ }
610
+
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
+
482
676
  // swiftlint:enable cyclomatic_complexity
483
677
  // swiftlint:enable function_body_length
484
678
 
@@ -530,6 +724,7 @@ class UtilsSQLCipher {
530
724
  class func findReferencesAndUpdate(mDB: Database, tableName: String,
531
725
  whereStmt: String,
532
726
  values: [Any]) throws {
727
+ var lastId: Int64 = -1
533
728
  do {
534
729
  var references = try getReferences(mDB: mDB,
535
730
  tableName: tableName)
@@ -590,9 +785,10 @@ class UtilsSQLCipher {
590
785
  }
591
786
  }
592
787
 
593
- let lastId = try prepareSQL(mDB: mDB, sql: stmt,
594
- values: selValues,
595
- fromJson: false)
788
+ let resp = try prepareSQL(mDB: mDB, sql: stmt,
789
+ values: selValues,
790
+ fromJson: false, returnMode: "no")
791
+ lastId = resp.0
596
792
  if lastId == -1 {
597
793
  let msg = "UPDATE sql_deleted failed for references " +
598
794
  "table: \(refTable) "
@@ -825,7 +1021,7 @@ class UtilsSQLCipher {
825
1021
 
826
1022
  class func querySQL(mDB: Database, sql: String,
827
1023
  values: [Any]) throws -> [[String: Any]] {
828
- var msg: String = "Error prepareSQL: "
1024
+ var msg: String = "Error querySQL: "
829
1025
  if !mDB.isDBOpen() {
830
1026
  msg.append("Database not opened")
831
1027
  throw UtilsSQLCipherError.querySQL(message: msg)
@@ -845,7 +1041,7 @@ class UtilsSQLCipher {
845
1041
  if message.count == 0 {
846
1042
  do {
847
1043
  result = try UtilsSQLCipher.fetchColumnInfo(
848
- handle: selectSQLStatement)
1044
+ handle: selectSQLStatement, returnMode: "all")
849
1045
  } catch UtilsSQLCipherError
850
1046
  .fetchColumnInfo(let message) {
851
1047
  throw UtilsSQLCipherError.querySQL(message: message)
@@ -875,7 +1071,7 @@ class UtilsSQLCipher {
875
1071
 
876
1072
  // swiftlint:disable function_body_length
877
1073
  // swiftlint:disable cyclomatic_complexity
878
- class func fetchColumnInfo(handle: OpaquePointer?)
1074
+ class func fetchColumnInfo(handle: OpaquePointer?, returnMode: String)
879
1075
  throws -> [[String: Any]] {
880
1076
  var result: [[String: Any]] = []
881
1077
  var columnCount: Int32 = 0
@@ -937,7 +1133,9 @@ class UtilsSQLCipher {
937
1133
  }
938
1134
  }
939
1135
  result.append(rowData)
940
-
1136
+ if returnMode == "one" {
1137
+ break
1138
+ }
941
1139
  }
942
1140
  return result
943
1141
  }
@@ -1026,14 +1224,16 @@ class UtilsSQLCipher {
1026
1224
 
1027
1225
  // MARK: - ExecuteSet
1028
1226
 
1029
- class func executeSet(mDB: Database, set: [[String: Any]])
1030
- throws -> Int64 {
1227
+ // swiftlint:disable function_body_length
1228
+ class func executeSet(mDB: Database, set: [[String: Any]], returnMode: String)
1229
+ throws -> (Int64, [[String: Any]]) {
1031
1230
  var msg: String = "Error executeSet: "
1032
1231
  if !mDB.isDBOpen() {
1033
1232
  msg.append("Database not opened")
1034
1233
  throw UtilsSQLCipherError.executeSet(message: msg)
1035
1234
  }
1036
1235
  var lastId: Int64 = -1
1236
+ var response: [[String: Any]] = []
1037
1237
  do {
1038
1238
  for dict in set {
1039
1239
  guard let sql: String = dict["statement"] as? String
@@ -1046,39 +1246,71 @@ class UtilsSQLCipher {
1046
1246
  throw UtilsSQLCipherError.executeSet(
1047
1247
  message: "No values given")
1048
1248
  }
1249
+ var respSet: [[String: Any]] = []
1049
1250
  let isArray = values.count > 0 ? UtilsSQLCipher.parse(mVar: values[0]) : false
1050
1251
  if isArray {
1051
1252
  if let arrValues = values as? [[Any]] {
1052
1253
  for vals in arrValues {
1053
- lastId = try UtilsSQLCipher
1254
+ let resp = try UtilsSQLCipher
1054
1255
  .prepareSQL(mDB: mDB, sql: sql,
1055
- values: vals, fromJson: false)
1256
+ values: vals, fromJson: false,
1257
+ returnMode: returnMode)
1258
+ lastId = resp.0
1259
+ respSet = resp.1
1260
+
1056
1261
  if lastId == -1 {
1057
1262
  let message: String = "lastId < 0"
1058
1263
  throw UtilsSQLCipherError
1059
1264
  .executeSet(message: message)
1060
1265
  }
1266
+
1267
+ response = addToResponse(response: response,
1268
+ respSet: respSet)
1061
1269
  }
1062
1270
  }
1063
1271
  } else {
1064
- lastId = try UtilsSQLCipher
1272
+ let resp = try UtilsSQLCipher
1065
1273
  .prepareSQL(mDB: mDB, sql: sql, values: values,
1066
- fromJson: false)
1274
+ fromJson: false, returnMode: returnMode)
1275
+ lastId = resp.0
1276
+ respSet = resp.1
1067
1277
  if lastId == -1 {
1068
1278
  let message: String = "lastId < 0"
1069
1279
  throw UtilsSQLCipherError.executeSet(
1070
1280
  message: message)
1071
1281
  }
1282
+ response = addToResponse(response: response, respSet: respSet)
1072
1283
  }
1073
1284
  }
1074
1285
 
1075
- return lastId
1286
+ return (lastId, response)
1076
1287
  } catch UtilsSQLCipherError.prepareSQL(let message) {
1077
1288
  throw UtilsSQLCipherError.executeSet(
1078
1289
  message: message)
1079
1290
  }
1080
1291
  }
1081
1292
 
1293
+ class func addToResponse(response: [[String: Any]],
1294
+ respSet: [[String: Any]]) -> [[String: Any]] {
1295
+ var retResponse = response
1296
+ var mRespSet = respSet
1297
+ if !retResponse.isEmpty {
1298
+ let keysInArray1 = ["ios_columns"]
1299
+ mRespSet = mRespSet.filter { dict2 in
1300
+ guard let dict2Key = dict2.keys.first else {
1301
+ return true // Keep dictionaries without any keys
1302
+ }
1303
+ return !keysInArray1.contains(dict2Key)
1304
+
1305
+ }
1306
+ }
1307
+ retResponse.append(contentsOf: mRespSet)
1308
+
1309
+ return retResponse
1310
+
1311
+ }
1312
+ // swiftlint:enable function_body_length
1313
+
1082
1314
  // MARK: - RestoreDB
1083
1315
 
1084
1316
  class func restoreDB(databaseLocation: String, databaseName: String) throws {
@@ -26,7 +26,6 @@ class UtilsUpgrade {
26
26
 
27
27
  for (versionKey, upgrade) in Array(upgDict).sorted(by: {$0.0 < $1.0}) {
28
28
  if versionKey > currentVersion && versionKey <= targetVersion {
29
- print("- UtilsUpgrade.onUpgrade toVersion: \(versionKey)")
30
29
 
31
30
  guard let statements = upgrade["statements"] as? [String] else {
32
31
  let msg: String = "Error: onUpgrade statements not given"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor-community/sqlite",
3
- "version": "5.0.5-1",
3
+ "version": "5.0.5",
4
4
  "description": "Community plugin for native & electron SQLite databases",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -95,6 +95,6 @@
95
95
  }
96
96
  },
97
97
  "dependencies": {
98
- "jeep-sqlite": "^2.3.6"
98
+ "jeep-sqlite": "^2.3.8"
99
99
  }
100
100
  }
@@ -506,6 +506,14 @@ export interface capSQLiteSetOptions {
506
506
  * @since 4.1.0-7
507
507
  */
508
508
  readonly?: boolean;
509
+ /**
510
+ * return mode
511
+ * default 'no'
512
+ * value 'all'
513
+ * value 'one' for Electron platform
514
+ * @since 5.0.5-3
515
+ */
516
+ returnMode?: string;
509
517
  }
510
518
  export interface capSQLiteRunOptions {
511
519
  /**
@@ -532,6 +540,14 @@ export interface capSQLiteRunOptions {
532
540
  * @since 4.1.0-7
533
541
  */
534
542
  readonly?: boolean;
543
+ /**
544
+ * return mode
545
+ * default 'no'
546
+ * value 'all'
547
+ * value 'one' for Electron platform
548
+ * @since 5.0.5-3
549
+ */
550
+ returnMode?: string;
535
551
  }
536
552
  export interface capSQLiteQueryOptions {
537
553
  /**
@@ -721,6 +737,10 @@ export interface Changes {
721
737
  * the lastId created from a run command
722
738
  */
723
739
  lastId?: number;
740
+ /**
741
+ * values when RETURNING
742
+ */
743
+ values?: any[];
724
744
  }
725
745
  export interface capSQLiteValues {
726
746
  /**
@@ -1572,7 +1592,7 @@ export class SQLiteConnection implements ISQLiteConnection {
1572
1592
  const res = await this.sqlite.getDatabaseList();
1573
1593
  const values: string[] = res.values;
1574
1594
  values.sort();
1575
- const ret = {values: values};
1595
+ const ret = { values: values };
1576
1596
  return Promise.resolve(ret);
1577
1597
  } catch (err) {
1578
1598
  return Promise.reject(err);
@@ -1705,6 +1725,7 @@ export interface ISQLiteDBConnection {
1705
1725
  statement: string,
1706
1726
  values?: any[],
1707
1727
  transaction?: boolean,
1728
+ returnMode?: string,
1708
1729
  ): Promise<capSQLiteChanges>;
1709
1730
  /**
1710
1731
  * Execute SQLite DB Connection Set
@@ -1715,6 +1736,7 @@ export interface ISQLiteDBConnection {
1715
1736
  executeSet(
1716
1737
  set: capSQLiteSet[],
1717
1738
  transaction?: boolean,
1739
+ returnMode?: string,
1718
1740
  ): Promise<capSQLiteChanges>;
1719
1741
  /**
1720
1742
  * Check if a SQLite DB Connection exists
@@ -1898,22 +1920,9 @@ export class SQLiteDBConnection implements ISQLiteDBConnection {
1898
1920
  readonly: this.readonly,
1899
1921
  });
1900
1922
  }
1901
- if (res && typeof res.values[0] === 'object') {
1902
- if (Object.keys(res.values[0]).includes('ios_columns')) {
1903
- const columnList: string[] = res.values[0]['ios_columns'];
1904
- const iosRes: any[] = [];
1905
- for (let i = 1; i < res.values.length; i++) {
1906
- const rowJson: any = res.values[i];
1907
- const resRowJson: any = {};
1908
- for (const item of columnList) {
1909
- resRowJson[item] = rowJson[item];
1910
- }
1911
- iosRes.push(resRowJson);
1912
- }
1913
- res = {};
1914
- res['values'] = iosRes;
1915
- }
1916
- }
1923
+
1924
+ // reorder rows for ios
1925
+ res = await this.reorderRows(res);
1917
1926
  return Promise.resolve(res);
1918
1927
  } catch (err) {
1919
1928
  return Promise.reject(err);
@@ -1923,28 +1932,39 @@ export class SQLiteDBConnection implements ISQLiteDBConnection {
1923
1932
  statement: string,
1924
1933
  values?: any[],
1925
1934
  transaction = true,
1935
+ returnMode = 'no',
1926
1936
  ): Promise<capSQLiteChanges> {
1927
1937
  let res: any;
1928
1938
  try {
1929
1939
  if (!this.readonly) {
1930
1940
  if (values && values.length > 0) {
1941
+ const mRetMode = statement.toUpperCase().includes('RETURNING')
1942
+ ? returnMode
1943
+ : 'no';
1931
1944
  res = await this.sqlite.run({
1932
1945
  database: this.dbName,
1933
1946
  statement: statement,
1934
1947
  values: values,
1935
1948
  transaction: transaction,
1936
1949
  readonly: false,
1950
+ returnMode: mRetMode,
1937
1951
  });
1938
1952
  // }
1939
1953
  } else {
1954
+ const mRetMode = statement.toUpperCase().includes('RETURNING')
1955
+ ? returnMode
1956
+ : 'no';
1940
1957
  res = await this.sqlite.run({
1941
1958
  database: this.dbName,
1942
1959
  statement: statement,
1943
1960
  values: [],
1944
1961
  transaction: transaction,
1945
1962
  readonly: false,
1963
+ returnMode: mRetMode,
1946
1964
  });
1947
1965
  }
1966
+ // reorder rows for ios
1967
+ res.changes = await this.reorderRows(res.changes);
1948
1968
  return Promise.resolve(res);
1949
1969
  } else {
1950
1970
  return Promise.reject('not allowed in read-only mode');
@@ -1956,16 +1976,21 @@ export class SQLiteDBConnection implements ISQLiteDBConnection {
1956
1976
  async executeSet(
1957
1977
  set: capSQLiteSet[],
1958
1978
  transaction = true,
1979
+ returnMode = 'no',
1959
1980
  ): Promise<capSQLiteChanges> {
1981
+ let res: any;
1960
1982
  try {
1961
1983
  if (!this.readonly) {
1962
- const res: any = await this.sqlite.executeSet({
1984
+ res = await this.sqlite.executeSet({
1963
1985
  database: this.dbName,
1964
1986
  set: set,
1965
1987
  transaction: transaction,
1966
1988
  readonly: false,
1989
+ returnMode: returnMode,
1967
1990
  });
1968
1991
  // }
1992
+ // reorder rows for ios
1993
+ res.changes = await this.reorderRows(res.changes);
1969
1994
  return Promise.resolve(res);
1970
1995
  } else {
1971
1996
  return Promise.reject('not allowed in read-only mode');
@@ -2111,12 +2136,16 @@ export class SQLiteDBConnection implements ISQLiteDBConnection {
2111
2136
  }
2112
2137
  for (const task of txn) {
2113
2138
  if (task.values && task.values.length > 0) {
2139
+ const retMode = task.statement.toUpperCase().includes('RETURNING')
2140
+ ? 'all'
2141
+ : 'no';
2114
2142
  const ret = await this.sqlite.run({
2115
2143
  database: this.dbName,
2116
2144
  statement: task.statement,
2117
2145
  values: task.values,
2118
2146
  transaction: false,
2119
2147
  readonly: false,
2148
+ returnMode: retMode,
2120
2149
  });
2121
2150
  if (ret.changes.lastId === -1) {
2122
2151
  await this.execute('ROLLBACK;', false);
@@ -2160,4 +2189,24 @@ export class SQLiteDBConnection implements ISQLiteDBConnection {
2160
2189
  return Promise.reject(err);
2161
2190
  }
2162
2191
  }
2192
+ private async reorderRows(res: any): Promise<any> {
2193
+ const retRes: any = res;
2194
+ if (res?.values && typeof res.values[0] === 'object') {
2195
+ if (Object.keys(res.values[0]).includes('ios_columns')) {
2196
+ const columnList: string[] = res.values[0]['ios_columns'];
2197
+ const iosRes: any[] = [];
2198
+ for (let i = 1; i < res.values.length; i++) {
2199
+ const rowJson: any = res.values[i];
2200
+ const resRowJson: any = {};
2201
+ for (const item of columnList) {
2202
+ resRowJson[item] = rowJson[item];
2203
+ }
2204
+ iosRes.push(resRowJson);
2205
+ }
2206
+ retRes['values'] = iosRes;
2207
+ }
2208
+ }
2209
+
2210
+ return Promise.resolve(retRes);
2211
+ }
2163
2212
  }