author | Gian-Carlo Pascutto <gpascutto@mozilla.com> |
Mon, 27 Feb 2012 12:28:21 +0100 | |
changeset 87831 | ff36792efde97c8409f92fa4ad5644a9caa6a9ef |
parent 87815 | 86f8ab61e7558e76cbf810e532fcc9bafd165942 |
child 87832 | 3e6935243310b57940c140238306dab8fefafa51 |
push id | 22160 |
push user | mbrubeck@mozilla.com |
push date | Tue, 28 Feb 2012 17:21:33 +0000 |
treeherder | mozilla-central@dde4e0089a18 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | blassey |
bugs | 727264 |
milestone | 13.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
mobile/android/base/sqlite/SQLiteBridge.java | file | annotate | diff | comparison | revisions | |
mozglue/android/SQLiteBridge.cpp | file | annotate | diff | comparison | revisions |
--- a/mobile/android/base/sqlite/SQLiteBridge.java +++ b/mobile/android/base/sqlite/SQLiteBridge.java @@ -21,67 +21,64 @@ import java.util.Set; /* * This class allows using the mozsqlite3 library included with Firefox * to read SQLite databases, instead of the Android SQLiteDataBase API, * which might use whatever outdated DB is present on the Android system. */ public class SQLiteBridge { private static final String LOGTAG = "SQLiteBridge"; + // Path to the database. We reopen it every query. private String mDb; + // Remember column names from last query result. private ArrayList<String> mColumns; + private Long[] mQueryResults; + + // Values remembered after a query. + private int kResultInsertRowId = 0; + private int kResultRowsChanged = 1; // JNI code in $(topdir)/mozglue/android/.. private static native void sqliteCall(String aDb, String aQuery, String[] aParams, ArrayList<String> aColumns, + Long[] aUpdateResult, ArrayList<Object[]> aRes) throws SQLiteBridgeException; // Takes the path to the database we want to access. public SQLiteBridge(String aDb) throws SQLiteBridgeException { mDb = aDb; } // Executes a simple line of sql. public void execSQL(String sql) throws SQLiteBridgeException { - try { - query(sql, null); - } catch(SQLiteBridgeException ex) { - throw ex; - } + query(sql, null); } // Executes a simple line of sql. Allow you to bind arguments public void execSQL(String sql, String[] bindArgs) throws SQLiteBridgeException { - try { - query(sql, bindArgs); - } catch(SQLiteBridgeException ex) { - throw ex; - } + query(sql, bindArgs); } // Executes a DELETE statement on the database public int delete(String table, String whereClause, String[] whereArgs) throws SQLiteBridgeException { StringBuilder sb = new StringBuilder("DELETE from "); sb.append(table); if (whereClause != null) { sb.append(" WHERE " + whereClause); } - try { - return getIntResult(sb.toString(), whereArgs, 1); - } catch(SQLiteBridgeException ex) { - throw ex; - } + query(sb.toString(), whereArgs); + return mQueryResults[kResultRowsChanged].intValue(); } public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, @@ -113,24 +110,17 @@ public class SQLiteBridge { sb.append(" ORDER BY " + orderBy); } if (limit != null) { sb.append(" " + limit); } ArrayList<Object[]> results; - try { - mColumns = null; - - results = query(sb.toString(), selectionArgs); - - } catch(SQLiteBridgeException ex) { - throw ex; - } + results = query(sb.toString(), selectionArgs); MatrixCursor cursor = new MatrixCursor(mColumns.toArray(new String[0])); try { for (Object resultRow: results) { Object[] resultColumns = (Object[])resultRow; if (resultColumns.length == mColumns.size()) cursor.addRow(resultColumns); } @@ -165,21 +155,18 @@ public class SQLiteBridge { // XXX - Do we need to bind these values? sb.append(" VALUES ("); sb.append(TextUtils.join(", ", valueNames)); sb.append(") "); String[] binds = new String[valueBinds.size()]; valueBinds.toArray(binds); - try { - return getIntResult(sb.toString(), binds, 0); - } catch (SQLiteBridgeException ex) { - throw ex; - } + query(sb.toString(), binds); + return mQueryResults[kResultInsertRowId]; } public int update(String table, ContentValues values, String whereClause, String[] whereArgs) throws SQLiteBridgeException { Set<Entry<String, Object>> valueSet = values.valueSet(); Iterator<Entry<String, Object>> valueIterator = valueSet.iterator(); ArrayList<String> valueNames = new ArrayList<String>(); @@ -202,81 +189,56 @@ public class SQLiteBridge { sb.append(whereClause); for (int i = 0; i < whereArgs.length; i++) { valueNames.add(whereArgs[i]); } } String[] binds = new String[valueNames.size()]; valueNames.toArray(binds); - try { - return getIntResult(sb.toString(), binds, 1); - } catch (SQLiteBridgeException ex) { - throw ex; - } - } - private int getIntResult(String query, String[] params, int resultIndex) - throws SQLiteBridgeException { - ArrayList<Object[]> results = null; - try { - mColumns = null; - results = query(query, params); - } catch(SQLiteBridgeException ex) { - throw ex; - } - - if (results != null) { - for (Object resultRow: results) { - Object[] resultColumns = (Object[])resultRow; - return ((Number)resultColumns[resultIndex]).intValue(); - } - } - return -1; + query(sb.toString(), binds); + return mQueryResults[kResultRowsChanged].intValue(); } public int getVersion() throws SQLiteBridgeException { ArrayList<Object[]> results = null; - try { - mColumns = null; - results = query("PRAGMA user_version"); - } catch(SQLiteBridgeException ex) { - throw ex; - } + results = query("PRAGMA user_version"); int ret = -1; if (results != null) { for (Object resultRow: results) { Object[] resultColumns = (Object[])resultRow; String version = (String)resultColumns[0]; ret = Integer.parseInt(version); } } return ret; } - // Do an SQL query without parameters public ArrayList<Object[]> query(String aQuery) throws SQLiteBridgeException { - String[] params = new String[0]; - return query(aQuery, params); + return query(aQuery, null); } // Do an SQL query, substituting the parameters in the query with the passed // parameters. The parameters are subsituded in order, so named parameters // are not supported. // The result is returned as an ArrayList<Object[]>, with each // row being an entry in the ArrayList, and each column being one Object // in the Object[] array. The columns are of type null, // direct ByteBuffer (BLOB), or String (everything else). public ArrayList<Object[]> query(String aQuery, String[] aParams) throws SQLiteBridgeException { ArrayList<Object[]> result = new ArrayList<Object[]>(); + mQueryResults = new Long[2]; mColumns = new ArrayList<String>(); - sqliteCall(mDb, aQuery, aParams, mColumns, result); + + sqliteCall(mDb, aQuery, aParams, mColumns, mQueryResults, result); + return result; } // Gets the index in the row Object[] for the given column name. // Returns -1 if not found. public int getColumnIndex(String aColumnName) { return mColumns.lastIndexOf(aColumnName); }
--- a/mozglue/android/SQLiteBridge.cpp +++ b/mozglue/android/SQLiteBridge.cpp @@ -90,20 +90,22 @@ void setup_sqlite_functions(void *sqlite GETFUNC(sqlite3_changes); GETFUNC(sqlite3_last_insert_rowid); #undef GETFUNC } static bool initialized = false; static jclass stringClass; static jclass objectClass; +static jclass longClass; static jclass byteBufferClass; static jclass arrayListClass; static jmethodID jByteBufferAllocateDirect; static jmethodID jArrayListAdd; +static jmethodID jLongConstructor; static jobject jNull; static void JNI_Throw(JNIEnv* jenv, const char* name, const char* msg) { jclass cls = jenv->FindClass(name); if (cls == NULL) { LOG("Couldn't find exception class (or exception pending)\n"); @@ -118,51 +120,59 @@ JNI_Throw(JNIEnv* jenv, const char* name static void JNI_Setup(JNIEnv* jenv) { if (initialized) return; objectClass = jenv->FindClass("java/lang/Object"); stringClass = jenv->FindClass("java/lang/String"); + longClass = jenv->FindClass("java/lang/Long"); byteBufferClass = jenv->FindClass("java/nio/ByteBuffer"); arrayListClass = jenv->FindClass("java/util/ArrayList"); jNull = jenv->NewGlobalRef(NULL); if (stringClass == NULL || objectClass == NULL - || byteBufferClass == NULL || arrayListClass == NULL) { + || byteBufferClass == NULL || arrayListClass == NULL + || longClass == NULL) { LOG("Error finding classes"); JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", "FindClass error"); return; } // public static ByteBuffer allocateDirect(int capacity) jByteBufferAllocateDirect = jenv->GetStaticMethodID(byteBufferClass, "allocateDirect", "(I)Ljava/nio/ByteBuffer;"); // boolean add(Object o) jArrayListAdd = jenv->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z"); + // new Long(long i) + jLongConstructor = + jenv->GetMethodID(longClass, "<init>", "(J)V"); - if (jByteBufferAllocateDirect == NULL || jArrayListAdd == NULL) { + if (jByteBufferAllocateDirect == NULL + || jArrayListAdd == NULL + || jLongConstructor == NULL) { LOG("Error finding methods"); JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", "GetMethodId error"); return; } initialized = true; } extern "C" NS_EXPORT void JNICALL Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, jstring jDb, jstring jQuery, jobjectArray jParams, jobject jColumns, + jobjectArray jQueryRes, jobject jArrayList) { JNI_Setup(jenv); char* errorMsg; jsize numPars = 0; const char* queryStr; @@ -239,39 +249,27 @@ Java_org_mozilla_gecko_sqlite_SQLiteBrid cols = f_sqlite3_column_count(ppStmt); for (int i = 0; i < cols; i++) { const char* colName = f_sqlite3_column_name(ppStmt, i); jstring jStr = jenv->NewStringUTF(colName); jenv->CallBooleanMethod(jColumns, jArrayListAdd, jStr); jenv->DeleteLocalRef(jStr); } - // if the statement doesn't return any results, instead return the id and number of changed rows - if (rc == SQLITE_DONE) { - jclass integerClass = jenv->FindClass("java/lang/Integer"); - jmethodID intConstructor = jenv->GetMethodID(integerClass, "<init>", "(I)V"); - - jobjectArray jRow = jenv->NewObjectArray(2, objectClass, NULL); - if (jRow == NULL) { - asprintf(&errorMsg, "Can't allocate jRow Object[]\n"); - goto error_close; - } - - int id = f_sqlite3_last_insert_rowid(db); - jobject jId = jenv->NewObject(integerClass, intConstructor, id); - jenv->SetObjectArrayElement(jRow, 0, jId); + // Return the id and number of changed rows in jQueryRes + { + long id = f_sqlite3_last_insert_rowid(db); + jobject jId = jenv->NewObject(longClass, jLongConstructor, id); + jenv->SetObjectArrayElement(jQueryRes, 0, jId); jenv->DeleteLocalRef(jId); - int changed = f_sqlite3_changes(db); - jobject jChanged = jenv->NewObject(integerClass, intConstructor, changed); - jenv->SetObjectArrayElement(jRow, 1, jChanged); + long changed = f_sqlite3_changes(db); + jobject jChanged = jenv->NewObject(longClass, jLongConstructor, changed); + jenv->SetObjectArrayElement(jQueryRes, 1, jChanged); jenv->DeleteLocalRef(jChanged); - - jenv->CallBooleanMethod(jArrayList, jArrayListAdd, jRow); - jenv->DeleteLocalRef(jRow); } // For each row, add an Object[] to the passed ArrayList, // with that containing either String or ByteArray objects // containing the columns while (rc != SQLITE_DONE) { // Process row // Construct Object[]