Skip to content

Commit 9302886

Browse files
committed
fix issue#504 & discussion#503
1 parent 7a1c4a6 commit 9302886

File tree

12 files changed

+404
-120
lines changed

12 files changed

+404
-120
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# 5.5.1 (2024-01-22)
2+
3+
### Bug Fixes
4+
5+
- Fix exportToJson getSchema Exception issue#504
6+
- Fix returning is treated as a keyword in a string object discussion#503
7+
18
# 5.5.1-4 (2023-12-30)
29

310
### Bug Fixes
0 Bytes
Binary file not shown.

android/src/main/java/com/getcapacitor/community/database/sqlite/SQLite/Database.java

Lines changed: 177 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.io.File;
2828
import java.text.SimpleDateFormat;
2929
import java.util.ArrayList;
30+
import java.util.Arrays;
3031
import java.util.Date;
3132
import java.util.Dictionary;
3233
import java.util.List;
@@ -641,71 +642,86 @@ public JSObject prepareSQL(String statement, ArrayList<Object> values, Boolean f
641642
String stmtType = statement.replaceAll("\n", "").trim().substring(0, 6).toUpperCase();
642643
SupportSQLiteStatement stmt = null;
643644
String sqlStmt = statement;
644-
String retMode = returnMode;
645+
String retMode;
645646
JSArray retValues = new JSArray();
646647
JSObject retObject = new JSObject();
647648
String colNames = "";
648649
long initLastId = (long) -1;
649-
boolean isReturning = sqlStmt.toUpperCase().contains("RETURNING");
650+
/* if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
651+
retMode = returnMode;
652+
throw new Exception(retMode +"Not implemented for above TIRAMISU");
653+
} else {
654+
655+
*/
656+
retMode = returnMode;
657+
if (!retMode.equals("no")) {
658+
retMode = "wA" + retMode;
659+
}
660+
// }
661+
if (retMode.equals("no") || retMode.substring(0, Math.min(retMode.length(), 2)).equals("wA")) {
662+
// get the statement and the returning column names
663+
try {
664+
JSObject stmtObj = getStmtAndRetColNames(sqlStmt, retMode);
665+
sqlStmt = stmtObj.getString("stmt", sqlStmt);
666+
colNames = stmtObj.getString("names","");
667+
} catch (JSONException e) {
668+
throw new Exception(e.getMessage());
669+
}
670+
}
650671
try {
651-
if (!fromJson && stmtType.equals("DELETE")) {
652-
sqlStmt = deleteSQL(this, statement, values);
653-
}
654-
if (isReturning && Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
655-
throw new Exception("Not implemented for above TIRAMISU");
656-
}
657-
if (isReturning) {
658-
// get the lastID
659-
initLastId = _uSqlite.dbLastId(_db);
660-
// get the statement and the returning column names
661-
JSObject stmtObj = getStmtAndRetColNames(sqlStmt);
662-
sqlStmt = stmtObj.getString("stmt");
663-
colNames = stmtObj.getString("names");
664-
}
665-
if (sqlStmt != null) {
672+
if (!fromJson && stmtType.equals("DELETE")) {
673+
sqlStmt = deleteSQL(this, sqlStmt, values);
674+
}
675+
if (sqlStmt != null) {
666676
stmt = _db.compileStatement(sqlStmt);
667-
} else {
668-
throw new Exception("sqlStmt is null");
669-
}
670-
if (values != null && values.size() > 0) {
671-
// retMode = "no";
672-
Object[] valObj = new Object[values.size()];
673-
for (int i = 0; i < values.size(); i++) {
674-
if (values.get(i) == null) {
675-
valObj[i] = null;
676-
} else if (JSONObject.NULL == values.get(i)) {
677-
valObj[i] = null;
678-
} else {
679-
valObj[i] = values.get(i);
680-
}
681-
}
682-
SimpleSQLiteQuery.bind(stmt, valObj);
677+
} else {
678+
throw new Exception("sqlStmt is null");
679+
}
680+
if (values != null && values.size() > 0) {
681+
// retMode = "no";
682+
Object[] valObj = new Object[values.size()];
683+
for (int i = 0; i < values.size(); i++) {
684+
if (values.get(i) == null) {
685+
valObj[i] = null;
686+
} else if (JSONObject.NULL == values.get(i)) {
687+
valObj[i] = null;
688+
} else {
689+
valObj[i] = values.get(i);
690+
}
691+
}
692+
SimpleSQLiteQuery.bind(stmt, valObj);
693+
}
694+
initLastId = _uSqlite.dbLastId(_db);
695+
if (stmtType.equals("INSERT")) {
696+
stmt.executeInsert();
697+
} else {
698+
if (retMode.startsWith("wA") && colNames.length() > 0 && stmtType.equals("DELETE")) {
699+
retValues = getUpdDelReturnedValues(this, sqlStmt, colNames);
683700
}
701+
stmt.executeUpdateDelete();
702+
}
703+
Long lastId = _uSqlite.dbLastId(_db);
704+
if (retMode.startsWith("wA") && colNames.length() > 0) {
684705
if (stmtType.equals("INSERT")) {
685-
stmt.executeInsert();
686-
} else {
687-
if (isReturning && stmtType.equals("DELETE")) {
688-
isReturning = false;
689-
retValues = getUpdDelReturnedValues(this, sqlStmt, colNames);
706+
String tableName = extractTableName(sqlStmt);
707+
if (tableName != null) {
708+
retValues = getInsertReturnedValues(this, colNames, tableName, initLastId, lastId, retMode);
690709
}
691-
stmt.executeUpdateDelete();
710+
} else if (stmtType.equals("UPDATE")) {
711+
retValues = getUpdDelReturnedValues(this, sqlStmt, colNames);
692712
}
693-
Long lastId = _uSqlite.dbLastId(_db);
694-
if (isReturning) {
695-
if (stmtType.equals("INSERT")) {
696-
String tableName = extractTableName(sqlStmt);
697-
if (tableName != null) {
698-
if (retMode.equals("one") || retMode.equals("all")) {
699-
retValues = getInsertReturnedValues(this, colNames, tableName, initLastId, lastId, retMode);
700-
}
701-
}
702-
} else if (stmtType.equals("UPDATE")) {
703-
retValues = getUpdDelReturnedValues(this, sqlStmt, colNames);
704-
}
713+
}
714+
/*
715+
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
716+
717+
if (retMode.startsWith("one") || retMode.startsWith("all")) {
718+
throw new Exception("returnMode : " + retMode + "Not implemented for above TIRAMISU");
705719
}
706-
retObject.put("lastId", lastId);
707-
retObject.put("values", retValues);
708-
return retObject;
720+
}
721+
*/
722+
retObject.put("lastId", lastId);
723+
retObject.put("values", retValues);
724+
return retObject;
709725
} catch (Exception e) {
710726
throw new Exception(e.getMessage());
711727
} finally {
@@ -715,18 +731,113 @@ public JSObject prepareSQL(String statement, ArrayList<Object> values, Boolean f
715731
}
716732
}
717733

718-
private JSObject getStmtAndRetColNames(String sqlStmt) {
734+
private JSObject getStmtAndRetColNames(String sqlStmt, String retMode) throws JSONException {
719735
JSObject retObj = new JSObject();
720-
int idx = sqlStmt.toUpperCase().indexOf("RETURNING");
721-
String retStmt = sqlStmt.substring(0, idx - 1) + ";";
722-
String names = sqlStmt.substring(idx + 9);
723-
String retNames = names;
724-
if (names.contains(";")) retNames = names.substring(0, names.length() - 1).trim();
725-
retObj.put("stmt", retStmt);
726-
retObj.put("names", retNames);
736+
JSObject retIsReturning = isReturning(sqlStmt);
737+
Boolean isReturning = retIsReturning.getBoolean("isReturning");
738+
String stmt = retIsReturning.getString("stmt");
739+
String suffix = retIsReturning.getString("names");
740+
retObj.put("stmt",stmt);
741+
retObj.put("names","");
742+
743+
if (isReturning && retMode.startsWith("wA")) {
744+
745+
String lowercaseSuffix = suffix != null ? suffix.toLowerCase() : "";
746+
int returningIndex = lowercaseSuffix.indexOf("returning");
747+
if (returningIndex != -1) {
748+
String substring = suffix.substring(returningIndex + "returning".length());
749+
String names = substring.trim();
750+
if (names.endsWith(";")) {
751+
retObj.put("names", names.substring(0, names.length() - 1));
752+
}
753+
}
754+
}
727755
return retObj;
728756
}
729757

758+
private JSObject isReturning(String sqlStmt) {
759+
JSObject retObj = new JSObject();
760+
761+
String stmt = sqlStmt.replace("\n", "").trim();
762+
if (stmt.endsWith(";")) {
763+
// Remove the suffix
764+
stmt = stmt.substring(0, stmt.length() - 1).trim();
765+
}
766+
retObj.put("isReturning",false);
767+
retObj.put("stmt",stmt);
768+
retObj.put("names","");
769+
770+
switch (stmt.substring(0, Math.min(stmt.length(), 6)).toUpperCase()) {
771+
case "INSERT":
772+
int valuesIndex = stmt.toUpperCase().indexOf("VALUES");
773+
if (valuesIndex != -1) {
774+
775+
int closingParenthesisIndex = -1;
776+
777+
for (int i = stmt.length() - 1; i >= valuesIndex; i--) {
778+
if (stmt.charAt(i) == ')') {
779+
closingParenthesisIndex = i;
780+
break;
781+
}
782+
}
783+
if (closingParenthesisIndex != -1) {
784+
String stmtString = stmt.substring(0, closingParenthesisIndex + 1).trim() + ";";
785+
String resultString = stmt.substring(closingParenthesisIndex + 1).trim();
786+
if (resultString.length() > 0 && !resultString.endsWith(";")) {
787+
resultString += ";";
788+
}
789+
if (resultString.toLowerCase().contains("returning")) {
790+
retObj.put("isReturning", true);
791+
retObj.put("stmt", stmtString);
792+
retObj.put("names", resultString);
793+
}
794+
}
795+
}
796+
return retObj;
797+
case "DELETE":
798+
case "UPDATE":
799+
String[] words = stmt.split("\\s+");
800+
List<String> wordsBeforeReturning = new ArrayList<>();
801+
List<String> returningString = new ArrayList<>();
802+
803+
boolean isReturningOutsideMessage = false;
804+
for (String word : words) {
805+
if (word.toLowerCase().equals("returning")) {
806+
isReturningOutsideMessage = true;
807+
// Include "RETURNING" and the words after it in returningString
808+
returningString.add(word);
809+
returningString.addAll(wordsAfter(word, words));
810+
break;
811+
}
812+
wordsBeforeReturning.add(word);
813+
}
814+
815+
if (isReturningOutsideMessage) {
816+
String joinedWords = String.join(" ", wordsBeforeReturning) + ";";
817+
String joinedReturningString = String.join(" ", returningString);
818+
if (joinedReturningString.length() > 0 && !joinedReturningString.endsWith(";")) {
819+
joinedReturningString += ";";
820+
}
821+
retObj.put("isReturning",true);
822+
retObj.put("stmt",joinedWords);
823+
retObj.put("names",joinedReturningString);
824+
return retObj;
825+
} else {
826+
return retObj;
827+
}
828+
default:
829+
return retObj;
830+
}
831+
}
832+
private List<String> wordsAfter(String word, String[] words) {
833+
List<String> mWords = Arrays.asList(words);
834+
int index = mWords.indexOf(word);
835+
if (index == -1) {
836+
return new ArrayList<>();
837+
}
838+
List<String> retWords = new ArrayList<>(mWords.subList(index + 1, mWords.size()));
839+
return retWords;
840+
}
730841
private JSArray getInsertReturnedValues(Database mDB, String colNames, String tableName, Long iLastId, Long lastId, String rMode)
731842
throws Exception {
732843
JSArray retVals = new JSArray();
@@ -735,10 +846,10 @@ private JSArray getInsertReturnedValues(Database mDB, String colNames, String ta
735846
StringBuilder sbQuery = new StringBuilder("SELECT ").append(colNames).append(" FROM ");
736847

737848
sbQuery.append(tableName).append(" WHERE ").append("rowid ");
738-
if (rMode.equals("one")) {
849+
if (rMode.equals("wAone")) {
739850
sbQuery.append("= ").append(sLastId);
740851
}
741-
if (rMode.equals("all")) {
852+
if (rMode.equals("wAall")) {
742853
sbQuery.append("BETWEEN ").append(sLastId).append(" AND ").append(lastId);
743854
}
744855
sbQuery.append(";");
@@ -1069,6 +1180,8 @@ public JSObject exportToJson(String mode, Boolean isEncrypted) throws Exception
10691180
Date date = new Date();
10701181
long syncTime = date.getTime() / 1000L;
10711182
toJson.setLastExportDate(this, syncTime);
1183+
} else {
1184+
throw new Exception("No sync_table available");
10721185
}
10731186
// launch the export process
10741187
JsonSQLite retJson = toJson.createExportObject(this, inJson);

electron/src/electron-utils/Database.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,10 @@ export class Database {
508508
/**
509509
* runSQL
510510
* execute a raw sql statement with/without binding values
511-
* @param sql: string
511+
* @param statement: string
512512
* @param values: string[]
513+
* @param transaction: boolean
514+
* @param returnMode: string
513515
* @param isSQL92: boolean,
514516
* @returns Promise<{changes:number, lastId:number}>
515517
*/
@@ -688,6 +690,8 @@ export class Database {
688690
this.database,
689691
new Date().toISOString(),
690692
);
693+
} else {
694+
throw new Error(`No sync_table available`);
691695
}
692696
let jsonResult: any = this.exportToJsonUtil.createExportObject(
693697
this.database,

0 commit comments

Comments
 (0)