@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
package/README.md CHANGED
@@ -9,14 +9,14 @@
9
9
  </p>
10
10
  <br>
11
11
  <p align="center">
12
- <img src="https://img.shields.io/maintenance/yes/2021?style=flat-square" />
12
+ <img src="https://img.shields.io/maintenance/yes/2022?style=flat-square" />
13
13
  <a href="https://github.com/capacitor-community/sqlite/actions?query=workflow%3A%22CI%22"><img src="https://img.shields.io/github/workflow/status/capacitor-community/sqlite/CI?style=flat-square" /></a>
14
14
  <a href="https://www.npmjs.com/package/@capacitor-community/sqlite"><img src="https://img.shields.io/npm/l/@capacitor-community/sqlite?style=flat-square" /></a>
15
15
  <br>
16
16
  <a href="https://www.npmjs.com/package/@capacitor-community/sqlite"><img src="https://img.shields.io/npm/dw/@capacitor-community/sqlite?style=flat-square" /></a>
17
17
  <a href="https://www.npmjs.com/package/@capacitor-community/sqlite"><img src="https://img.shields.io/npm/v/@capacitor-community/sqlite?style=flat-square" /></a>
18
18
  <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
19
- <a href="#contributors-"><img src="https://img.shields.io/badge/all%20contributors-13-orange?style=flat-square" /></a>
19
+ <a href="#contributors-"><img src="https://img.shields.io/badge/all%20contributors-16-orange?style=flat-square" /></a>
20
20
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
21
21
  </p>
22
22
 
@@ -28,6 +28,38 @@
28
28
 
29
29
  ## CAPACITOR 3 (Master)
30
30
 
