Skip to content

Commit

Permalink
I don't think it makes any sence to support pre-honeycomb code while …
Browse files Browse the repository at this point in the history
…react-native minimum API level is 16. It causes side effects for us in production (#147)
  • Loading branch information
dryganets authored and andpor committed Apr 15, 2017
1 parent e558bcd commit be972ed
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 329 deletions.
168 changes: 22 additions & 146 deletions src/android-native/src/main/java/io/liteglue/SQLiteAndroidDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import android.annotation.SuppressLint;

import android.database.Cursor;
import android.database.CursorWindow;
import android.database.sqlite.SQLiteCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteStatement;
Expand All @@ -38,14 +36,6 @@ class SQLiteAndroidDatabase {
private static final Pattern FIRST_WORD = Pattern.compile("^\\s*(\\S+)",
Pattern.CASE_INSENSITIVE);

private static final Pattern WHERE_CLAUSE = Pattern.compile("\\s+WHERE\\s+(.+)$",
Pattern.CASE_INSENSITIVE);

private static final Pattern UPDATE_TABLE_NAME = Pattern.compile("^\\s*UPDATE\\s+(\\S+)",
Pattern.CASE_INSENSITIVE);

private static final Pattern DELETE_TABLE_NAME = Pattern.compile("^\\s*DELETE\\s+FROM\\s+(\\S+)",
Pattern.CASE_INSENSITIVE);

File dbFile;
int openFlags;
Expand Down Expand Up @@ -129,37 +119,29 @@ void executeSqlBatch(String[] queryarr, JSONArray[] jsonparams,
QueryType queryType = getQueryType(query);

if (queryType == QueryType.update || queryType == QueryType.delete) {
if (android.os.Build.VERSION.SDK_INT >= 11) {
SQLiteStatement myStatement = mydb.compileStatement(query);

if (jsonparams != null) {
bindArgsToStatement(myStatement, jsonparams[i]);
}
SQLiteStatement myStatement = mydb.compileStatement(query);

int rowsAffected = -1; // (assuming invalid)

// Use try & catch just in case android.os.Build.VERSION.SDK_INT >= 11 is lying:
try {
rowsAffected = myStatement.executeUpdateDelete();
// Indicate valid results:
needRawQuery = false;
} catch (SQLiteException ex) {
// Indicate problem & stop this query:
errorMessage = ex.getMessage();
FLog.e(SQLitePlugin.TAG, "SQLiteStatement.executeUpdateDelete() failed", ex);
needRawQuery = false;
} catch (Exception ex) {
// Assuming SDK_INT was lying & method not found:
// do nothing here & try again with raw query.
}
if (jsonparams != null) {
bindArgsToStatement(myStatement, jsonparams[i]);
}

if (rowsAffected != -1) {
queryResult = new JSONObject();
queryResult.put("rowsAffected", rowsAffected);
}
} else { // pre-honeycomb
rowsAffectedCompat = countRowsAffectedCompat(queryType, query, jsonparams, mydb, i);
needRowsAffectedCompat = true;
int rowsAffected = -1; // (assuming invalid)

try {
rowsAffected = myStatement.executeUpdateDelete();
// Indicate valid results:
needRawQuery = false;
} catch (SQLiteException ex) {
// Indicate problem & stop this query:
errorMessage = ex.getMessage();
FLog.e(SQLitePlugin.TAG, "SQLiteStatement.executeUpdateDelete() failed", ex);
needRawQuery = false;
}

if (rowsAffected != -1) {
queryResult = new JSONObject();
queryResult.put("rowsAffected", rowsAffected);
}
}

Expand Down Expand Up @@ -273,81 +255,6 @@ void executeSqlBatch(String[] queryarr, JSONArray[] jsonparams,
cbc.success(batchResults);
}

private int countRowsAffectedCompat(QueryType queryType, String query, JSONArray[] jsonparams,
SQLiteDatabase mydb, int i) throws JSONException {
// quick and dirty way to calculate the rowsAffected in pre-Honeycomb. just do a SELECT
// beforehand using the same WHERE clause. might not be perfect, but it's better than nothing
Matcher whereMatcher = WHERE_CLAUSE.matcher(query);

String where = "";

int pos = 0;
while (whereMatcher.find(pos)) {
where = " WHERE " + whereMatcher.group(1);
pos = whereMatcher.start(1);
}
// WHERE clause may be omitted, and also be sure to find the last one,
// e.g. for cases where there's a subquery

// bindings may be in the update clause, so only take the last n
int numQuestionMarks = 0;
for (int j = 0; j < where.length(); j++) {
if (where.charAt(j) == '?') {
numQuestionMarks++;
}
}

JSONArray subParams = null;

if (jsonparams != null) {
// only take the last n of every array of sqlArgs
JSONArray origArray = jsonparams[i];
subParams = new JSONArray();
int startPos = origArray.length() - numQuestionMarks;
for (int j = startPos; j < origArray.length(); j++) {
subParams.put(j - startPos, origArray.get(j));
}
}

if (queryType == QueryType.update) {
Matcher tableMatcher = UPDATE_TABLE_NAME.matcher(query);
if (tableMatcher.find()) {
String table = tableMatcher.group(1);
try {
SQLiteStatement statement = mydb.compileStatement(
"SELECT count(*) FROM " + table + where);

if (subParams != null) {
bindArgsToStatement(statement, subParams);
}

return (int)statement.simpleQueryForLong();
} catch (Exception e) {
// assume we couldn't count for whatever reason, keep going
FLog.e(SQLitePlugin.TAG, "update query failed", e);
}
}
} else { // delete
Matcher tableMatcher = DELETE_TABLE_NAME.matcher(query);
if (tableMatcher.find()) {
String table = tableMatcher.group(1);
try {
SQLiteStatement statement = mydb.compileStatement(
"SELECT count(*) FROM " + table + where);
bindArgsToStatement(statement, subParams);

return (int)statement.simpleQueryForLong();
} catch (Exception e) {
// assume we couldn't count for whatever reason, keep going
FLog.e(SQLitePlugin.TAG, "delete table query failed", e);

}
}
}

return 0;
}

private void bindArgsToStatement(SQLiteStatement myStatement, JSONArray sqlArgs) throws JSONException {
for (int i = 0; i < sqlArgs.length(); i++) {
if (sqlArgs.get(i) instanceof Float || sqlArgs.get(i) instanceof Double) {
Expand Down Expand Up @@ -403,18 +310,7 @@ private JSONObject executeSqlStatementQuery(SQLiteDatabase mydb,
try {
for (int i = 0; i < colCount; ++i) {
key = cur.getColumnName(i);

if (android.os.Build.VERSION.SDK_INT >= 11) {

// Use try & catch just in case android.os.Build.VERSION.SDK_INT >= 11 is lying:
try {
bindPostHoneycomb(row, key, cur, i);
} catch (Exception ex) {
bindPreHoneycomb(row, key, cur, i);
}
} else {
bindPreHoneycomb(row, key, cur, i);
}
bindRow(row, key, cur, i);
}

rowsArrayResult.put(row);
Expand All @@ -439,7 +335,7 @@ private JSONObject executeSqlStatementQuery(SQLiteDatabase mydb,
}

@SuppressLint("NewApi")
private void bindPostHoneycomb(JSONObject row, String key, Cursor cur, int i) throws JSONException {
private void bindRow(JSONObject row, String key, Cursor cur, int i) throws JSONException {
int curType = cur.getType(i);

switch (curType) {
Expand All @@ -462,26 +358,6 @@ private void bindPostHoneycomb(JSONObject row, String key, Cursor cur, int i) th
}
}

private void bindPreHoneycomb(JSONObject row, String key, Cursor cursor, int i) throws JSONException {
// Since cursor.getType() is not available pre-honeycomb, this is
// a workaround so we don't have to bind everything as a string
// Details here: http://stackoverflow.com/q/11658239
SQLiteCursor sqLiteCursor = (SQLiteCursor) cursor;
CursorWindow cursorWindow = sqLiteCursor.getWindow();
int pos = cursor.getPosition();
if (cursorWindow.isNull(pos, i)) {
row.put(key, JSONObject.NULL);
} else if (cursorWindow.isLong(pos, i)) {
row.put(key, cursor.getLong(i));
} else if (cursorWindow.isFloat(pos, i)) {
row.put(key, cursor.getDouble(i));
} else if (cursorWindow.isBlob(pos, i)) {
row.put(key, new String(Base64.encode(cursor.getBlob(i), Base64.DEFAULT)));
} else { // string
row.put(key, cursor.getString(i));
}
}

static QueryType getQueryType(String query) {
Matcher matcher = FIRST_WORD.matcher(query);
if (matcher.find()) {
Expand Down
Loading

0 comments on commit be972ed

Please sign in to comment.