package org.n0m.pawsqlite; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteStatement; import android.database.SQLException; import android.database.Cursor; class QueryWrapper { static enum QueryType { SELECT, INSERT, UPDATE, DELETE, BEGIN, COMMIT, ROLLBACK, OTHER } SQLiteDatabase db; String query; QueryType queryType; JSONArray args; public QueryWrapper(SQLiteDatabase db, String query, JSONArray args) { this.db = db; this.args = args; query = query.trim(); // Strip trailing semi-colon if (query.endsWith(";")) { query = query.substring(0, query.length() - 1); } String operation = query .replaceAll("[^a-zA-Z].*", "") .toUpperCase(); try { queryType = QueryType.valueOf(operation); } catch (IllegalArgumentException e) { queryType = QueryType.OTHER; } this.query = query; } public JSONObject execute() throws JSONException, SQLException { JSONObject result = new JSONObject(); result.put("query", query); result.put("args", args); switch (queryType) { case SELECT: executeRaw(result); break; case INSERT: executeInsert(result); break; case UPDATE: case DELETE: executeUpdateDelete(result); break; default: executeOther(result); break; } return result; } private JSONObject executeInsert(JSONObject result) throws JSONException, SQLException { SQLiteStatement statement = compileStatement(); long rowId = statement.executeInsert(); result.put("insertId", rowId); // Allow chaining return result; } private JSONObject executeUpdateDelete(JSONObject result) throws JSONException, SQLException { SQLiteStatement statement = compileStatement(); int rowsAffected = statement.executeUpdateDelete(); result.put("rowsAffected", rowsAffected); // Allow chaining return result; } private JSONObject executeOther(JSONObject result) throws JSONException, SQLException { SQLiteStatement statement = compileStatement(); statement.execute(); return result; } private SQLiteStatement compileStatement() throws JSONException, SQLException { SQLiteStatement statement = db.compileStatement(query); for (int i = 0; i < args.length(); i++) { if (args.get(i) instanceof Float || args.get(i) instanceof Double) { statement.bindDouble(i + 1, args.getDouble(i)); } else if (args.get(i) instanceof Number) { statement.bindLong(i + 1, args.getLong(i)); } else if (args.isNull(i)) { statement.bindNull(i + 1); } else { statement.bindString(i + 1, args.getString(i)); } } return statement; } private JSONObject executeRaw(JSONObject result) throws JSONException { String[] stringArgs = new String[args.length()]; for (int i = 0; i < args.length(); i++) { if (args.isNull(i)) { stringArgs[i] = ""; } else { stringArgs[i] = args.getString(i); } } Cursor cur = db.rawQuery(query, stringArgs); if (cur != null) { JSONArray rows = cursorToJSONArray(cur); result.put("rows", rows); cur.close(); } // Allow chaining return result; } private JSONArray cursorToJSONArray(Cursor cur) throws JSONException { JSONArray rows = new JSONArray(); if (cur != null && cur.moveToFirst()) { int colCount = cur.getColumnCount(); do { JSONObject row = new JSONObject(); for (int i = 0; i < colCount; i++) { String key = cur.getColumnName(i); switch(cur.getType(i)) { case Cursor.FIELD_TYPE_NULL: row.put(key, JSONObject.NULL); break; case Cursor.FIELD_TYPE_INTEGER: row.put(key, cur.getLong(i)); break; case Cursor.FIELD_TYPE_FLOAT: row.put(key, cur.getDouble(i)); break; case Cursor.FIELD_TYPE_STRING: case Cursor.FIELD_TYPE_BLOB: default: row.put(key, cur.getString(i)); break; } } rows.put(row); } while (cur.moveToNext()); } return rows; } }