19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006-2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#undef LOG_TAG 18fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori#define LOG_TAG "SqliteDatabaseCpp" 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String16.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <jni.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <JNIHelp.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sqlite3.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sqlite3_android.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 313b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/Log.h> 323b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/threads.h> 333b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/List.h> 343b4062eeb01be33951ba214e027da523cf09f8b1Mathias Agopian#include <utils/Errors.h> 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ctype.h> 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/socket.h> 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netinet/in.h> 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netdb.h> 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/ioctl.h> 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "sqlite3_exception.h" 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define UTF16_STORAGE 0 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define INVALID_VERSION -1 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define ANDROID_TABLE "android_metadata" 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* uncomment the next line to force-enable logging of all statements */ 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// #define DB_LOG_STATEMENTS 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5377267fc68f2c05ca7cdd1f6b6a9d9b2d4479f8bbVasu Nori#define DEBUG_JNI 0 5477267fc68f2c05ca7cdd1f6b6a9d9b2d4479f8bbVasu Nori 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectenum { 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OPEN_READWRITE = 0x00000000, 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OPEN_READONLY = 0x00000001, 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OPEN_READ_MASK = 0x00000001, 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NO_LOCALIZED_COLLATORS = 0x00000010, 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CREATE_IF_NECESSARY = 0x10000000 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID offset_db_handle; 669d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwoodstatic jmethodID method_custom_function_callback; 67b0f72de87d1abdfec0cd188f277c48f65f7011a8Mike Lockwoodstatic jclass string_class; 6834ad57f0e844cd97f59d4ab22087d60d58650ba4Vasu Noristatic jint sSqliteSoftHeapLimit = 0; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 706c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Noristatic char *createStr(const char *path, short extra) { 716c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori int len = strlen(path) + extra; 72bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori char *str = (char *)malloc(len + 1); 73bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori strncpy(str, path, len); 74bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori str[len] = NULL; 75bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori return str; 76bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori} 77bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori 7854dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Noristatic void sqlLogger(void *databaseName, int iErrCode, const char *zMsg) { 79cc17ed29e0ff184afd1bce750f4f80aa917cfcafVasu Nori // skip printing this message if it is due to certain types of errors 80060e25bf124c530423c589622c220828a7f35086Vasu Nori if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT) return; 815be894e636522addc40dad3b631f0249e6cc25cfVasu Nori // print databasename, errorcode and msg 825be894e636522addc40dad3b631f0249e6cc25cfVasu Nori LOGI("sqlite returned: error code = %d, msg = %s, db=%s\n", iErrCode, zMsg, databaseName); 8354dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori} 8454dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 8554dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori// register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called. 86bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Noristatic void registerLoggingFunc(const char *path) { 8754dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori static bool loggingFuncSet = false; 8854dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori if (loggingFuncSet) { 8954dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori return; 9054dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori } 9154dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 9254dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori LOGV("Registering sqlite logging func \n"); 936c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori int err = sqlite3_config(SQLITE_CONFIG_LOG, &sqlLogger, (void *)createStr(path, 0)); 9491d0e3c950846ad0dfa67ac8d67b554880795580Vasu Nori if (err != SQLITE_OK) { 95f7ebe8e8564108c020fc0d89b833635d210b38a8Vasu Nori LOGW("sqlite returned error = %d when trying to register logging func.\n", err); 9691d0e3c950846ad0dfa67ac8d67b554880795580Vasu Nori return; 9791d0e3c950846ad0dfa67ac8d67b554880795580Vasu Nori } 9854dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori loggingFuncSet = true; 9954dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori} 10054dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* public native void dbopen(String path, int flags, String locale); */ 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void dbopen(JNIEnv* env, jobject object, jstring pathString, jint flags) 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3 * handle = NULL; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_stmt * statement = NULL; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char const * path8 = env->GetStringUTFChars(pathString, NULL); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sqliteFlags; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11054dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori // register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called. 111bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori registerLoggingFunc(path8); 11254dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // convert our flags into the sqlite flags 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flags & CREATE_IF_NECESSARY) { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (flags & OPEN_READONLY) { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqliteFlags = SQLITE_OPEN_READONLY; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqliteFlags = SQLITE_OPEN_READWRITE; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_open_v2(path8, &handle, sqliteFlags, NULL); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_open_v2(\"%s\", &handle, %d, NULL) failed\n", path8, sqliteFlags); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The soft heap limit prevents the page cache allocations from growing 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // beyond the given limit, no matter what the max page cache sizes are 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // set to. The limit does not, as of 3.5.0, affect any other allocations. 13234ad57f0e844cd97f59d4ab22087d60d58650ba4Vasu Nori sqlite3_soft_heap_limit(sSqliteSoftHeapLimit); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set the default busy handler to retry for 1000ms and then return SQLITE_BUSY 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_busy_timeout(handle, 1000 /* ms */); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_busy_timeout(handle, 1000) failed for \"%s\"\n", path8); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef DB_INTEGRITY_CHECK 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static const char* integritySql = "pragma integrity_check(1);"; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_prepare_v2(handle, integritySql, -1, &statement, NULL); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite_prepare_v2(handle, \"%s\") failed for \"%s\"\n", integritySql, path8); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // first is OK or error message 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_step(statement); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_ROW) { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("integrity check failed for \"%s\"\n", integritySql, path8); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *text = (const char*)sqlite3_column_text(statement, 0); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strcmp(text, "ok") != 0) { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("integrity check failed for \"%s\": %s\n", integritySql, path8, text); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "android/database/sqlite/SQLiteDatabaseCorruptException", text); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = register_android_functions(handle, UTF16_STORAGE); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err) { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("Opened '%s' - %p\n", path8, handle); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, offset_db_handle, (int) handle); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handle = NULL; // The caller owns the handle now. 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectdone: 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Release allocated resources 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (path8 != NULL) env->ReleaseStringUTFChars(pathString, path8); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (statement != NULL) sqlite3_finalize(statement); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (handle != NULL) sqlite3_close(handle); 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1846c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Noristatic char *getDatabaseName(JNIEnv* env, sqlite3 * handle, jstring databaseName, short connNum) { 18554dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori char const *path = env->GetStringUTFChars(databaseName, NULL); 18654dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori if (path == NULL) { 18754dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori LOGE("Failure in getDatabaseName(). VM ran out of memory?\n"); 18854dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori return NULL; // VM would have thrown OutOfMemoryError 18954dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori } 1906c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori char *dbNameStr = createStr(path, 4); 1916c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori if (connNum > 999) { // TODO: if number of pooled connections > 999, fix this line. 1926c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori connNum = -1; 1936c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori } 1946c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori sprintf(dbNameStr + strlen(path), "|%03d", connNum); 19554dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori env->ReleaseStringUTFChars(databaseName, path); 19654dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori return dbNameStr; 19754dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori} 19854dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 19954dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Noristatic void sqlTrace(void *databaseName, const char *sql) { 2003ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori LOGI("sql_statement|%s|%s\n", (char *)databaseName, sql); 2013ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori} 2023ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori 2033ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori/* public native void enableSqlTracing(); */ 2046c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Noristatic void enableSqlTracing(JNIEnv* env, jobject object, jstring databaseName, jshort connType) 2053ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori{ 2063ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 2076c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori sqlite3_trace(handle, &sqlTrace, (void *)getDatabaseName(env, handle, databaseName, connType)); 2083ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori} 2093ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori 21054dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Noristatic void sqlProfile(void *databaseName, const char *sql, sqlite3_uint64 tm) { 2113ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori double d = tm/1000000.0; 2123ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori LOGI("elapsedTime4Sql|%s|%.3f ms|%s\n", (char *)databaseName, d, sql); 2133ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori} 2143ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori 2153ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori/* public native void enableSqlProfiling(); */ 2166c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Noristatic void enableSqlProfiling(JNIEnv* env, jobject object, jstring databaseName, jshort connType) 2173ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori{ 2183ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 2196c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori sqlite3_profile(handle, &sqlProfile, (void *)getDatabaseName(env, handle, databaseName, 2206c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori connType)); 2213ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori} 2223ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* public native void close(); */ 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void dbclose(JNIEnv* env, jobject object) 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (handle != NULL) { 2293ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori // release the memory associated with the traceFuncArg in enableSqlTracing function 2303ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori void *traceFuncArg = sqlite3_trace(handle, &sqlTrace, NULL); 2313ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori if (traceFuncArg != NULL) { 2323ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori free(traceFuncArg); 2333ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori } 2343ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori // release the memory associated with the traceFuncArg in enableSqlProfiling function 2353ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori traceFuncArg = sqlite3_profile(handle, &sqlProfile, NULL); 2363ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori if (traceFuncArg != NULL) { 2373ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori free(traceFuncArg); 2383ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("Closing database: handle=%p\n", handle); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int result = sqlite3_close(handle); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result == SQLITE_OK) { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("Closed %p\n", handle); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, offset_db_handle, 0); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This can happen if sub-objects aren't closed first. Make sure the caller knows. 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_close(%p) failed: %d\n", handle, result); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 252c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori/* native int native_getDbLookaside(); */ 253c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Noristatic jint native_getDbLookaside(JNIEnv* env, jobject object) 254c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori{ 255c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 256c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori int pCur = -1; 257c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori int unused; 258c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori sqlite3_db_status(handle, SQLITE_DBSTATUS_LOOKASIDE_USED, &pCur, &unused, 0); 259c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori return pCur; 260c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori} 261c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* set locale in the android_metadata table, install localized collators, and rebuild indexes */ 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void native_setLocale(JNIEnv* env, jobject object, jstring localeString, jint flags) 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & NO_LOCALIZED_COLLATORS)) return; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char const* locale8 = env->GetStringUTFChars(localeString, NULL); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_stmt* stmt = NULL; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char** meta = NULL; 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowCount, colCount; 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char* dbLocale = NULL; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // create the table, if necessary and possible 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!(flags & OPEN_READONLY)) { 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static const char *createSql ="CREATE TABLE IF NOT EXISTS " ANDROID_TABLE " (locale TEXT)"; 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_exec(handle, createSql, NULL, NULL, NULL); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("CREATE TABLE " ANDROID_TABLE " failed\n"); 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // try to read from the table 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static const char *selectSql = "SELECT locale FROM " ANDROID_TABLE " LIMIT 1"; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_get_table(handle, selectSql, &meta, &rowCount, &colCount, NULL); 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("SELECT locale FROM " ANDROID_TABLE " failed\n"); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 295b945639d0c3fa1850c07a2b80f476c8d242a8bdeDaisuke Miyakawa dbLocale = (rowCount >= 1) ? meta[colCount] : NULL; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dbLocale != NULL && !strcmp(dbLocale, locale8)) { 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // database locale is the same as the desired locale; set up the collators and go 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = register_localized_collators(handle, locale8, UTF16_STORAGE); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) throw_sqlite3_exception(env, handle); 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; // no database changes needed 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & OPEN_READONLY)) { 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read-only database, so we're going to have to put up with whatever we got 306b945639d0c3fa1850c07a2b80f476c8d242a8bdeDaisuke Miyakawa // For registering new index. Not for modifing the read-only database. 307b945639d0c3fa1850c07a2b80f476c8d242a8bdeDaisuke Miyakawa err = register_localized_collators(handle, locale8, UTF16_STORAGE); 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) throw_sqlite3_exception(env, handle); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // need to update android_metadata and indexes atomically, so use a transaction... 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_exec(handle, "BEGIN TRANSACTION", NULL, NULL, NULL); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("BEGIN TRANSACTION failed setting locale\n"); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 320b945639d0c3fa1850c07a2b80f476c8d242a8bdeDaisuke Miyakawa err = register_localized_collators(handle, locale8, UTF16_STORAGE); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("register_localized_collators() failed setting locale\n"); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 32478f307d229466bb41c0260d1092dcea82a7bb5f8Vasu Nori goto rollback; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_exec(handle, "DELETE FROM " ANDROID_TABLE, NULL, NULL, NULL); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("DELETE failed setting locale\n"); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto rollback; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static const char *sql = "INSERT INTO " ANDROID_TABLE " (locale) VALUES(?);"; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_prepare_v2(handle, sql, -1, &stmt, NULL); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_prepare_v2(\"%s\") failed\n", sql); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto rollback; 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_bind_text(stmt, 1, locale8, -1, SQLITE_TRANSIENT); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_bind_text() failed setting locale\n"); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto rollback; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_step(stmt); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK && err != SQLITE_DONE) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_step(\"%s\") failed setting locale\n", sql); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto rollback; 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_exec(handle, "REINDEX LOCALIZED", NULL, NULL, NULL); 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("REINDEX LOCALIZED failed\n"); 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto rollback; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // all done, yay! 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_exec(handle, "COMMIT TRANSACTION", NULL, NULL, NULL); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("COMMIT TRANSACTION failed setting locale\n"); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectrollback: 37278f307d229466bb41c0260d1092dcea82a7bb5f8Vasu Nori if (err != SQLITE_OK) { 37378f307d229466bb41c0260d1092dcea82a7bb5f8Vasu Nori sqlite3_exec(handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL); 37478f307d229466bb41c0260d1092dcea82a7bb5f8Vasu Nori } 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectdone: 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (locale8 != NULL) env->ReleaseStringUTFChars(localeString, locale8); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stmt != NULL) sqlite3_finalize(stmt); 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (meta != NULL) sqlite3_free_table(meta); 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38234ad57f0e844cd97f59d4ab22087d60d58650ba4Vasu Noristatic void native_setSqliteSoftHeapLimit(JNIEnv* env, jobject clazz, jint limit) { 38334ad57f0e844cd97f59d4ab22087d60d58650ba4Vasu Nori sSqliteSoftHeapLimit = limit; 38434ad57f0e844cd97f59d4ab22087d60d58650ba4Vasu Nori} 38534ad57f0e844cd97f59d4ab22087d60d58650ba4Vasu Nori 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint native_releaseMemory(JNIEnv *env, jobject clazz) 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Attempt to release as much memory from the 38934ad57f0e844cd97f59d4ab22087d60d58650ba4Vasu Nori return sqlite3_release_memory(sSqliteSoftHeapLimit); 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3926f37f83a4802a0d411395f3abc5f24a2cfec025dVasu Noristatic void native_finalize(JNIEnv* env, jobject object, jint statementId) 3936f37f83a4802a0d411395f3abc5f24a2cfec025dVasu Nori{ 3946f37f83a4802a0d411395f3abc5f24a2cfec025dVasu Nori if (statementId > 0) { 3956f37f83a4802a0d411395f3abc5f24a2cfec025dVasu Nori sqlite3_finalize((sqlite3_stmt *)statementId); 3966f37f83a4802a0d411395f3abc5f24a2cfec025dVasu Nori } 3976f37f83a4802a0d411395f3abc5f24a2cfec025dVasu Nori} 3986f37f83a4802a0d411395f3abc5f24a2cfec025dVasu Nori 3999d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwoodstatic void custom_function_callback(sqlite3_context * context, int argc, sqlite3_value ** argv) { 4009d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood JNIEnv* env = AndroidRuntime::getJNIEnv(); 4019d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood if (!env) { 4029d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood LOGE("custom_function_callback cannot call into Java on this thread"); 4039d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood return; 4049d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood } 405c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood // get global ref to CustomFunction object from our user data 406c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood jobject function = (jobject)sqlite3_user_data(context); 4079d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood 4089d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood // pack up the arguments into a string array 409c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood jobjectArray strArray = env->NewObjectArray(argc, string_class, NULL); 410c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood if (!strArray) 411c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood goto done; 4129d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood for (int i = 0; i < argc; i++) { 4139d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood char* arg = (char *)sqlite3_value_text(argv[i]); 414c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood if (!arg) { 415c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood LOGE("NULL argument in custom_function_callback. This should not happen."); 4169d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood return; 4179d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood } 418c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood jobject obj = env->NewStringUTF(arg); 419c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood if (!obj) 420c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood goto done; 4219d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood env->SetObjectArrayElement(strArray, i, obj); 4229d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood env->DeleteLocalRef(obj); 4239d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood } 4249d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood 4259d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood env->CallVoidMethod(function, method_custom_function_callback, strArray); 426b0f72de87d1abdfec0cd188f277c48f65f7011a8Mike Lockwood env->DeleteLocalRef(strArray); 427c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood 428c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwooddone: 429c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood if (env->ExceptionCheck()) { 430c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood LOGE("An exception was thrown by custom sqlite3 function."); 431c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood LOGE_EX(env); 432c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood env->ExceptionClear(); 433c5bb8d8de5297c610c0c75897e025cbd6aec8ddaMike Lockwood } 4349d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood} 4359d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood 4369d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwoodstatic jint native_addCustomFunction(JNIEnv* env, jobject object, 4379d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood jstring name, jint numArgs, jobject function) 4389d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood{ 4399d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 4409d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood char const *nameStr = env->GetStringUTFChars(name, NULL); 4419d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood jobject ref = env->NewGlobalRef(function); 44277267fc68f2c05ca7cdd1f6b6a9d9b2d4479f8bbVasu Nori LOGD_IF(DEBUG_JNI, "native_addCustomFunction %s ref: %p", nameStr, ref); 4439d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood int err = sqlite3_create_function(handle, nameStr, numArgs, SQLITE_UTF8, 4449d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood (void *)ref, custom_function_callback, NULL, NULL); 4459d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood env->ReleaseStringUTFChars(name, nameStr); 4469d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood 4479d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood if (err == SQLITE_OK) 4489d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood return (int)ref; 4499d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood else { 4509d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood LOGE("sqlite3_create_function returned %d", err); 4519d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood env->DeleteGlobalRef(ref); 4529d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood throw_sqlite3_exception(env, handle); 4539d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood return 0; 4549d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood } 4559d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood} 4569d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood 4579d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwoodstatic void native_releaseCustomFunction(JNIEnv* env, jobject object, jint ref) 4589d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood{ 45977267fc68f2c05ca7cdd1f6b6a9d9b2d4479f8bbVasu Nori LOGD_IF(DEBUG_JNI, "native_releaseCustomFunction %d", ref); 4609d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood env->DeleteGlobalRef((jobject)ref); 4619d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood} 4629d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod sMethods[] = 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* name, signature, funcPtr */ 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"dbopen", "(Ljava/lang/String;I)V", (void *)dbopen}, 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"dbclose", "()V", (void *)dbclose}, 4686c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori {"enableSqlTracing", "(Ljava/lang/String;S)V", (void *)enableSqlTracing}, 4696c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori {"enableSqlProfiling", "(Ljava/lang/String;S)V", (void *)enableSqlProfiling}, 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_setLocale", "(Ljava/lang/String;I)V", (void *)native_setLocale}, 471c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori {"native_getDbLookaside", "()I", (void *)native_getDbLookaside}, 47234ad57f0e844cd97f59d4ab22087d60d58650ba4Vasu Nori {"native_setSqliteSoftHeapLimit", "(I)V", (void *)native_setSqliteSoftHeapLimit}, 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"releaseMemory", "()I", (void *)native_releaseMemory}, 4746f37f83a4802a0d411395f3abc5f24a2cfec025dVasu Nori {"native_finalize", "(I)V", (void *)native_finalize}, 4759d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood {"native_addCustomFunction", 4769d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood "(Ljava/lang/String;ILandroid/database/sqlite/SQLiteDatabase$CustomFunction;)I", 4779d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood (void *)native_addCustomFunction}, 4789d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood {"native_releaseCustomFunction", "(I)V", (void *)native_releaseCustomFunction}, 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_database_SQLiteDatabase(JNIEnv *env) 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clazz = env->FindClass("android/database/sqlite/SQLiteDatabase"); 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clazz == NULL) { 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Can't find android/database/sqlite/SQLiteDatabase\n"); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 491b0f72de87d1abdfec0cd188f277c48f65f7011a8Mike Lockwood string_class = (jclass)env->NewGlobalRef(env->FindClass("java/lang/String")); 492b0f72de87d1abdfec0cd188f277c48f65f7011a8Mike Lockwood if (string_class == NULL) { 493b0f72de87d1abdfec0cd188f277c48f65f7011a8Mike Lockwood LOGE("Can't find java/lang/String\n"); 494b0f72de87d1abdfec0cd188f277c48f65f7011a8Mike Lockwood return -1; 495b0f72de87d1abdfec0cd188f277c48f65f7011a8Mike Lockwood } 496b0f72de87d1abdfec0cd188f277c48f65f7011a8Mike Lockwood 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offset_db_handle = env->GetFieldID(clazz, "mNativeHandle", "I"); 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset_db_handle == NULL) { 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Can't find SQLiteDatabase.mNativeHandle\n"); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5039d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood clazz = env->FindClass("android/database/sqlite/SQLiteDatabase$CustomFunction"); 5049d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood if (clazz == NULL) { 5059d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood LOGE("Can't find android/database/sqlite/SQLiteDatabase$CustomFunction\n"); 5069d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood return -1; 5079d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood } 5089d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood method_custom_function_callback = env->GetMethodID(clazz, "callback", "([Ljava/lang/String;)V"); 5099d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood if (method_custom_function_callback == NULL) { 5109d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood LOGE("Can't find method SQLiteDatabase.CustomFunction.callback\n"); 5119d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood return -1; 5129d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood } 5139d9c1be296db26c6ad36b8593fb77ca263422665Mike Lockwood 5146c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori return AndroidRuntime::registerNativeMethods(env, "android/database/sqlite/SQLiteDatabase", 5156c354da9436e946708fc3f3a1c0d18b18bbfdf43Vasu Nori sMethods, NELEM(sMethods)); 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* throw a SQLiteException with a message appropriate for the error in handle */ 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid throw_sqlite3_exception(JNIEnv* env, sqlite3* handle) { 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle, NULL); 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* throw a SQLiteException with the given message */ 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid throw_sqlite3_exception(JNIEnv* env, const char* message) { 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, NULL, message); 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* throw a SQLiteException with a message appropriate for the error in handle 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project concatenated with the given message 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid throw_sqlite3_exception(JNIEnv* env, sqlite3* handle, const char* message) { 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (handle) { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, sqlite3_errcode(handle), 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_errmsg(handle), message); 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we use SQLITE_OK so that a generic SQLiteException is thrown; 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // any code not specified in the switch statement below would do. 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, SQLITE_OK, "unknown error", message); 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* throw a SQLiteException for a given error code */ 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) { 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (errcode == SQLITE_DONE) { 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, errcode, NULL, message); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 547f80efdf7e2b34ab8fec8f47052bf8386616ac312Kenny Root char temp[21]; 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(temp, "error code %d", errcode); 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, errcode, temp, message); 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* throw a SQLiteException for a given error code, sqlite3message, and 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project user message 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid throw_sqlite3_exception(JNIEnv* env, int errcode, 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* sqlite3Message, const char* message) { 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* exceptionClass; 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (errcode) { 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_IOERR: 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteDiskIOException"; 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_CORRUPT: 564b339509d3129db32a57ef95fc322a8482b6994f3Vasu Nori case SQLITE_NOTADB: // treat "unsupported file format" error as corruption also 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteDatabaseCorruptException"; 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_CONSTRAINT: 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteConstraintException"; 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_ABORT: 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteAbortException"; 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_DONE: 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteDoneException"; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_FULL: 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteFullException"; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_MISUSE: 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteMisuseException"; 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 582dea9713387460c560b67106ab913f686f7d16af2Vasu Nori case SQLITE_PERM: 583dea9713387460c560b67106ab913f686f7d16af2Vasu Nori exceptionClass = "android/database/sqlite/SQLiteAccessPermException"; 584dea9713387460c560b67106ab913f686f7d16af2Vasu Nori break; 585dea9713387460c560b67106ab913f686f7d16af2Vasu Nori case SQLITE_BUSY: 586dea9713387460c560b67106ab913f686f7d16af2Vasu Nori exceptionClass = "android/database/sqlite/SQLiteDatabaseLockedException"; 587dea9713387460c560b67106ab913f686f7d16af2Vasu Nori break; 588dea9713387460c560b67106ab913f686f7d16af2Vasu Nori case SQLITE_LOCKED: 589dea9713387460c560b67106ab913f686f7d16af2Vasu Nori exceptionClass = "android/database/sqlite/SQLiteTableLockedException"; 590dea9713387460c560b67106ab913f686f7d16af2Vasu Nori break; 591dea9713387460c560b67106ab913f686f7d16af2Vasu Nori case SQLITE_READONLY: 592dea9713387460c560b67106ab913f686f7d16af2Vasu Nori exceptionClass = "android/database/sqlite/SQLiteReadOnlyDatabaseException"; 593dea9713387460c560b67106ab913f686f7d16af2Vasu Nori break; 594dea9713387460c560b67106ab913f686f7d16af2Vasu Nori case SQLITE_CANTOPEN: 595dea9713387460c560b67106ab913f686f7d16af2Vasu Nori exceptionClass = "android/database/sqlite/SQLiteCantOpenDatabaseException"; 596dea9713387460c560b67106ab913f686f7d16af2Vasu Nori break; 597dea9713387460c560b67106ab913f686f7d16af2Vasu Nori case SQLITE_TOOBIG: 598dea9713387460c560b67106ab913f686f7d16af2Vasu Nori exceptionClass = "android/database/sqlite/SQLiteBlobTooBigException"; 599dea9713387460c560b67106ab913f686f7d16af2Vasu Nori break; 600dea9713387460c560b67106ab913f686f7d16af2Vasu Nori case SQLITE_RANGE: 601dea9713387460c560b67106ab913f686f7d16af2Vasu Nori exceptionClass = "android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException"; 602dea9713387460c560b67106ab913f686f7d16af2Vasu Nori break; 603dea9713387460c560b67106ab913f686f7d16af2Vasu Nori case SQLITE_NOMEM: 604dea9713387460c560b67106ab913f686f7d16af2Vasu Nori exceptionClass = "android/database/sqlite/SQLiteOutOfMemoryException"; 605dea9713387460c560b67106ab913f686f7d16af2Vasu Nori break; 606dea9713387460c560b67106ab913f686f7d16af2Vasu Nori case SQLITE_MISMATCH: 607dea9713387460c560b67106ab913f686f7d16af2Vasu Nori exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException"; 608dea9713387460c560b67106ab913f686f7d16af2Vasu Nori break; 609422dad0f5069a96c002faf31540bf471a7052585Vasu Nori case SQLITE_UNCLOSED: 610422dad0f5069a96c002faf31540bf471a7052585Vasu Nori exceptionClass = "android/database/sqlite/SQLiteUnfinalizedObjectsException"; 611422dad0f5069a96c002faf31540bf471a7052585Vasu Nori break; 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteException"; 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sqlite3Message != NULL && message != NULL) { 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char* fullMessage = (char *)malloc(strlen(sqlite3Message) + strlen(message) + 3); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fullMessage != NULL) { 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strcpy(fullMessage, sqlite3Message); 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strcat(fullMessage, ": "); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strcat(fullMessage, message); 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, exceptionClass, fullMessage); 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(fullMessage); 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, exceptionClass, sqlite3Message); 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sqlite3Message != NULL) { 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, exceptionClass, sqlite3Message); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, exceptionClass, message); 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android 637