@capacitor-community/sqlite 3.4.2 → 3.4.3-3
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 +42 -2
- 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 +100 -3
- package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/ImportExportJson/ImportFromJson.java +37 -34
- 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 +9 -17
- 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 +273 -466
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +1036 -1229
- package/dist/plugin.js.map +1 -1
- package/electron/dist/plugin.js +1147 -1032
- 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 +154 -25
- package/ios/Plugin/ImportExportJson/ImportFromJson.swift +53 -27
- package/ios/Plugin/Utils/UtilsDrop.swift +2 -2
- package/ios/Plugin/Utils/UtilsSQLCipher.swift +277 -8
- package/ios/Plugin/Utils/UtilsUpgrade.swift +33 -13
- 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/
|
|
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-
|
|
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-3 all platforms ->> 🚨
|
|
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-3 <<- 🚨
|
|
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)
|
|
@@ -423,6 +461,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|
|
423
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>
|
|
424
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>
|
|
425
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>
|
|
426
466
|
</tr>
|
|
427
467
|
</table>
|
|
428
468
|
|
package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLite.java
CHANGED
|
@@ -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
|
-
|
|
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 {
|
package/android/src/main/java/com/getcapacitor/community/database/sqlite/CapacitorSQLitePlugin.java
CHANGED
|
@@ -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
|
package/android/src/main/java/com/getcapacitor/community/database/sqlite/NotificationCenter.java
CHANGED
|
@@ -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
|
}
|
package/android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/Database.java
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
}
|