Loading mobile/android/base/sqlite/SQLiteBridge.java +19 −50 Original line number Diff line number Diff line Loading @@ -30,20 +30,16 @@ public class 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; private long[] mQueryResults; private static final int RESULT_INSERT_ROW_ID = 0; private static final int RESULT_ROWS_CHANGED = 1; // JNI code in $(topdir)/mozglue/android/.. private static native void sqliteCall(String aDb, String aQuery, private static native MatrixBlobCursor sqliteCall(String aDb, String aQuery, String[] aParams, ArrayList<String> aColumns, Long[] aUpdateResult, ArrayList<Object[]> aRes) long[] aUpdateResult) throws SQLiteBridgeException; // Takes the path to the database we want to access. Loading Loading @@ -73,7 +69,7 @@ public class SQLiteBridge { } internalQuery(sb.toString(), whereArgs); return mQueryResults[kResultRowsChanged].intValue(); return (int)mQueryResults[RESULT_ROWS_CHANGED]; } public Cursor query(String table, Loading Loading @@ -119,22 +115,7 @@ public class SQLiteBridge { public Cursor rawQuery(String sql, String[] selectionArgs) throws SQLiteBridgeException { ArrayList<Object[]> results; results = internalQuery(sql, selectionArgs); MatrixBlobCursor cursor = new MatrixBlobCursor(mColumns.toArray(new String[0])); try { for (Object resultRow: results) { Object[] resultColumns = (Object[])resultRow; if (resultColumns.length == mColumns.size()) cursor.addRow(resultColumns); } } catch(IllegalArgumentException ex) { Log.e(LOGTAG, "Error getting rows", ex); } return cursor; return internalQuery(sql, selectionArgs); } public long insert(String table, String nullColumnHack, ContentValues values) Loading Loading @@ -167,7 +148,7 @@ public class SQLiteBridge { String[] binds = new String[valueBinds.size()]; valueBinds.toArray(binds); internalQuery(sb.toString(), binds); return mQueryResults[kResultInsertRowId]; return mQueryResults[RESULT_INSERT_ROW_ID]; } public int update(String table, ContentValues values, String whereClause, String[] whereArgs) Loading Loading @@ -202,40 +183,28 @@ public class SQLiteBridge { valueNames.toArray(binds); internalQuery(sb.toString(), binds); return mQueryResults[kResultRowsChanged].intValue(); return (int)mQueryResults[RESULT_ROWS_CHANGED]; } public int getVersion() throws SQLiteBridgeException { ArrayList<Object[]> results = null; results = internalQuery("PRAGMA user_version", null); Cursor cursor = internalQuery("PRAGMA user_version", null); int ret = -1; if (results != null) { for (Object resultRow: results) { Object[] resultColumns = (Object[])resultRow; String version = (String)resultColumns[0]; if (cursor != null) { cursor.moveToFirst(); String version = cursor.getString(0); ret = Integer.parseInt(version); } } return ret; } // 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). private ArrayList<Object[]> internalQuery(String aQuery, String[] aParams) private Cursor internalQuery(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, mQueryResults, result); return result; mQueryResults = new long[2]; return sqliteCall(mDb, aQuery, aParams, mQueryResults); } // nop, provided for API compatibility with SQLiteDatabase. Loading mozglue/android/SQLiteBridge.cpp +57 −46 Original line number Diff line number Diff line Loading @@ -95,13 +95,11 @@ void setup_sqlite_functions(void *sqlite_handle) static bool initialized = false; static jclass stringClass; static jclass objectClass; static jclass longClass; static jclass byteBufferClass; static jclass arrayListClass; static jclass cursorClass; static jmethodID jByteBufferAllocateDirect; static jmethodID jArrayListAdd; static jmethodID jLongConstructor; static jobject jNull; static jmethodID jCursorConstructor; static jmethodID jCursorAddRow; static void JNI_Throw(JNIEnv* jenv, const char* name, const char* msg) Loading @@ -125,14 +123,12 @@ JNI_Setup(JNIEnv* jenv) 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); cursorClass = jenv->FindClass("org/mozilla/gecko/sqlite/MatrixBlobCursor"); if (stringClass == NULL || objectClass == NULL || byteBufferClass == NULL || arrayListClass == NULL || longClass == NULL) { || byteBufferClass == NULL || cursorClass == NULL) { LOG("Error finding classes"); JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", "FindClass error"); Loading @@ -142,16 +138,16 @@ JNI_Setup(JNIEnv* jenv) // 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"); // new MatrixBlobCursor(String []) jCursorConstructor = jenv->GetMethodID(cursorClass, "<init>", "([Ljava/lang/String;)V"); // public void addRow (Object[] columnValues) jCursorAddRow = jenv->GetMethodID(cursorClass, "addRow", "([Ljava/lang/Object;)V"); if (jByteBufferAllocateDirect == NULL || jArrayListAdd == NULL || jLongConstructor == NULL) { || jCursorConstructor == NULL || jCursorAddRow == NULL) { LOG("Error finding methods"); JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", "GetMethodId error"); Loading @@ -161,17 +157,16 @@ JNI_Setup(JNIEnv* jenv) initialized = true; } extern "C" NS_EXPORT void JNICALL extern "C" NS_EXPORT jobject JNICALL Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, jstring jDb, jstring jQuery, jobjectArray jParams, jobject jColumns, jobjectArray jQueryRes, jobject jArrayList) jlongArray jQueryRes) { JNI_Setup(jenv); jobject jCursor = NULL; char* errorMsg; jsize numPars = 0; Loading Loading @@ -244,27 +239,44 @@ Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, goto error_close; } // Get the column names // Get the column count and names int cols; cols = f_sqlite3_column_count(ppStmt); { // Allocate a String[cols] jobjectArray jStringArray = jenv->NewObjectArray(cols, stringClass, NULL); if (jStringArray == NULL) { asprintf(&errorMsg, "Can't allocate String[]\n"); goto error_close; } // Assign column names to the String[] 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); jenv->SetObjectArrayElement(jStringArray, i, jStr); } // Construct the MatrixCursor(String[]) with given column names jCursor = jenv->NewObject(cursorClass, jCursorConstructor, jStringArray); if (jCursor == NULL) { asprintf(&errorMsg, "Can't allocate MatrixBlobCursor\n"); goto error_close; } } // 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); long changed = f_sqlite3_changes(db); jobject jChanged = jenv->NewObject(longClass, jLongConstructor, changed); jenv->SetObjectArrayElement(jQueryRes, 1, jChanged); jenv->DeleteLocalRef(jChanged); jlong id = f_sqlite3_last_insert_rowid(db); jenv->SetLongArrayRegion(jQueryRes, 0, 1, &id); jlong changed = f_sqlite3_changes(db); jenv->SetLongArrayRegion(jQueryRes, 1, 1, &changed); } // For each row, add an Object[] to the passed ArrayList, Loading Loading @@ -308,7 +320,7 @@ Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, jenv->SetObjectArrayElement(jRow, i, jByteBuffer); jenv->DeleteLocalRef(jByteBuffer); } else if (colType == SQLITE_NULL) { jenv->SetObjectArrayElement(jRow, i, jNull); jenv->SetObjectArrayElement(jRow, i, NULL); } else { // Treat everything else as text const char* txt = (const char*)f_sqlite3_column_text(ppStmt, i); Loading @@ -318,9 +330,8 @@ Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, } } // Append Object[] to ArrayList<Object[]> // JNI doesn't know about the generic, so use Object[] as Object jenv->CallBooleanMethod(jArrayList, jArrayListAdd, jRow); // Append Object[] to Cursor jenv->CallVoidMethod(jCursor, jCursorAddRow, jRow); // Clean up jenv->DeleteLocalRef(jRow); Loading @@ -341,12 +352,12 @@ Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, } f_sqlite3_close(db); return; return jCursor; error_close: f_sqlite3_close(db); LOG("Error in SQLiteBridge: %s\n", errorMsg); JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", errorMsg); free(errorMsg); return; return jCursor; } Loading
mobile/android/base/sqlite/SQLiteBridge.java +19 −50 Original line number Diff line number Diff line Loading @@ -30,20 +30,16 @@ public class 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; private long[] mQueryResults; private static final int RESULT_INSERT_ROW_ID = 0; private static final int RESULT_ROWS_CHANGED = 1; // JNI code in $(topdir)/mozglue/android/.. private static native void sqliteCall(String aDb, String aQuery, private static native MatrixBlobCursor sqliteCall(String aDb, String aQuery, String[] aParams, ArrayList<String> aColumns, Long[] aUpdateResult, ArrayList<Object[]> aRes) long[] aUpdateResult) throws SQLiteBridgeException; // Takes the path to the database we want to access. Loading Loading @@ -73,7 +69,7 @@ public class SQLiteBridge { } internalQuery(sb.toString(), whereArgs); return mQueryResults[kResultRowsChanged].intValue(); return (int)mQueryResults[RESULT_ROWS_CHANGED]; } public Cursor query(String table, Loading Loading @@ -119,22 +115,7 @@ public class SQLiteBridge { public Cursor rawQuery(String sql, String[] selectionArgs) throws SQLiteBridgeException { ArrayList<Object[]> results; results = internalQuery(sql, selectionArgs); MatrixBlobCursor cursor = new MatrixBlobCursor(mColumns.toArray(new String[0])); try { for (Object resultRow: results) { Object[] resultColumns = (Object[])resultRow; if (resultColumns.length == mColumns.size()) cursor.addRow(resultColumns); } } catch(IllegalArgumentException ex) { Log.e(LOGTAG, "Error getting rows", ex); } return cursor; return internalQuery(sql, selectionArgs); } public long insert(String table, String nullColumnHack, ContentValues values) Loading Loading @@ -167,7 +148,7 @@ public class SQLiteBridge { String[] binds = new String[valueBinds.size()]; valueBinds.toArray(binds); internalQuery(sb.toString(), binds); return mQueryResults[kResultInsertRowId]; return mQueryResults[RESULT_INSERT_ROW_ID]; } public int update(String table, ContentValues values, String whereClause, String[] whereArgs) Loading Loading @@ -202,40 +183,28 @@ public class SQLiteBridge { valueNames.toArray(binds); internalQuery(sb.toString(), binds); return mQueryResults[kResultRowsChanged].intValue(); return (int)mQueryResults[RESULT_ROWS_CHANGED]; } public int getVersion() throws SQLiteBridgeException { ArrayList<Object[]> results = null; results = internalQuery("PRAGMA user_version", null); Cursor cursor = internalQuery("PRAGMA user_version", null); int ret = -1; if (results != null) { for (Object resultRow: results) { Object[] resultColumns = (Object[])resultRow; String version = (String)resultColumns[0]; if (cursor != null) { cursor.moveToFirst(); String version = cursor.getString(0); ret = Integer.parseInt(version); } } return ret; } // 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). private ArrayList<Object[]> internalQuery(String aQuery, String[] aParams) private Cursor internalQuery(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, mQueryResults, result); return result; mQueryResults = new long[2]; return sqliteCall(mDb, aQuery, aParams, mQueryResults); } // nop, provided for API compatibility with SQLiteDatabase. Loading
mozglue/android/SQLiteBridge.cpp +57 −46 Original line number Diff line number Diff line Loading @@ -95,13 +95,11 @@ void setup_sqlite_functions(void *sqlite_handle) static bool initialized = false; static jclass stringClass; static jclass objectClass; static jclass longClass; static jclass byteBufferClass; static jclass arrayListClass; static jclass cursorClass; static jmethodID jByteBufferAllocateDirect; static jmethodID jArrayListAdd; static jmethodID jLongConstructor; static jobject jNull; static jmethodID jCursorConstructor; static jmethodID jCursorAddRow; static void JNI_Throw(JNIEnv* jenv, const char* name, const char* msg) Loading @@ -125,14 +123,12 @@ JNI_Setup(JNIEnv* jenv) 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); cursorClass = jenv->FindClass("org/mozilla/gecko/sqlite/MatrixBlobCursor"); if (stringClass == NULL || objectClass == NULL || byteBufferClass == NULL || arrayListClass == NULL || longClass == NULL) { || byteBufferClass == NULL || cursorClass == NULL) { LOG("Error finding classes"); JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", "FindClass error"); Loading @@ -142,16 +138,16 @@ JNI_Setup(JNIEnv* jenv) // 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"); // new MatrixBlobCursor(String []) jCursorConstructor = jenv->GetMethodID(cursorClass, "<init>", "([Ljava/lang/String;)V"); // public void addRow (Object[] columnValues) jCursorAddRow = jenv->GetMethodID(cursorClass, "addRow", "([Ljava/lang/Object;)V"); if (jByteBufferAllocateDirect == NULL || jArrayListAdd == NULL || jLongConstructor == NULL) { || jCursorConstructor == NULL || jCursorAddRow == NULL) { LOG("Error finding methods"); JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", "GetMethodId error"); Loading @@ -161,17 +157,16 @@ JNI_Setup(JNIEnv* jenv) initialized = true; } extern "C" NS_EXPORT void JNICALL extern "C" NS_EXPORT jobject JNICALL Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, jstring jDb, jstring jQuery, jobjectArray jParams, jobject jColumns, jobjectArray jQueryRes, jobject jArrayList) jlongArray jQueryRes) { JNI_Setup(jenv); jobject jCursor = NULL; char* errorMsg; jsize numPars = 0; Loading Loading @@ -244,27 +239,44 @@ Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, goto error_close; } // Get the column names // Get the column count and names int cols; cols = f_sqlite3_column_count(ppStmt); { // Allocate a String[cols] jobjectArray jStringArray = jenv->NewObjectArray(cols, stringClass, NULL); if (jStringArray == NULL) { asprintf(&errorMsg, "Can't allocate String[]\n"); goto error_close; } // Assign column names to the String[] 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); jenv->SetObjectArrayElement(jStringArray, i, jStr); } // Construct the MatrixCursor(String[]) with given column names jCursor = jenv->NewObject(cursorClass, jCursorConstructor, jStringArray); if (jCursor == NULL) { asprintf(&errorMsg, "Can't allocate MatrixBlobCursor\n"); goto error_close; } } // 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); long changed = f_sqlite3_changes(db); jobject jChanged = jenv->NewObject(longClass, jLongConstructor, changed); jenv->SetObjectArrayElement(jQueryRes, 1, jChanged); jenv->DeleteLocalRef(jChanged); jlong id = f_sqlite3_last_insert_rowid(db); jenv->SetLongArrayRegion(jQueryRes, 0, 1, &id); jlong changed = f_sqlite3_changes(db); jenv->SetLongArrayRegion(jQueryRes, 1, 1, &changed); } // For each row, add an Object[] to the passed ArrayList, Loading Loading @@ -308,7 +320,7 @@ Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, jenv->SetObjectArrayElement(jRow, i, jByteBuffer); jenv->DeleteLocalRef(jByteBuffer); } else if (colType == SQLITE_NULL) { jenv->SetObjectArrayElement(jRow, i, jNull); jenv->SetObjectArrayElement(jRow, i, NULL); } else { // Treat everything else as text const char* txt = (const char*)f_sqlite3_column_text(ppStmt, i); Loading @@ -318,9 +330,8 @@ Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, } } // Append Object[] to ArrayList<Object[]> // JNI doesn't know about the generic, so use Object[] as Object jenv->CallBooleanMethod(jArrayList, jArrayListAdd, jRow); // Append Object[] to Cursor jenv->CallVoidMethod(jCursor, jCursorAddRow, jRow); // Clean up jenv->DeleteLocalRef(jRow); Loading @@ -341,12 +352,12 @@ Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass, } f_sqlite3_close(db); return; return jCursor; error_close: f_sqlite3_close(db); LOG("Error in SQLiteBridge: %s\n", errorMsg); JNI_Throw(jenv, "org/mozilla/gecko/sqlite/SQLiteBridgeException", errorMsg); free(errorMsg); return; return jCursor; }