summaryrefslogtreecommitdiffstats
path: root/core/jni/android_database_SQLiteDatabase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/jni/android_database_SQLiteDatabase.cpp')
-rw-r--r--core/jni/android_database_SQLiteDatabase.cpp636
1 files changed, 0 insertions, 636 deletions
diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp
deleted file mode 100644
index 28c421d..0000000
--- a/core/jni/android_database_SQLiteDatabase.cpp
+++ /dev/null
@@ -1,636 +0,0 @@
-/*
- * Copyright (C) 2006-2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#undef LOG_TAG
-#define LOG_TAG "SqliteDatabaseCpp"
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
-
-#include <jni.h>
-#include <JNIHelp.h>
-#include <android_runtime/AndroidRuntime.h>
-
-#include <sqlite3.h>
-#include <sqlite3_android.h>
-#include <string.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <utils/List.h>
-#include <utils/Errors.h>
-#include <ctype.h>
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <netdb.h>
-#include <sys/ioctl.h>
-
-#include "sqlite3_exception.h"
-
-#define UTF16_STORAGE 0
-#define INVALID_VERSION -1
-#define ANDROID_TABLE "android_metadata"
-/* uncomment the next line to force-enable logging of all statements */
-// #define DB_LOG_STATEMENTS
-
-#define DEBUG_JNI 0
-
-namespace android {
-
-enum {
- OPEN_READWRITE = 0x00000000,
- OPEN_READONLY = 0x00000001,
- OPEN_READ_MASK = 0x00000001,
- NO_LOCALIZED_COLLATORS = 0x00000010,
- CREATE_IF_NECESSARY = 0x10000000
-};
-
-static jfieldID offset_db_handle;
-static jmethodID method_custom_function_callback;
-static jclass string_class;
-static jint sSqliteSoftHeapLimit = 0;
-
-static char *createStr(const char *path, short extra) {
- int len = strlen(path) + extra;
- char *str = (char *)malloc(len + 1);
- strncpy(str, path, len);
- str[len] = NULL;
- return str;
-}
-
-static void sqlLogger(void *databaseName, int iErrCode, const char *zMsg) {
- // skip printing this message if it is due to certain types of errors
- if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT) return;
- // print databasename, errorcode and msg
- ALOGI("sqlite returned: error code = %d, msg = %s, db=%s\n", iErrCode, zMsg, databaseName);
-}
-
-// register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called.
-static void registerLoggingFunc(const char *path) {
- static bool loggingFuncSet = false;
- if (loggingFuncSet) {
- return;
- }
-
- ALOGV("Registering sqlite logging func \n");
- int err = sqlite3_config(SQLITE_CONFIG_LOG, &sqlLogger, (void *)createStr(path, 0));
- if (err != SQLITE_OK) {
- ALOGW("sqlite returned error = %d when trying to register logging func.\n", err);
- return;
- }
- loggingFuncSet = true;
-}
-
-/* public native void dbopen(String path, int flags, String locale); */
-static void dbopen(JNIEnv* env, jobject object, jstring pathString, jint flags)
-{
- int err;
- sqlite3 * handle = NULL;
- sqlite3_stmt * statement = NULL;
- char const * path8 = env->GetStringUTFChars(pathString, NULL);
- int sqliteFlags;
-
- // register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called.
- registerLoggingFunc(path8);
-
- // convert our flags into the sqlite flags
- if (flags & CREATE_IF_NECESSARY) {
- sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
- } else if (flags & OPEN_READONLY) {
- sqliteFlags = SQLITE_OPEN_READONLY;
- } else {
- sqliteFlags = SQLITE_OPEN_READWRITE;
- }
-
- err = sqlite3_open_v2(path8, &handle, sqliteFlags, NULL);
- if (err != SQLITE_OK) {
- ALOGE("sqlite3_open_v2(\"%s\", &handle, %d, NULL) failed\n", path8, sqliteFlags);
- throw_sqlite3_exception(env, handle);
- goto done;
- }
-
- // The soft heap limit prevents the page cache allocations from growing
- // beyond the given limit, no matter what the max page cache sizes are
- // set to. The limit does not, as of 3.5.0, affect any other allocations.
- sqlite3_soft_heap_limit(sSqliteSoftHeapLimit);
-
- // Set the default busy handler to retry for 1000ms and then return SQLITE_BUSY
- err = sqlite3_busy_timeout(handle, 1000 /* ms */);
- if (err != SQLITE_OK) {
- ALOGE("sqlite3_busy_timeout(handle, 1000) failed for \"%s\"\n", path8);
- throw_sqlite3_exception(env, handle);
- goto done;
- }
-
-#ifdef DB_INTEGRITY_CHECK
- static const char* integritySql = "pragma integrity_check(1);";
- err = sqlite3_prepare_v2(handle, integritySql, -1, &statement, NULL);
- if (err != SQLITE_OK) {
- ALOGE("sqlite_prepare_v2(handle, \"%s\") failed for \"%s\"\n", integritySql, path8);
- throw_sqlite3_exception(env, handle);
- goto done;
- }
-
- // first is OK or error message
- err = sqlite3_step(statement);
- if (err != SQLITE_ROW) {
- ALOGE("integrity check failed for \"%s\"\n", integritySql, path8);
- throw_sqlite3_exception(env, handle);
- goto done;
- } else {
- const char *text = (const char*)sqlite3_column_text(statement, 0);
- if (strcmp(text, "ok") != 0) {
- ALOGE("integrity check failed for \"%s\": %s\n", integritySql, path8, text);
- jniThrowException(env, "android/database/sqlite/SQLiteDatabaseCorruptException", text);
- goto done;
- }
- }
-#endif
-
- err = register_android_functions(handle, UTF16_STORAGE);
- if (err) {
- throw_sqlite3_exception(env, handle);
- goto done;
- }
-
- ALOGV("Opened '%s' - %p\n", path8, handle);
- env->SetIntField(object, offset_db_handle, (int) handle);
- handle = NULL; // The caller owns the handle now.
-
-done:
- // Release allocated resources
- if (path8 != NULL) env->ReleaseStringUTFChars(pathString, path8);
- if (statement != NULL) sqlite3_finalize(statement);
- if (handle != NULL) sqlite3_close(handle);
-}
-
-static char *getDatabaseName(JNIEnv* env, sqlite3 * handle, jstring databaseName, short connNum) {
- char const *path = env->GetStringUTFChars(databaseName, NULL);
- if (path == NULL) {
- ALOGE("Failure in getDatabaseName(). VM ran out of memory?\n");
- return NULL; // VM would have thrown OutOfMemoryError
- }
- char *dbNameStr = createStr(path, 4);
- if (connNum > 999) { // TODO: if number of pooled connections > 999, fix this line.
- connNum = -1;
- }
- sprintf(dbNameStr + strlen(path), "|%03d", connNum);
- env->ReleaseStringUTFChars(databaseName, path);
- return dbNameStr;
-}
-
-static void sqlTrace(void *databaseName, const char *sql) {
- ALOGI("sql_statement|%s|%s\n", (char *)databaseName, sql);
-}
-
-/* public native void enableSqlTracing(); */
-static void enableSqlTracing(JNIEnv* env, jobject object, jstring databaseName, jshort connType)
-{
- sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle);
- sqlite3_trace(handle, &sqlTrace, (void *)getDatabaseName(env, handle, databaseName, connType));
-}
-
-static void sqlProfile(void *databaseName, const char *sql, sqlite3_uint64 tm) {
- double d = tm/1000000.0;
- ALOGI("elapsedTime4Sql|%s|%.3f ms|%s\n", (char *)databaseName, d, sql);
-}
-
-/* public native void enableSqlProfiling(); */
-static void enableSqlProfiling(JNIEnv* env, jobject object, jstring databaseName, jshort connType)
-{
- sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle);
- sqlite3_profile(handle, &sqlProfile, (void *)getDatabaseName(env, handle, databaseName,
- connType));
-}
-
-/* public native void close(); */
-static void dbclose(JNIEnv* env, jobject object)
-{
- sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle);
-
- if (handle != NULL) {
- // release the memory associated with the traceFuncArg in enableSqlTracing function
- void *traceFuncArg = sqlite3_trace(handle, &sqlTrace, NULL);
- if (traceFuncArg != NULL) {
- free(traceFuncArg);
- }
- // release the memory associated with the traceFuncArg in enableSqlProfiling function
- traceFuncArg = sqlite3_profile(handle, &sqlProfile, NULL);
- if (traceFuncArg != NULL) {
- free(traceFuncArg);
- }
- ALOGV("Closing database: handle=%p\n", handle);
- int result = sqlite3_close(handle);
- if (result == SQLITE_OK) {
- ALOGV("Closed %p\n", handle);
- env->SetIntField(object, offset_db_handle, 0);
- } else {
- // This can happen if sub-objects aren't closed first. Make sure the caller knows.
- throw_sqlite3_exception(env, handle);
- ALOGE("sqlite3_close(%p) failed: %d\n", handle, result);
- }
- }
-}
-
-/* native int native_getDbLookaside(); */
-static jint native_getDbLookaside(JNIEnv* env, jobject object)
-{
- sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle);
- int pCur = -1;
- int unused;
- sqlite3_db_status(handle, SQLITE_DBSTATUS_LOOKASIDE_USED, &pCur, &unused, 0);
- return pCur;
-}
-
-/* set locale in the android_metadata table, install localized collators, and rebuild indexes */
-static void native_setLocale(JNIEnv* env, jobject object, jstring localeString, jint flags)
-{
- if ((flags & NO_LOCALIZED_COLLATORS)) return;
-
- int err;
- char const* locale8 = env->GetStringUTFChars(localeString, NULL);
- sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle);
- sqlite3_stmt* stmt = NULL;
- char** meta = NULL;
- int rowCount, colCount;
- char* dbLocale = NULL;
-
- // create the table, if necessary and possible
- if (!(flags & OPEN_READONLY)) {
- static const char *createSql ="CREATE TABLE IF NOT EXISTS " ANDROID_TABLE " (locale TEXT)";
- err = sqlite3_exec(handle, createSql, NULL, NULL, NULL);
- if (err != SQLITE_OK) {
- ALOGE("CREATE TABLE " ANDROID_TABLE " failed\n");
- throw_sqlite3_exception(env, handle);
- goto done;
- }
- }
-
- // try to read from the table
- static const char *selectSql = "SELECT locale FROM " ANDROID_TABLE " LIMIT 1";
- err = sqlite3_get_table(handle, selectSql, &meta, &rowCount, &colCount, NULL);
- if (err != SQLITE_OK) {
- ALOGE("SELECT locale FROM " ANDROID_TABLE " failed\n");
- throw_sqlite3_exception(env, handle);
- goto done;
- }
-
- dbLocale = (rowCount >= 1) ? meta[colCount] : NULL;
-
- if (dbLocale != NULL && !strcmp(dbLocale, locale8)) {
- // database locale is the same as the desired locale; set up the collators and go
- err = register_localized_collators(handle, locale8, UTF16_STORAGE);
- if (err != SQLITE_OK) throw_sqlite3_exception(env, handle);
- goto done; // no database changes needed
- }
-
- if ((flags & OPEN_READONLY)) {
- // read-only database, so we're going to have to put up with whatever we got
- // For registering new index. Not for modifing the read-only database.
- err = register_localized_collators(handle, locale8, UTF16_STORAGE);
- if (err != SQLITE_OK) throw_sqlite3_exception(env, handle);
- goto done;
- }
-
- // need to update android_metadata and indexes atomically, so use a transaction...
- err = sqlite3_exec(handle, "BEGIN TRANSACTION", NULL, NULL, NULL);
- if (err != SQLITE_OK) {
- ALOGE("BEGIN TRANSACTION failed setting locale\n");
- throw_sqlite3_exception(env, handle);
- goto done;
- }
-
- err = register_localized_collators(handle, locale8, UTF16_STORAGE);
- if (err != SQLITE_OK) {
- ALOGE("register_localized_collators() failed setting locale\n");
- throw_sqlite3_exception(env, handle);
- goto rollback;
- }
-
- err = sqlite3_exec(handle, "DELETE FROM " ANDROID_TABLE, NULL, NULL, NULL);
- if (err != SQLITE_OK) {
- ALOGE("DELETE failed setting locale\n");
- throw_sqlite3_exception(env, handle);
- goto rollback;
- }
-
- static const char *sql = "INSERT INTO " ANDROID_TABLE " (locale) VALUES(?);";
- err = sqlite3_prepare_v2(handle, sql, -1, &stmt, NULL);
- if (err != SQLITE_OK) {
- ALOGE("sqlite3_prepare_v2(\"%s\") failed\n", sql);
- throw_sqlite3_exception(env, handle);
- goto rollback;
- }
-
- err = sqlite3_bind_text(stmt, 1, locale8, -1, SQLITE_TRANSIENT);
- if (err != SQLITE_OK) {
- ALOGE("sqlite3_bind_text() failed setting locale\n");
- throw_sqlite3_exception(env, handle);
- goto rollback;
- }
-
- err = sqlite3_step(stmt);
- if (err != SQLITE_OK && err != SQLITE_DONE) {
- ALOGE("sqlite3_step(\"%s\") failed setting locale\n", sql);
- throw_sqlite3_exception(env, handle);
- goto rollback;
- }
-
- err = sqlite3_exec(handle, "REINDEX LOCALIZED", NULL, NULL, NULL);
- if (err != SQLITE_OK) {
- ALOGE("REINDEX LOCALIZED failed\n");
- throw_sqlite3_exception(env, handle);
- goto rollback;
- }
-
- // all done, yay!
- err = sqlite3_exec(handle, "COMMIT TRANSACTION", NULL, NULL, NULL);
- if (err != SQLITE_OK) {
- ALOGE("COMMIT TRANSACTION failed setting locale\n");
- throw_sqlite3_exception(env, handle);
- goto done;
- }
-
-rollback:
- if (err != SQLITE_OK) {
- sqlite3_exec(handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
- }
-
-done:
- if (locale8 != NULL) env->ReleaseStringUTFChars(localeString, locale8);
- if (stmt != NULL) sqlite3_finalize(stmt);
- if (meta != NULL) sqlite3_free_table(meta);
-}
-
-static void native_setSqliteSoftHeapLimit(JNIEnv* env, jobject clazz, jint limit) {
- sSqliteSoftHeapLimit = limit;
-}
-
-static jint native_releaseMemory(JNIEnv *env, jobject clazz)
-{
- // Attempt to release as much memory from the
- return sqlite3_release_memory(sSqliteSoftHeapLimit);
-}
-
-static void native_finalize(JNIEnv* env, jobject object, jint statementId)
-{
- if (statementId > 0) {
- sqlite3_finalize((sqlite3_stmt *)statementId);
- }
-}
-
-static void custom_function_callback(sqlite3_context * context, int argc, sqlite3_value ** argv) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- if (!env) {
- ALOGE("custom_function_callback cannot call into Java on this thread");
- return;
- }
- // get global ref to CustomFunction object from our user data
- jobject function = (jobject)sqlite3_user_data(context);
-
- // pack up the arguments into a string array
- jobjectArray strArray = env->NewObjectArray(argc, string_class, NULL);
- if (!strArray)
- goto done;
- for (int i = 0; i < argc; i++) {
- char* arg = (char *)sqlite3_value_text(argv[i]);
- if (!arg) {
- ALOGE("NULL argument in custom_function_callback. This should not happen.");
- return;
- }
- jobject obj = env->NewStringUTF(arg);
- if (!obj)
- goto done;
- env->SetObjectArrayElement(strArray, i, obj);
- env->DeleteLocalRef(obj);
- }
-
- env->CallVoidMethod(function, method_custom_function_callback, strArray);
- env->DeleteLocalRef(strArray);
-
-done:
- if (env->ExceptionCheck()) {
- ALOGE("An exception was thrown by custom sqlite3 function.");
- LOGE_EX(env);
- env->ExceptionClear();
- }
-}
-
-static jint native_addCustomFunction(JNIEnv* env, jobject object,
- jstring name, jint numArgs, jobject function)
-{
- sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle);
- char const *nameStr = env->GetStringUTFChars(name, NULL);
- jobject ref = env->NewGlobalRef(function);
- ALOGD_IF(DEBUG_JNI, "native_addCustomFunction %s ref: %p", nameStr, ref);
- int err = sqlite3_create_function(handle, nameStr, numArgs, SQLITE_UTF8,
- (void *)ref, custom_function_callback, NULL, NULL);
- env->ReleaseStringUTFChars(name, nameStr);
-
- if (err == SQLITE_OK)
- return (int)ref;
- else {
- ALOGE("sqlite3_create_function returned %d", err);
- env->DeleteGlobalRef(ref);
- throw_sqlite3_exception(env, handle);
- return 0;
- }
-}
-
-static void native_releaseCustomFunction(JNIEnv* env, jobject object, jint ref)
-{
- ALOGD_IF(DEBUG_JNI, "native_releaseCustomFunction %d", ref);
- env->DeleteGlobalRef((jobject)ref);
-}
-
-static JNINativeMethod sMethods[] =
-{
- /* name, signature, funcPtr */
- {"dbopen", "(Ljava/lang/String;I)V", (void *)dbopen},
- {"dbclose", "()V", (void *)dbclose},
- {"enableSqlTracing", "(Ljava/lang/String;S)V", (void *)enableSqlTracing},
- {"enableSqlProfiling", "(Ljava/lang/String;S)V", (void *)enableSqlProfiling},
- {"native_setLocale", "(Ljava/lang/String;I)V", (void *)native_setLocale},
- {"native_getDbLookaside", "()I", (void *)native_getDbLookaside},
- {"native_setSqliteSoftHeapLimit", "(I)V", (void *)native_setSqliteSoftHeapLimit},
- {"releaseMemory", "()I", (void *)native_releaseMemory},
- {"native_finalize", "(I)V", (void *)native_finalize},
- {"native_addCustomFunction",
- "(Ljava/lang/String;ILandroid/database/sqlite/SQLiteDatabase$CustomFunction;)I",
- (void *)native_addCustomFunction},
- {"native_releaseCustomFunction", "(I)V", (void *)native_releaseCustomFunction},
-};
-
-int register_android_database_SQLiteDatabase(JNIEnv *env)
-{
- jclass clazz;
-
- clazz = env->FindClass("android/database/sqlite/SQLiteDatabase");
- if (clazz == NULL) {
- ALOGE("Can't find android/database/sqlite/SQLiteDatabase\n");
- return -1;
- }
-
- string_class = (jclass)env->NewGlobalRef(env->FindClass("java/lang/String"));
- if (string_class == NULL) {
- ALOGE("Can't find java/lang/String\n");
- return -1;
- }
-
- offset_db_handle = env->GetFieldID(clazz, "mNativeHandle", "I");
- if (offset_db_handle == NULL) {
- ALOGE("Can't find SQLiteDatabase.mNativeHandle\n");
- return -1;
- }
-
- clazz = env->FindClass("android/database/sqlite/SQLiteDatabase$CustomFunction");
- if (clazz == NULL) {
- ALOGE("Can't find android/database/sqlite/SQLiteDatabase$CustomFunction\n");
- return -1;
- }
- method_custom_function_callback = env->GetMethodID(clazz, "callback", "([Ljava/lang/String;)V");
- if (method_custom_function_callback == NULL) {
- ALOGE("Can't find method SQLiteDatabase.CustomFunction.callback\n");
- return -1;
- }
-
- return AndroidRuntime::registerNativeMethods(env, "android/database/sqlite/SQLiteDatabase",
- sMethods, NELEM(sMethods));
-}
-
-/* throw a SQLiteException with a message appropriate for the error in handle */
-void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle) {
- throw_sqlite3_exception(env, handle, NULL);
-}
-
-/* throw a SQLiteException with the given message */
-void throw_sqlite3_exception(JNIEnv* env, const char* message) {
- throw_sqlite3_exception(env, NULL, message);
-}
-
-/* throw a SQLiteException with a message appropriate for the error in handle
- concatenated with the given message
- */
-void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle, const char* message) {
- if (handle) {
- throw_sqlite3_exception(env, sqlite3_errcode(handle),
- sqlite3_errmsg(handle), message);
- } else {
- // we use SQLITE_OK so that a generic SQLiteException is thrown;
- // any code not specified in the switch statement below would do.
- throw_sqlite3_exception(env, SQLITE_OK, "unknown error", message);
- }
-}
-
-/* throw a SQLiteException for a given error code */
-void throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) {
- if (errcode == SQLITE_DONE) {
- throw_sqlite3_exception(env, errcode, NULL, message);
- } else {
- char temp[21];
- sprintf(temp, "error code %d", errcode);
- throw_sqlite3_exception(env, errcode, temp, message);
- }
-}
-
-/* throw a SQLiteException for a given error code, sqlite3message, and
- user message
- */
-void throw_sqlite3_exception(JNIEnv* env, int errcode,
- const char* sqlite3Message, const char* message) {
- const char* exceptionClass;
- switch (errcode) {
- case SQLITE_IOERR:
- exceptionClass = "android/database/sqlite/SQLiteDiskIOException";
- break;
- case SQLITE_CORRUPT:
- case SQLITE_NOTADB: // treat "unsupported file format" error as corruption also
- exceptionClass = "android/database/sqlite/SQLiteDatabaseCorruptException";
- break;
- case SQLITE_CONSTRAINT:
- exceptionClass = "android/database/sqlite/SQLiteConstraintException";
- break;
- case SQLITE_ABORT:
- exceptionClass = "android/database/sqlite/SQLiteAbortException";
- break;
- case SQLITE_DONE:
- exceptionClass = "android/database/sqlite/SQLiteDoneException";
- break;
- case SQLITE_FULL:
- exceptionClass = "android/database/sqlite/SQLiteFullException";
- break;
- case SQLITE_MISUSE:
- exceptionClass = "android/database/sqlite/SQLiteMisuseException";
- break;
- case SQLITE_PERM:
- exceptionClass = "android/database/sqlite/SQLiteAccessPermException";
- break;
- case SQLITE_BUSY:
- exceptionClass = "android/database/sqlite/SQLiteDatabaseLockedException";
- break;
- case SQLITE_LOCKED:
- exceptionClass = "android/database/sqlite/SQLiteTableLockedException";
- break;
- case SQLITE_READONLY:
- exceptionClass = "android/database/sqlite/SQLiteReadOnlyDatabaseException";
- break;
- case SQLITE_CANTOPEN:
- exceptionClass = "android/database/sqlite/SQLiteCantOpenDatabaseException";
- break;
- case SQLITE_TOOBIG:
- exceptionClass = "android/database/sqlite/SQLiteBlobTooBigException";
- break;
- case SQLITE_RANGE:
- exceptionClass = "android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException";
- break;
- case SQLITE_NOMEM:
- exceptionClass = "android/database/sqlite/SQLiteOutOfMemoryException";
- break;
- case SQLITE_MISMATCH:
- exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException";
- break;
- case SQLITE_UNCLOSED:
- exceptionClass = "android/database/sqlite/SQLiteUnfinalizedObjectsException";
- break;
- default:
- exceptionClass = "android/database/sqlite/SQLiteException";
- break;
- }
-
- if (sqlite3Message != NULL && message != NULL) {
- char* fullMessage = (char *)malloc(strlen(sqlite3Message) + strlen(message) + 3);
- if (fullMessage != NULL) {
- strcpy(fullMessage, sqlite3Message);
- strcat(fullMessage, ": ");
- strcat(fullMessage, message);
- jniThrowException(env, exceptionClass, fullMessage);
- free(fullMessage);
- } else {
- jniThrowException(env, exceptionClass, sqlite3Message);
- }
- } else if (sqlite3Message != NULL) {
- jniThrowException(env, exceptionClass, sqlite3Message);
- } else {
- jniThrowException(env, exceptionClass, message);
- }
-}
-
-
-} // namespace android