31
+ 🚨 Release 3.4.3-2 Web, iOS & Android only ->> 🚨
32
+
33
+ The main change is related to the delete table's rows when a synchronization table exists as well as a last_mofidied table's column, allowing for database synchronization of the local database with a remote server database.
34
+
35
+ - All existing triggers to YOUR_TABLE_NAME_trigger_last_modified must be modified as follows
36
+ ```
37
+ CREATE TRIGGER YOUR_TABLE_NAME_trigger_last_modified
38
+ AFTER UPDATE ON YOUR_TABLE_NAME
39
+ FOR EACH ROW WHEN NEW.last_modified < OLD.last_modified
40
+ BEGIN
41
+ UPDATE YOUR_TABLE_NAME SET last_modified= (strftime('%s', 'now')) WHERE id=OLD.id;
42
+ END;
43
+ ```
44
+ - an new column `sql_deleted` must be added to each of your tables as
45
+ ```
46
+ sql_deleted BOOLEAN DEFAULT 0 CHECK (sql_deleted IN (0, 1))
47
+ ```
48
+ This column will be autommatically set to 1 when you will use a `DELETE FROM ...` sql statement in the `execute`, `run` or `executeSet` methods.
49
+
50
+ - In the JSON object that you provide to `importFromJson`, all the deleted rows in your remote server database's tables must have the `sql_deleted` column set to 1. This will indicate to the import process to physically delete the corresponding rows in your local database. All the others rows must have the `sql_deleted` column set to 0.
51
+
52
+ - In the JSON object outputs by the `exportToJson`, all the deleted rows in your local database have got the `sql_deleted` column set to 1 to help in your synchronization management process with the remote server database. A system `last_exported_date` is automatically saved in the synchronization table at the start of the export process flow.
53
+
54
+ - On successfull completion of your synchronization management process with the remote server database, you must
55
+ - Set a new synchronization date (as `(new Date()).toISOString()`) with the `setSyncDate` method.
56
+ - Execute the `deleteExportedRows` method which physically deletes all table's rows having 1 as value for the `sql_deleted` column prior to the `last_exported_date` in your local database.
57
+
58
+ An example of using this new feature is given in [solidjs-vite-sqlite-app](https://github.com/jepiqueau/capacitor-solid-sqlite). It has been used to test the validity of the implementation.
59
+
60
+
61
+ 🚨 Release 3.4.3-2 <<- 🚨
62
+
31
63
  🚨 Release 3.4.2-4 ->> 🚨
32
64
  !!!! DO NOT USE IT !!!!
33
65
  🚨 Release 3.4.2-4 <<- 🚨
@@ -297,6 +329,7 @@ No configuration required for this plugin
297
329
  | deleteDatabase | ✅ | ✅ | ✅ | ✅ |
298
330
  | importFromJson | ✅ | ✅ | ✅ | ✅ |
299
331
  | exportToJson | ✅ | ✅ | ✅ | ✅ |
332
+ | deleteExportedRows | ✅ | ✅ | ❌ | ✅ | NEW in 3.4.3-2
300
333
  | createSyncTable | ✅ | ✅ | ✅ | ✅ |
301
334
  | setSyncDate | ✅ | ✅ | ✅ | ✅ |
302
335
  | getSyncDate | ✅ | ✅ | ✅ | ✅ |
@@ -388,6 +421,11 @@ No configuration required for this plugin
388
421
 
389
422
  - [vue-vite-sqlite-app](https://github.com/jepiqueau/vuevite-app)
390
423
 
424
+ ### SolidJS+Vite
425
+
426
+ - [solidjs-vite-sqlite-app](https://github.com/jepiqueau/capacitor-solid-sqlite)
427
+
428
+
391
429
  ## Usage
392
430
 
393
431
  - [see capacitor documentation](https://capacitor.ionicframework.com/docs/getting-started/with-ionic)
@@ -420,8 +458,12 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
420
458
  <td align="center"><a href="https://github.com/gion-andri"><img src="https://avatars.githubusercontent.com/u/540998?v=4" width="100px;" alt=""/><br /><sub><b>Gion-Andri Cantieni</b></sub></a><br /><a href="https://github.com/capacitor-community/sqlite/commits?author=gion-andri" title="Documentation">📖</a></td>
421
459
  <td align="center"><a href="https://github.com/robingenz"><img src="https://avatars.githubusercontent.com/u/13857929?v=4" width="100px;" alt=""/><br /><sub><b>Robin Genz</b></sub></a><br /><a href="https://github.com/capacitor-community/sqlite/commits?author=robingenz" title="Documentation">📖</a></td>
422
460
  <td align="center"><a href="https://github.com/dewald-els"><img src="https://avatars.githubusercontent.com/u/10051247?v=4" width="100px;" alt=""/><br /><sub><b>Dewald Els</b></sub></a><br /><a href="https://github.com/capacitor-community/sqlite/commits?author=dewald-els" title="Code">💻</a></td>
423
- <td align="center"><a href="https://github.com/joewoodhouse"><img src="https://avatars.githubusercontent.com/u/3168135?v=4" width="100px;" alt=""/><br /><sub><b>Joe Woodhouse</b></sub></a><br /><a href="https://github.com/capacitor-community/sqlite/commits?author=joewoodhouse" title="Documentation">📖</a></td> </tr>
424
- <td align="center"><a href="https://github.com/ptasheq"><img src="https://avatars.githubusercontent.com/u/3025106?v=4" width="100px;" alt=""/><br /><sub><b>Ptasheq</b></sub></a><br /><a href="https://github.com/capacitor-community/sqlite/commits?author=ptasheq" title="Documentation">📖</a></td> </tr>
461
+ <td align="center"><a href="https://github.com/joewoodhouse"><img src="https://avatars.githubusercontent.com/u/3168135?v=4" width="100px;" alt=""/><br /><sub><b>Joe Woodhouse</b></sub></a><br /><a href="https://github.com/capacitor-community/sqlite/commits?author=joewoodhouse" title="Documentation">📖</a></td>
462
+ <td align="center"><a href="https://github.com/ptasheq"><img src="https://avatars.githubusercontent.com/u/3025106?v=4" width="100px;" alt=""/><br /><sub><b>Ptasheq</b></sub></a><br /><a href="https://github.com/capacitor-community/sqlite/commits?author=ptasheq" title="Documentation">📖</a></td>
463
+ <td align="center"><a href="https://github.com/victorybiz"><img src="https://avatars.githubusercontent.com/u/8276466?v=4" width="100px;" alt=""/><br /><sub><b>Victory Osayi</b></sub></a><br /><a href="https://github.com/capacitor-community/sqlite/commits?author=victorybiz" title="Code">💻</a></td>
464
+ <td align="center"><a href="https://github.com/tobiasmuecksch"><img src="https://avatars.githubusercontent.com/u/1294854?v=4" width="100px;" alt=""/><br /><sub><b>Tobias Mücksch</b></sub></a><br /><a href="https://github.com/capacitor-community/sqlite/commits?author=tobiasmuecksch" title="Code">💻</a></td>
465
+ <td align="center"><a href="https://github.com/dragermrb"><img src="https://avatars.githubusercontent.com/u/11479696?v=4" width="100px;" alt=""/><br /><sub><b>Manuel Rodríguez</b></sub></a><br /><a href="https://github.com/capacitor-community/sqlite/commits?author=dragermrb" title="Code">💻</a></td>
466
+ </tr>
425
467
  </table>
426
468
 
427
469
  <!-- markdownlint-enable -->
@@ -864,6 +864,10 @@ public class CapacitorSQLite {
864
864
  Database db = dbDict.get(dbName);
865
865
  if (db != null) {
866
866
  try {
867
+ if (!db.isOpen()) {
868
+ String msg = "CreateSyncTable: db not opened";
869
+ throw new Exception(msg);
870
+ }
867
871
  JSObject res = db.createSyncTable();
868
872
  return res;
869
873
  } catch (Exception e) {
@@ -880,6 +884,10 @@ public class CapacitorSQLite {
880
884
  Database db = dbDict.get(dbName);
881
885
  if (db != null) {
882
886
  try {
887
+ if (!db.isOpen()) {
888
+ String msg = "SetSyncDate: db not opened";
889
+ throw new Exception(msg);
890
+ }
883
891
  db.setSyncDate(syncDate);
884
892
  return;
885
893
  } catch (Exception e) {
@@ -896,6 +904,10 @@ public class CapacitorSQLite {
896
904
  Database db = dbDict.get(dbName);
897
905
  if (db != null) {
898
906
  try {
907
+ if (!db.isOpen()) {
908
+ String msg = "GetSyncDate: db not opened";
909
+ throw new Exception(msg);
910
+ }
899
911
  long syncDate = db.getSyncDate();
900
912
  return syncDate;
901
913
  } catch (Exception e) {
@@ -1011,9 +1023,15 @@ public class CapacitorSQLite {
1011
1023
  Database db = dbDict.get(dbName);
1012
1024
  if (db != null) {
1013
1025
  try {
1026
+ if (!db.isOpen()) {
1027
+ String msg = "ExportToJson: db not opened";
1028
+ throw new Exception(msg);
1029
+ }
1014
1030
  JSObject ret = db.exportToJson(expMode);
1015
-
1016
- if (ret.length() == 5 || ret.length() == 6 || ret.length() == 7) {
1031
+ if (ret.length() == 0) {
1032
+ String msg = "ExportToJson: : return Object is empty " + "No data to synchronize";
1033
+ throw new Exception(msg);
1034
+ } else if (ret.length() == 5 || ret.length() == 6 || ret.length() == 7) {
1017
1035
  return ret;
1018
1036
  } else {
1019
1037
  String msg = "ExportToJson: return Obj is not a JsonSQLite Obj";
@@ -1029,6 +1047,27 @@ public class CapacitorSQLite {
1029
1047
  }
1030
1048
  }
1031
1049
 
1050
+ public void deleteExportedRows(String dbName) throws Exception {
1051
+ dbName = getDatabaseName(dbName);
1052
+ Database db = dbDict.get(dbName);
1053
+ if (db != null) {
1054
+ try {
1055
+ if (!db.isOpen()) {
1056
+ String msg = "deleteExportedRows: db not opened";
1057
+ throw new Exception(msg);
1058
+ }
1059
+ db.deleteExportedRows();
1060
+ return;
1061
+ } catch (Exception e) {
1062
+ String msg = "DeleteExportedRows " + e.getMessage();
1063
+ throw new Exception(msg);
1064
+ }
1065
+ } else {
1066
+ String msg = "No available connection for database " + dbName;
1067
+ throw new Exception(msg);
1068
+ }
1069
+ }
1070
+
1032
1071
  public void copyFromAssets(Boolean overwrite) throws Exception {
1033
1072
  String msg = "copy failed : ";
1034
1073
  try {
@@ -1259,6 +1259,32 @@ public class CapacitorSQLitePlugin extends Plugin {
1259
1259
  }
1260
1260
  }
1261
1261
 
1262
+ @PluginMethod
1263
+ public void deleteExportedRows(PluginCall call) {
1264
+ JSObject retObj = new JSObject();
1265
+ JsonSQLite retJson = new JsonSQLite();
1266
+ if (!call.getData().has("database")) {
1267
+ String msg = "ExportToJson: Must provide a database name";
1268
+ rHandler.retResult(call, null, msg);
1269
+ return;
1270
+ }
1271
+ String dbName = call.getString("database");
1272
+ if (implementation != null) {
1273
+ try {
1274
+ implementation.deleteExportedRows(dbName);
1275
+ rHandler.retResult(call, null, null);
1276
+ return;
1277
+ } catch (Exception e) {
1278
+ String msg = "DeleteExportedRows: " + e.getMessage();
1279
+ rHandler.retResult(call, null, msg);
1280
+ return;
1281
+ }
1282
+ } else {
1283
+ rHandler.retResult(call, null, loadMessage);
1284
+ return;
1285
+ }
1286
+ }
1287
+
1262
1288
  /**
1263
1289
  * CopyFromAssets
1264
1290
  * copy all databases from public/assets/databases to application folder
@@ -52,7 +52,7 @@ public class NotificationCenter {
52
52
  public synchronized void postNotification(String notificationName, Map<String, Object> _info) {
53
53
  ArrayList<MyRunnable> list = registredObjects.get(notificationName);
54
54
  if (list != null) {
55
- for (MyRunnable r : list) {
55
+ for (MyRunnable r : new ArrayList<>(list)) {
56
56
  r.setInfo(_info);
57
57
  r.run();
58
58
  }
@@ -18,6 +18,7 @@ import com.getcapacitor.JSObject;
18
18
  import com.getcapacitor.community.database.sqlite.SQLite.GlobalSQLite;
19
19
  import com.getcapacitor.community.database.sqlite.SQLite.ImportExportJson.ExportToJson;
20
20
  import com.getcapacitor.community.database.sqlite.SQLite.ImportExportJson.ImportFromJson;
21
+ import com.getcapacitor.community.database.sqlite.SQLite.ImportExportJson.JsonIndex;
21
22
  import com.getcapacitor.community.database.sqlite.SQLite.ImportExportJson.JsonSQLite;
22
23
  import com.getcapacitor.community.database.sqlite.SQLite.ImportExportJson.UtilsJson;
23
24
  import com.getcapacitor.community.database.sqlite.SQLite.UtilsSQLCipher;
@@ -34,6 +35,7 @@ import net.sqlcipher.Cursor;
34
35
  import net.sqlcipher.database.SQLiteDatabase;
35
36
  import net.sqlcipher.database.SQLiteException;
36
37
  import org.json.JSONArray;
38
+ import org.json.JSONException;
37
39
  import org.json.JSONObject;
38
40
 
39
41
  public class Database {
@@ -116,6 +118,7 @@ public class Database {
116
118
 
117
119
  /**
118
120
  * isOpen Method
121
+ *
119
122
  * @return database status
120
123
  */
121
124
  public Boolean isOpen() {
@@ -124,6 +127,7 @@ public class Database {
124
127
 
125
128
  /**
126
129
  * isNCDB Method
130
+ *
127
131
  * @return non-conformed database status
128
132
  */
129
133
  public Boolean isNCDB() {
@@ -132,6 +136,7 @@ public class Database {
132
136
 
133
137
  /**
134
138
  * GetUrl method
139
+ *
135
140
  * @return database url
136
141
  */
137
142
  public String getUrl() {
@@ -141,6 +146,7 @@ public class Database {
141
146
 
142
147
  /**
143
148
  * Open method
149
+ *
144
150
  * @return open status
145
151
  */
146
152
  public void open() throws Exception {
@@ -257,6 +263,7 @@ public class Database {
257
263
 
258
264
  /**
259
265
  * Close Method
266
+ *
260
267
  * @return close status
261
268
  */
262
269
 
@@ -293,6 +300,7 @@ public class Database {
293
300
 
294
301
  /**
295
302
  * IsDBExists Method
303
+ *
296
304
  * @return the existence of the database on folder
297
305
  */
298
306
  public boolean isDBExists() {
@@ -306,6 +314,7 @@ public class Database {
306
314
  /**
307
315
  * Execute Method
308
316
  * Execute an Array of SQL Statements
317
+ *
309
318
  * @param statements Array of Strings
310
319
  * @return
311
320
  */
@@ -319,7 +328,13 @@ public class Database {
319
328
  if (transaction) _db.beginTransaction();
320
329
  for (String cmd : statements) {
321
330
  if (!cmd.endsWith(";")) cmd += ";";
322
- _db.execSQL(cmd);
331
+ String nCmd = cmd;
332
+ String trimCmd = nCmd.trim().substring(0, 11).toUpperCase();
333
+ if (trimCmd.equals("DELETE FROM") && nCmd.toLowerCase().contains("WHERE".toLowerCase())) {
334
+ String whereStmt = nCmd.trim();
335
+ nCmd = deleteSQL(this, whereStmt, new ArrayList<Object>());
336
+ }
337
+ _db.execSQL(nCmd);
323
338
  }
324
339
  changes = _uSqlite.dbChanges(_db) - initChanges;
325
340
  if (changes != -1) {
@@ -340,6 +355,7 @@ public class Database {
340
355
  /**
341
356
  * ExecuteSet Method
342
357
  * Execute a Set of SQL Statements
358
+ *
343
359
  * @param set JSArray of statements
344
360
  * @return
345
361
  */
@@ -368,11 +384,11 @@ public class Database {
368
384
  for (int k = 0; k < valsJson.length(); k++) {
369
385
  vals.add(valsJson.get(k));
370
386
  }
371
- lastId = prepareSQL(statement, vals);
387
+ lastId = prepareSQL(statement, vals, false);
372
388
  if (lastId == -1) break;
373
389
  }
374
390
  } else {
375
- lastId = prepareSQL(statement, values);
391
+ lastId = prepareSQL(statement, values, false);
376
392
  }
377
393
  if (lastId == -1) break;
378
394
  }
@@ -399,6 +415,7 @@ public class Database {
399
415
  /**
400
416
  * InTransaction Method
401
417
  * Check if a transaction is still running
418
+ *
402
419
  * @return
403
420
  */
404
421
  public boolean inTransaction() {
@@ -407,8 +424,9 @@ public class Database {
407
424
 
408
425
  /**
409
426
  * RunSQL Method
427
+ *
410
428
  * @param statement a raw SQL statement
411
- * @param values Array of Strings to bind to the statement
429
+ * @param values Array of Strings to bind to the statement
412
430
  * @return
413
431
  */
414
432
  public JSObject runSQL(String statement, ArrayList<Object> values, Boolean... others) throws Exception {
@@ -420,7 +438,7 @@ public class Database {
420
438
  if (_db != null && _db.isOpen() && statement.length() > 0) {
421
439
  Integer initChanges = _uSqlite.dbChanges(_db);
422
440
  if (transaction) _db.beginTransaction();
423
- lastId = prepareSQL(statement, values);
441
+ lastId = prepareSQL(statement, values, false);
424
442
  if (lastId != -1 && transaction) _db.setTransactionSuccessful();
425
443
  changes = _uSqlite.dbChanges(_db) - initChanges;
426
444
  retObj.put("changes", changes);
@@ -438,15 +456,20 @@ public class Database {
438
456
 
439
457
  /**
440
458
  * PrepareSQL Method
459
+ *
441
460
  * @param statement
442
461
  * @param values
443
462
  * @return
444
463
  */
445
- public long prepareSQL(String statement, ArrayList<Object> values) throws Exception {
464
+ public long prepareSQL(String statement, ArrayList<Object> values, Boolean fromJson) throws Exception {
446
465
  String stmtType = statement.replaceAll("\n", "").trim().substring(0, 6).toUpperCase();
447
466
  SupportSQLiteStatement stmt = null;
467
+ String sqlStmt = statement;
448
468
  try {
449
- stmt = _db.compileStatement(statement);
469
+ if (!fromJson && stmtType.equals("DELETE")) {
470
+ sqlStmt = deleteSQL(this, statement, values);
471
+ }
472
+ stmt = _db.compileStatement(sqlStmt);
450
473
  if (values != null && values.size() > 0) {
451
474
  Object[] valObj = new Object[values.size()];
452
475
  for (int i = 0; i < values.size(); i++) {
@@ -481,9 +504,160 @@ public class Database {
481
504
  }
482
505
  }
483
506
 
507
+ /**
508
+ * DeleteSQL method
509
+ *
510
+ * @param mDB
511
+ * @param statement
512
+ * @param values
513
+ * @return
514
+ * @throws Exception
515
+ */
516
+ public String deleteSQL(Database mDB, String statement, ArrayList<Object> values) throws Exception {
517
+ String sqlStmt = statement;
518
+ try {
519
+ Boolean isLast = _uJson.isLastModified(mDB);
520
+ if (isLast) {
521
+ // Replace DELETE by UPDATE and set sql_deleted to 1
522
+ Integer wIdx = statement.toUpperCase().indexOf("WHERE");
523
+ String preStmt = statement.substring(0, wIdx - 1);
524
+ String clauseStmt = statement.substring(wIdx, statement.length());
525
+ String tableName = preStmt.substring(("DELETE FROM").length()).trim();
526
+ sqlStmt = "UPDATE " + tableName + " SET sql_deleted = 1 " + clauseStmt;
527
+ // Find REFERENCES if any and update the sql_deleted column
528
+ findReferencesAndUpdate(mDB, tableName, clauseStmt, values);
529
+ }
530
+ return sqlStmt;
531
+ } catch (Exception e) {
532
+ throw new Exception(e.getMessage());
533
+ }
534
+ }
535
+
536
+ /**
537
+ * FindReferencesAndUpdate method
538
+ *
539
+ * @param mDB
540
+ * @param tableName
541
+ * @param whereStmt
542
+ * @param values
543
+ * @throws Exception
544
+ */
545
+ public void findReferencesAndUpdate(Database mDB, String tableName, String whereStmt, ArrayList<Object> values) throws Exception {
546
+ try {
547
+ JSArray references = getReferences(mDB, tableName);
548
+ for (int j = 0; j < references.length(); j++) {
549
+ // get the tableName of the reference
550
+ String refTable = getReferenceTableName(references.getJSONObject(j).getString("sql"));
551
+ if (refTable.length() <= 0) {
552
+ continue;
553
+ }
554
+ // get the columnName
555
+ String colName = getReferenceColumnName(references.getJSONObject(j).getString("sql"));
556
+ if (refTable.length() <= 0) {
557
+ continue;
558
+ }
559
+ // update the where clause
560
+ String uWhereStmt = updateWhere(whereStmt, colName);
561
+
562
+ if (uWhereStmt.length() <= 0) {
563
+ continue;
564
+ }
565
+ //update sql_deleted for this reference
566
+ String stmt = "UPDATE " + refTable + " SET sql_deleted = 1 " + uWhereStmt;
567
+ long lastId = prepareSQL(stmt, values, false);
568
+ if (lastId == -1) {
569
+ String msg = "UPDATE sql_deleted failed for references " + "table: " + refTable + ";";
570
+ throw new Exception(msg);
571
+ }
572
+ }
573
+ return;
574
+ } catch (JSONException e) {
575
+ throw new Exception(e.getMessage());
576
+ } catch (Exception e) {
577
+ throw new Exception(e.getMessage());
578
+ }
579
+ }
580
+
581
+ /**
582
+ * GetReferenceTableName method
583
+ *
584
+ * @param refValue
585
+ * @return
586
+ */
587
+ public String getReferenceTableName(String refValue) {
588
+ String tableName = "";
589
+ if (refValue.length() > 0 && refValue.substring(0, 12).equalsIgnoreCase("CREATE TABLE")) {
590
+ Integer oPar = refValue.indexOf("(");
591
+ tableName = refValue.substring(13, oPar).trim();
592
+ }
593
+
594
+ return tableName;
595
+ }
596
+
597
+ /**
598
+ * GetReferenceColumnName method
599
+ *
600
+ * @param refValue
601
+ * @return
602
+ */
603
+ public String getReferenceColumnName(String refValue) {
604
+ String colName = "";
605
+ if (refValue.length() > 0) {
606
+ Integer index = refValue.toLowerCase().indexOf("FOREIGN KEY".toLowerCase());
607
+ String stmt = refValue.substring(index + 12);
608
+ Integer oPar = stmt.indexOf("(");
609
+ Integer cPar = stmt.indexOf(")");
610
+ colName = stmt.substring(oPar + 1, cPar).trim();
611
+ }
612
+ return colName;
613
+ }
614
+
615
+ /**
616
+ * UpdateWhere method
617
+ *
618
+ * @param whStmt
619
+ * @param colName
620
+ * @return
621
+ */
622
+ public String updateWhere(String whStmt, String colName) {
623
+ String whereStmt = "";
624
+ if (whStmt.length() > 0) {
625
+ Integer index = whStmt.toLowerCase().indexOf("WHERE".toLowerCase());
626
+ String stmt = whStmt.substring(index + 6);
627
+ Integer fEqual = stmt.indexOf("=");
628
+ String whereColName = stmt.substring(0, fEqual).trim();
629
+ whereStmt = whStmt.replaceFirst(whereColName, colName);
630
+ }
631
+ return whereStmt;
632
+ }
633
+
634
+ /**
635
+ * GetReferences method
636
+ *
637
+ * @param mDB
638
+ * @param tableName
639
+ * @return
640
+ * @throws Exception
641
+ */
642
+ public JSArray getReferences(Database mDB, String tableName) throws Exception {
643
+ String sqlStmt =
644
+ "SELECT sql FROM sqlite_master " +
645
+ "WHERE sql LIKE('%REFERENCES%') AND " +
646
+ "sql LIKE('%" +
647
+ tableName +
648
+ "%') AND sql LIKE('%ON DELETE%');";
649
+ try {
650
+ JSArray references = mDB.selectSQL(sqlStmt, new ArrayList<Object>());
651
+ return references;
652
+ } catch (Exception e) {
653
+ throw new Exception(e.getMessage());
654
+ }
655
+ }
656
+
484
657
  /**
485
658
  * SelectSQL Method
486
659
  * Query a raw sql statement with or without binding values
660
+ *
487
661
  * @param statement
488
662
  * @param values
489
663
  * @return
@@ -534,6 +708,7 @@ public class Database {
534
708
  /**
535
709
  * GetTableNames Method
536
710
  * Returned a JSArray of table's name
711
+ *
537
712
  * @return
538
713
  * @throws Exception
539
714
  */
@@ -553,6 +728,7 @@ public class Database {
553
728
  /**
554
729
  * DeleteDB Method
555
730
  * Delete the database file
731
+ *
556
732
  * @param dbName
557
733
  * @return
558
734
  */
@@ -584,6 +760,7 @@ public class Database {
584
760
  /**
585
761
  * CreateSyncTable Method
586
762
  * create the synchronization table
763
+ *
587
764
  * @return
588
765
  */
589
766
  public JSObject createSyncTable() throws Exception {
@@ -618,6 +795,7 @@ public class Database {
618
795
  /**
619
796
  * SetSyncDate Method
620
797
  * Set the synchronization date
798
+ *
621
799
  * @param syncDate
622
800
  * @return
623
801
  */
@@ -643,6 +821,13 @@ public class Database {
643
821
  }
644
822
  }
645
823
 
824
+ /**
825
+ * GetSyncDate method
826
+ * get the synchronization date
827
+ *
828
+ * @return
829
+ * @throws Exception
830
+ */
646
831
  public Long getSyncDate() throws Exception {
647
832
  long syncDate = 0;
648
833
  try {
@@ -659,6 +844,7 @@ public class Database {
659
844
 
660
845
  /**
661
846
  * Import from Json object
847
+ *
662
848
  * @param jsonSQL
663
849
  * @return
664
850
  */
@@ -666,6 +852,9 @@ public class Database {
666
852
  JSObject retObj = new JSObject();
667
853
  int changes = Integer.valueOf(0);
668
854
  try {
855
+ // set Foreign Keys OFF
856
+ _db.setForeignKeyConstraintsEnabled(false);
857
+
669
858
  if (jsonSQL.getTables().size() > 0) {
670
859
  // create the database schema
671
860
  changes = fromJson.createDatabaseSchema(this, jsonSQL);
@@ -676,6 +865,9 @@ public class Database {
676
865
  if (jsonSQL.getViews().size() > 0) {
677
866
  changes += fromJson.createViews(this, jsonSQL.getViews());
678
867
  }
868
+ // set Foreign Keys ON
869
+ _db.setForeignKeyConstraintsEnabled(true);
870
+
679
871
  retObj.put("changes", changes);
680
872
  return retObj;
681
873
  } catch (Exception e) {
@@ -685,6 +877,7 @@ public class Database {
685
877
 
686
878
  /**
687
879
  * Export to JSON Object
880
+ *
688
881
  * @param mode
689
882
  * @return
690
883
  */
@@ -696,6 +889,11 @@ public class Database {
696
889
  inJson.setEncrypted(_encrypted);
697
890
  inJson.setMode(mode);
698
891
  try {
892
+ // set the last export date
893
+ Date date = new Date();
894
+ long syncTime = date.getTime() / 1000L;
895
+ toJson.setLastExportDate(this, syncTime);
896
+ // launch the export process
699
897
  JsonSQLite retJson = toJson.createExportObject(this, inJson);
700
898
  // retJson.print();
701
899
  ArrayList<String> keys = retJson.getKeys();
@@ -717,4 +915,19 @@ public class Database {
717
915
  throw new Exception(e.getMessage());
718
916
  } finally {}
719
917
  }
918
+
919
+ /**
920
+ * Delete exported rows
921
+ *
922
+ * @throws Exception
923
+ */
924
+ public void deleteExportedRows() throws Exception {
925
+ try {
926
+ toJson.delExportedRows(this);
927
+ return;
928
+ } catch (Exception e) {
929
+ Log.e(TAG, "Error: exportToJson " + e.getMessage());
930
+ throw new Exception(e.getMessage());
931
+ }
932
+ }
720
933
  }