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 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "Database" 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 SQLITE_SOFT_HEAP_LIMIT (4 * 1024 * 1024) 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define ANDROID_TABLE "android_metadata" 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* uncomment the next line to force-enable logging of all statements */ 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// #define DB_LOG_STATEMENTS 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectenum { 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OPEN_READWRITE = 0x00000000, 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OPEN_READONLY = 0x00000001, 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OPEN_READ_MASK = 0x00000001, 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NO_LOCALIZED_COLLATORS = 0x00000010, 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CREATE_IF_NECESSARY = 0x10000000 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID offset_db_handle; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 66bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Noristatic char *createStr(const char *path) { 67bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori int len = strlen(path); 68bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori char *str = (char *)malloc(len + 1); 69bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori strncpy(str, path, len); 70bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori str[len] = NULL; 71bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori return str; 72bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori} 73bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori 7454dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Noristatic void sqlLogger(void *databaseName, int iErrCode, const char *zMsg) { 75cc17ed29e0ff184afd1bce750f4f80aa917cfcafVasu Nori // skip printing this message if it is due to certain types of errors 76cc17ed29e0ff184afd1bce750f4f80aa917cfcafVasu Nori if (iErrCode == SQLITE_CONSTRAINT) return; 77cc17ed29e0ff184afd1bce750f4f80aa917cfcafVasu Nori LOGI("sqlite returned: error code = %d, msg = %s\n", iErrCode, zMsg); 7854dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori} 7954dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 8054dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori// register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called. 81bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Noristatic void registerLoggingFunc(const char *path) { 8254dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori static bool loggingFuncSet = false; 8354dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori if (loggingFuncSet) { 8454dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori return; 8554dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori } 8654dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 8754dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori LOGV("Registering sqlite logging func \n"); 88bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori int err = sqlite3_config(SQLITE_CONFIG_LOG, &sqlLogger, (void *)createStr(path)); 8991d0e3c950846ad0dfa67ac8d67b554880795580Vasu Nori if (err != SQLITE_OK) { 9091d0e3c950846ad0dfa67ac8d67b554880795580Vasu Nori LOGE("sqlite_config failed error_code = %d. THIS SHOULD NEVER occur.\n", err); 9191d0e3c950846ad0dfa67ac8d67b554880795580Vasu Nori return; 9291d0e3c950846ad0dfa67ac8d67b554880795580Vasu Nori } 9354dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori loggingFuncSet = true; 9454dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori} 9554dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* public native void dbopen(String path, int flags, String locale); */ 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void dbopen(JNIEnv* env, jobject object, jstring pathString, jint flags) 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3 * handle = NULL; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_stmt * statement = NULL; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char const * path8 = env->GetStringUTFChars(pathString, NULL); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sqliteFlags; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10554dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori // register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called. 106bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori registerLoggingFunc(path8); 10754dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // convert our flags into the sqlite flags 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flags & CREATE_IF_NECESSARY) { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (flags & OPEN_READONLY) { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqliteFlags = SQLITE_OPEN_READONLY; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqliteFlags = SQLITE_OPEN_READWRITE; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_open_v2(path8, &handle, sqliteFlags, NULL); 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_open_v2(\"%s\", &handle, %d, NULL) failed\n", path8, sqliteFlags); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The soft heap limit prevents the page cache allocations from growing 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // beyond the given limit, no matter what the max page cache sizes are 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // set to. The limit does not, as of 3.5.0, affect any other allocations. 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_soft_heap_limit(SQLITE_SOFT_HEAP_LIMIT); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set the default busy handler to retry for 1000ms and then return SQLITE_BUSY 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_busy_timeout(handle, 1000 /* ms */); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_busy_timeout(handle, 1000) failed for \"%s\"\n", path8); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef DB_INTEGRITY_CHECK 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static const char* integritySql = "pragma integrity_check(1);"; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_prepare_v2(handle, integritySql, -1, &statement, NULL); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite_prepare_v2(handle, \"%s\") failed for \"%s\"\n", integritySql, path8); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // first is OK or error message 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_step(statement); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_ROW) { 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("integrity check failed for \"%s\"\n", integritySql, path8); 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *text = (const char*)sqlite3_column_text(statement, 0); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strcmp(text, "ok") != 0) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("integrity check failed for \"%s\": %s\n", integritySql, path8, text); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "android/database/sqlite/SQLiteDatabaseCorruptException", text); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = register_android_functions(handle, UTF16_STORAGE); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("Opened '%s' - %p\n", path8, handle); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, offset_db_handle, (int) handle); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handle = NULL; // The caller owns the handle now. 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectdone: 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Release allocated resources 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (path8 != NULL) env->ReleaseStringUTFChars(pathString, path8); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (statement != NULL) sqlite3_finalize(statement); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (handle != NULL) sqlite3_close(handle); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17954dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Noristatic char *getDatabaseName(JNIEnv* env, sqlite3 * handle, jstring databaseName) { 18054dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori char const *path = env->GetStringUTFChars(databaseName, NULL); 18154dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori if (path == NULL) { 18254dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori LOGE("Failure in getDatabaseName(). VM ran out of memory?\n"); 18354dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori return NULL; // VM would have thrown OutOfMemoryError 18454dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori } 185bd29b7c2b7f6c4041b270599d4f0a8bbfb4d785bVasu Nori char *dbNameStr = createStr(path); 18654dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori env->ReleaseStringUTFChars(databaseName, path); 18754dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori return dbNameStr; 18854dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori} 18954dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 19054dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Noristatic void sqlTrace(void *databaseName, const char *sql) { 1913ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori LOGI("sql_statement|%s|%s\n", (char *)databaseName, sql); 1923ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori} 1933ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori 1943ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori/* public native void enableSqlTracing(); */ 1953ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Noristatic void enableSqlTracing(JNIEnv* env, jobject object, jstring databaseName) 1963ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori{ 1973ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 19854dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori sqlite3_trace(handle, &sqlTrace, (void *)getDatabaseName(env, handle, databaseName)); 1993ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori} 2003ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori 20154dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Noristatic void sqlProfile(void *databaseName, const char *sql, sqlite3_uint64 tm) { 2023ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori double d = tm/1000000.0; 2033ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori LOGI("elapsedTime4Sql|%s|%.3f ms|%s\n", (char *)databaseName, d, sql); 2043ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori} 2053ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori 2063ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori/* public native void enableSqlProfiling(); */ 2073ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Noristatic void enableSqlProfiling(JNIEnv* env, jobject object, jstring databaseName) 2083ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori{ 2093ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 21054dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori sqlite3_profile(handle, &sqlProfile, (void *)getDatabaseName(env, handle, databaseName)); 2113ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori} 2123ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori 21354dd0f25acad86f7c4901e6f7d8fdd5628e42970Vasu Nori 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* public native void close(); */ 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void dbclose(JNIEnv* env, jobject object) 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (handle != NULL) { 2203ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori // release the memory associated with the traceFuncArg in enableSqlTracing function 2213ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori void *traceFuncArg = sqlite3_trace(handle, &sqlTrace, NULL); 2223ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori if (traceFuncArg != NULL) { 2233ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori free(traceFuncArg); 2243ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori } 2253ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori // release the memory associated with the traceFuncArg in enableSqlProfiling function 2263ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori traceFuncArg = sqlite3_profile(handle, &sqlProfile, NULL); 2273ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori if (traceFuncArg != NULL) { 2283ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori free(traceFuncArg); 2293ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("Closing database: handle=%p\n", handle); 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int result = sqlite3_close(handle); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result == SQLITE_OK) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("Closed %p\n", handle); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, offset_db_handle, 0); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This can happen if sub-objects aren't closed first. Make sure the caller knows. 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_close(%p) failed: %d\n", handle, result); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* public native void native_execSQL(String sql); */ 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void native_execSQL(JNIEnv* env, jobject object, jstring sqlString) 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int stepErr; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_stmt * statement = NULL; 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jchar const * sql = env->GetStringChars(sqlString, NULL); 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jsize sqlLen = env->GetStringLength(sqlString); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sql == NULL || sqlLen == 0) { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", "You must supply an SQL string"); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_prepare16_v2(handle, sql, sqlLen * 2, &statement, NULL); 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseStringChars(sqlString, sql); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char const * sql8 = env->GetStringUTFChars(sqlString, NULL); 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Failure %d (%s) on %p when preparing '%s'.\n", err, sqlite3_errmsg(handle), handle, sql8); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle, sql8); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseStringUTFChars(sqlString, sql8); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stepErr = sqlite3_step(statement); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_finalize(statement); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stepErr != SQLITE_DONE) { 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stepErr == SQLITE_ROW) { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Queries cannot be performed using execSQL(), use query() instead."); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char const * sql8 = env->GetStringUTFChars(sqlString, NULL); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Failure %d (%s) on %p when executing '%s'\n", err, sqlite3_errmsg(handle), handle, sql8); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle, sql8); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseStringUTFChars(sqlString, sql8); 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifndef DB_LOG_STATEMENTS 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IF_LOGV() 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char const * sql8 = env->GetStringUTFChars(sqlString, NULL); 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("Success on %p when executing '%s'\n", handle, sql8); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ReleaseStringUTFChars(sqlString, sql8); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* native long lastInsertRow(); */ 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong lastInsertRow(JNIEnv* env, jobject object) 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sqlite3_last_insert_rowid(handle); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* native int lastChangeCount(); */ 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint lastChangeCount(JNIEnv* env, jobject object) 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sqlite3_changes(handle); 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 310c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori/* native int native_getDbLookaside(); */ 311c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Noristatic jint native_getDbLookaside(JNIEnv* env, jobject object) 312c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori{ 313c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 314c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori int pCur = -1; 315c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori int unused; 316c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori sqlite3_db_status(handle, SQLITE_DBSTATUS_LOOKASIDE_USED, &pCur, &unused, 0); 317c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori return pCur; 318c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori} 319c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* set locale in the android_metadata table, install localized collators, and rebuild indexes */ 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void native_setLocale(JNIEnv* env, jobject object, jstring localeString, jint flags) 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & NO_LOCALIZED_COLLATORS)) return; 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char const* locale8 = env->GetStringUTFChars(localeString, NULL); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_stmt* stmt = NULL; 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char** meta = NULL; 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowCount, colCount; 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char* dbLocale = NULL; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // create the table, if necessary and possible 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!(flags & OPEN_READONLY)) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static const char *createSql ="CREATE TABLE IF NOT EXISTS " ANDROID_TABLE " (locale TEXT)"; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_exec(handle, createSql, NULL, NULL, NULL); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("CREATE TABLE " ANDROID_TABLE " failed\n"); 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // try to read from the table 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static const char *selectSql = "SELECT locale FROM " ANDROID_TABLE " LIMIT 1"; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_get_table(handle, selectSql, &meta, &rowCount, &colCount, NULL); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("SELECT locale FROM " ANDROID_TABLE " failed\n"); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 353b945639d0c3fa1850c07a2b80f476c8d242a8bdeDaisuke Miyakawa dbLocale = (rowCount >= 1) ? meta[colCount] : NULL; 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dbLocale != NULL && !strcmp(dbLocale, locale8)) { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // database locale is the same as the desired locale; set up the collators and go 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = register_localized_collators(handle, locale8, UTF16_STORAGE); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) throw_sqlite3_exception(env, handle); 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; // no database changes needed 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & OPEN_READONLY)) { 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read-only database, so we're going to have to put up with whatever we got 364b945639d0c3fa1850c07a2b80f476c8d242a8bdeDaisuke Miyakawa // For registering new index. Not for modifing the read-only database. 365b945639d0c3fa1850c07a2b80f476c8d242a8bdeDaisuke Miyakawa err = register_localized_collators(handle, locale8, UTF16_STORAGE); 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) throw_sqlite3_exception(env, handle); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // need to update android_metadata and indexes atomically, so use a transaction... 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_exec(handle, "BEGIN TRANSACTION", NULL, NULL, NULL); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("BEGIN TRANSACTION failed setting locale\n"); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 378b945639d0c3fa1850c07a2b80f476c8d242a8bdeDaisuke Miyakawa err = register_localized_collators(handle, locale8, UTF16_STORAGE); 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("register_localized_collators() failed setting locale\n"); 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 38278f307d229466bb41c0260d1092dcea82a7bb5f8Vasu Nori goto rollback; 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_exec(handle, "DELETE FROM " ANDROID_TABLE, NULL, NULL, NULL); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("DELETE failed setting locale\n"); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto rollback; 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static const char *sql = "INSERT INTO " ANDROID_TABLE " (locale) VALUES(?);"; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_prepare_v2(handle, sql, -1, &stmt, NULL); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_prepare_v2(\"%s\") failed\n", sql); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto rollback; 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_bind_text(stmt, 1, locale8, -1, SQLITE_TRANSIENT); 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_bind_text() failed setting locale\n"); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto rollback; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_step(stmt); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK && err != SQLITE_DONE) { 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("sqlite3_step(\"%s\") failed setting locale\n", sql); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto rollback; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_exec(handle, "REINDEX LOCALIZED", NULL, NULL, NULL); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("REINDEX LOCALIZED failed\n"); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto rollback; 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // all done, yay! 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_exec(handle, "COMMIT TRANSACTION", NULL, NULL, NULL); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("COMMIT TRANSACTION failed setting locale\n"); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle); 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto done; 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectrollback: 43078f307d229466bb41c0260d1092dcea82a7bb5f8Vasu Nori if (err != SQLITE_OK) { 43178f307d229466bb41c0260d1092dcea82a7bb5f8Vasu Nori sqlite3_exec(handle, "ROLLBACK TRANSACTION", NULL, NULL, NULL); 43278f307d229466bb41c0260d1092dcea82a7bb5f8Vasu Nori } 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectdone: 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (locale8 != NULL) env->ReleaseStringUTFChars(localeString, locale8); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stmt != NULL) sqlite3_finalize(stmt); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (meta != NULL) sqlite3_free_table(meta); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint native_releaseMemory(JNIEnv *env, jobject clazz) 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Attempt to release as much memory from the 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sqlite3_release_memory(SQLITE_SOFT_HEAP_LIMIT); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod sMethods[] = 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* name, signature, funcPtr */ 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"dbopen", "(Ljava/lang/String;I)V", (void *)dbopen}, 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"dbclose", "()V", (void *)dbclose}, 4513ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori {"enableSqlTracing", "(Ljava/lang/String;)V", (void *)enableSqlTracing}, 4523ef94e25b4c896ecaa85aa2c12b8863ecdf98df0Vasu Nori {"enableSqlProfiling", "(Ljava/lang/String;)V", (void *)enableSqlProfiling}, 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_execSQL", "(Ljava/lang/String;)V", (void *)native_execSQL}, 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"lastInsertRow", "()J", (void *)lastInsertRow}, 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"lastChangeCount", "()I", (void *)lastChangeCount}, 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_setLocale", "(Ljava/lang/String;I)V", (void *)native_setLocale}, 457c3849200fa60b22ea583ba2a6f902d6a632a5e7eVasu Nori {"native_getDbLookaside", "()I", (void *)native_getDbLookaside}, 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"releaseMemory", "()I", (void *)native_releaseMemory}, 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_database_SQLiteDatabase(JNIEnv *env) 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clazz = env->FindClass("android/database/sqlite/SQLiteDatabase"); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clazz == NULL) { 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Can't find android/database/sqlite/SQLiteDatabase\n"); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offset_db_handle = env->GetFieldID(clazz, "mNativeHandle", "I"); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset_db_handle == NULL) { 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Can't find SQLiteDatabase.mNativeHandle\n"); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, "android/database/sqlite/SQLiteDatabase", sMethods, NELEM(sMethods)); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* throw a SQLiteException with a message appropriate for the error in handle */ 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid throw_sqlite3_exception(JNIEnv* env, sqlite3* handle) { 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, handle, NULL); 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* throw a SQLiteException with the given message */ 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid throw_sqlite3_exception(JNIEnv* env, const char* message) { 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, NULL, message); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* throw a SQLiteException with a message appropriate for the error in handle 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project concatenated with the given message 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid throw_sqlite3_exception(JNIEnv* env, sqlite3* handle, const char* message) { 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (handle) { 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, sqlite3_errcode(handle), 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_errmsg(handle), message); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we use SQLITE_OK so that a generic SQLiteException is thrown; 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // any code not specified in the switch statement below would do. 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, SQLITE_OK, "unknown error", message); 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* throw a SQLiteException for a given error code */ 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) { 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (errcode == SQLITE_DONE) { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, errcode, NULL, message); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 509f80efdf7e2b34ab8fec8f47052bf8386616ac312Kenny Root char temp[21]; 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(temp, "error code %d", errcode); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, errcode, temp, message); 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* throw a SQLiteException for a given error code, sqlite3message, and 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project user message 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid throw_sqlite3_exception(JNIEnv* env, int errcode, 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* sqlite3Message, const char* message) { 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* exceptionClass; 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (errcode) { 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_IOERR: 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteDiskIOException"; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_CORRUPT: 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteDatabaseCorruptException"; 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_CONSTRAINT: 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteConstraintException"; 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_ABORT: 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteAbortException"; 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_DONE: 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteDoneException"; 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_FULL: 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteFullException"; 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SQLITE_MISUSE: 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteMisuseException"; 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exceptionClass = "android/database/sqlite/SQLiteException"; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sqlite3Message != NULL && message != NULL) { 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char* fullMessage = (char *)malloc(strlen(sqlite3Message) + strlen(message) + 3); 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fullMessage != NULL) { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strcpy(fullMessage, sqlite3Message); 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strcat(fullMessage, ": "); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strcat(fullMessage, message); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, exceptionClass, fullMessage); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(fullMessage); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, exceptionClass, sqlite3Message); 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sqlite3Message != NULL) { 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, exceptionClass, sqlite3Message); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, exceptionClass, message); 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android 568