This repository has been archived on 2023-11-19. You can view files and clone it, but cannot push or open issues or pull requests.
goober-ionic/platforms/android/app/src/main/java/io/sqlc/SQLiteConnectorDatabase.java

287 lines
9.1 KiB
Java

/*
* Copyright (c) 2012-present Christopher J. Brody (aka Chris Brody)
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
*/
package io.sqlc;
import android.annotation.SuppressLint;
import android.util.Log;
import java.io.File;
import java.lang.IllegalArgumentException;
import java.lang.Number;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import io.liteglue.SQLCode;
import io.liteglue.SQLColumnType;
import io.liteglue.SQLiteConnector;
import io.liteglue.SQLiteConnection;
import io.liteglue.SQLiteOpenFlags;
import io.liteglue.SQLiteStatement;
/**
* Android SQLite-Connector Database helper class
*/
class SQLiteConnectorDatabase extends SQLiteAndroidDatabase
{
static SQLiteConnector connector = new SQLiteConnector();
SQLiteConnection mydb;
/**
* NOTE: Using default constructor, no explicit constructor.
*/
/**
* Open a database.
*
* @param dbFile The database File specification
*/
@Override
void open(File dbFile) throws Exception {
mydb = connector.newSQLiteConnection(dbFile.getAbsolutePath(),
SQLiteOpenFlags.READWRITE | SQLiteOpenFlags.CREATE);
}
/**
* Close a database (in the current thread).
*/
@Override
void closeDatabaseNow() {
try {
if (mydb != null)
mydb.dispose();
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database, ignoring", e);
}
}
/**
* Ignore Android bug workaround for NDK version
*/
@Override
void bugWorkaround() { }
/**
* Executes a batch request and sends the results via cbc.
*
* @param dbname The name of the database.
* @param queryarr Array of query strings
* @param jsonparams Array of JSON query parameters
* @param cbc Callback context from Cordova API
*/
@Override
void executeSqlBatch( String[] queryarr, JSONArray[] jsonparams, CallbackContext cbc) {
if (mydb == null) {
// not allowed - can only happen if someone has closed (and possibly deleted) a database and then re-used the database
cbc.error("database has been closed");
return;
}
int len = queryarr.length;
JSONArray batchResults = new JSONArray();
for (int i = 0; i < len; i++) {
int rowsAffectedCompat = 0;
boolean needRowsAffectedCompat = false;
JSONObject queryResult = null;
String errorMessage = "unknown";
int sqliteErrorCode = -1;
int code = 0; // SQLException.UNKNOWN_ERR
try {
String query = queryarr[i];
long lastTotal = mydb.getTotalChanges();
queryResult = this.executeSQLiteStatement(query, jsonparams[i], cbc);
long newTotal = mydb.getTotalChanges();
long rowsAffected = newTotal - lastTotal;
queryResult.put("rowsAffected", rowsAffected);
if (rowsAffected > 0) {
long insertId = mydb.getLastInsertRowid();
if (insertId > 0) {
queryResult.put("insertId", insertId);
}
}
} catch (SQLException ex) {
ex.printStackTrace();
sqliteErrorCode = ex.getErrorCode();
errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): SQL Error code = " + sqliteErrorCode + " message = " + errorMessage);
switch(sqliteErrorCode) {
case SQLCode.ERROR:
code = 5; // SQLException.SYNTAX_ERR
break;
case 13: // SQLITE_FULL
code = 4; // SQLException.QUOTA_ERR
break;
case SQLCode.CONSTRAINT:
code = 6; // SQLException.CONSTRAINT_ERR
break;
default:
/* do nothing */
}
} catch (JSONException ex) {
// NOT expected:
ex.printStackTrace();
errorMessage = ex.getMessage();
code = 0; // SQLException.UNKNOWN_ERR
Log.e("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): UNEXPECTED JSON Error=" + errorMessage);
}
try {
if (queryResult != null) {
JSONObject r = new JSONObject();
r.put("type", "success");
r.put("result", queryResult);
batchResults.put(r);
} else {
JSONObject r = new JSONObject();
r.put("type", "error");
JSONObject er = new JSONObject();
er.put("message", errorMessage);
er.put("code", code);
r.put("result", er);
batchResults.put(r);
}
} catch (JSONException ex) {
ex.printStackTrace();
Log.e("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + ex.getMessage());
// TODO what to do?
}
}
cbc.success(batchResults);
}
/**
* Get rows results from query cursor.
*
* @param cur Cursor into query results
* @return results in string form
*/
private JSONObject executeSQLiteStatement(String query, JSONArray paramsAsJson,
CallbackContext cbc) throws JSONException, SQLException {
JSONObject rowsResult = new JSONObject();
boolean hasRows = false;
SQLiteStatement myStatement = mydb.prepareStatement(query);
try {
String[] params = null;
params = new String[paramsAsJson.length()];
for (int i = 0; i < paramsAsJson.length(); ++i) {
if (paramsAsJson.isNull(i)) {
myStatement.bindNull(i + 1);
} else {
Object p = paramsAsJson.get(i);
if (p instanceof Float || p instanceof Double)
myStatement.bindDouble(i + 1, paramsAsJson.getDouble(i));
else if (p instanceof Number)
myStatement.bindLong(i + 1, paramsAsJson.getLong(i));
else
myStatement.bindTextNativeString(i + 1, paramsAsJson.getString(i));
}
}
hasRows = myStatement.step();
} catch (SQLException ex) {
ex.printStackTrace();
String errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + errorMessage);
// cleanup statement and throw the exception:
myStatement.dispose();
throw ex;
} catch (JSONException ex) {
ex.printStackTrace();
String errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + errorMessage);
// cleanup statement and throw the exception:
myStatement.dispose();
throw ex;
}
// If query result has rows
if (hasRows) {
JSONArray rowsArrayResult = new JSONArray();
String key = "";
int colCount = myStatement.getColumnCount();
// Build up JSON result object for each row
do {
JSONObject row = new JSONObject();
try {
for (int i = 0; i < colCount; ++i) {
key = myStatement.getColumnName(i);
switch (myStatement.getColumnType(i)) {
case SQLColumnType.NULL:
row.put(key, JSONObject.NULL);
break;
case SQLColumnType.REAL:
row.put(key, myStatement.getColumnDouble(i));
break;
case SQLColumnType.INTEGER:
row.put(key, myStatement.getColumnLong(i));
break;
case SQLColumnType.BLOB:
case SQLColumnType.TEXT:
default: // (just in case)
row.put(key, myStatement.getColumnTextNativeString(i));
}
}
rowsArrayResult.put(row);
} catch (JSONException e) {
e.printStackTrace();
}
} while (myStatement.step());
try {
rowsResult.put("rows", rowsArrayResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
myStatement.dispose();
return rowsResult;
}
} /* vim: set expandtab : */