android_database_SQLiteConnection.cpp revision 676c519ec4509c799049bae5f6b20748ee5210c1
1e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/* 2e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Copyright (C) 2011 The Android Open Source Project 3e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 4e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * you may not use this file except in compliance with the License. 6e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * You may obtain a copy of the License at 7e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 8e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 10e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Unless required by applicable law or agreed to in writing, software 11e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * See the License for the specific language governing permissions and 14e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * limitations under the License. 15e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 16e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 17e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#define LOG_TAG "SQLiteConnection" 18e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 19e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <jni.h> 20e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <JNIHelp.h> 21e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <android_runtime/AndroidRuntime.h> 22e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 23e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <utils/Log.h> 24e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <utils/String8.h> 25e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <utils/String16.h> 26e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <cutils/ashmem.h> 27e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <sys/mman.h> 28e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 29e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <string.h> 30e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <unistd.h> 31e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 3249d2b1864c3dfec6faff74d67cb2527a8f1af5a8Mathias Agopian#include <androidfw/CursorWindow.h> 33e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 34e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <sqlite3.h> 35e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include <sqlite3_android.h> 36e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 37e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include "android_database_SQLiteCommon.h" 38e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 391d9f742e001ed8280fa93fd9ba0b1125ce6d00aeJeff Brown// Set to 1 to use UTF16 storage for localized indexes. 40e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#define UTF16_STORAGE 0 41e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 42e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownnamespace android { 43e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 44676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown/* Busy timeout in milliseconds. 45676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown * If another connection (possibly in another process) has the database locked for 46676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown * longer than this amount of time then SQLite will generate a SQLITE_BUSY error. 47676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown * The SQLITE_BUSY error is then raised as a SQLiteDatabaseLockedException. 48676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown * 49676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown * In ordinary usage, busy timeouts are quite rare. Most databases only ever 50676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown * have a single open connection at a time unless they are using WAL. When using 51676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown * WAL, a timeout could occur if one connection is busy performing an auto-checkpoint 52676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown * operation. The busy timeout needs to be long enough to tolerate slow I/O write 53676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown * operations but not so long as to cause the application to hang indefinitely if 54676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown * there is a problem acquiring a database lock. 55676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown */ 56676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brownstatic const int BUSY_TIMEOUT_MS = 2500; 57676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown 58e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic struct { 59e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jfieldID name; 60e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jfieldID numArgs; 61e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jmethodID dispatchCallback; 62e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} gSQLiteCustomFunctionClassInfo; 63e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 64e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic struct { 65e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jclass clazz; 66e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} gStringClassInfo; 67e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 68e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstruct SQLiteConnection { 69e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Open flags. 70e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Must be kept in sync with the constants defined in SQLiteDatabase.java. 71e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown enum { 72e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown OPEN_READWRITE = 0x00000000, 73e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown OPEN_READONLY = 0x00000001, 74e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown OPEN_READ_MASK = 0x00000001, 75e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown NO_LOCALIZED_COLLATORS = 0x00000010, 76e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown CREATE_IF_NECESSARY = 0x10000000, 77e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown }; 78e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 79e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3* const db; 80e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const int openFlags; 81e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const String8 path; 82e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const String8 label; 83e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 8475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown volatile bool canceled; 8575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 86e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection(sqlite3* db, int openFlags, const String8& path, const String8& label) : 8775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown db(db), openFlags(openFlags), path(path), label(label), canceled(false) { } 88e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown}; 89e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 90e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown// Called each time a statement begins execution, when tracing is enabled. 91e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void sqliteTraceCallback(void *data, const char *sql) { 92e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = static_cast<SQLiteConnection*>(data); 93e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOG(LOG_VERBOSE, SQLITE_TRACE_TAG, "%s: \"%s\"\n", 94e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection->label.string(), sql); 95e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 96e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 97e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown// Called each time a statement finishes execution, when profiling is enabled. 98e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void sqliteProfileCallback(void *data, const char *sql, sqlite3_uint64 tm) { 99e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = static_cast<SQLiteConnection*>(data); 100e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOG(LOG_VERBOSE, SQLITE_PROFILE_TAG, "%s: \"%s\" took %0.3f ms\n", 101e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown connection->label.string(), sql, tm * 0.000001f); 102e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 103e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 10475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown// Called after each SQLite VM instruction when cancelation is enabled. 10575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brownstatic int sqliteProgressHandlerCallback(void* data) { 10675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown SQLiteConnection* connection = static_cast<SQLiteConnection*>(data); 10775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return connection->canceled; 10875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown} 10975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 110e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 111e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jint nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFlags, 112e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jstring labelStr, jboolean enableTrace, jboolean enableProfile) { 113e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int sqliteFlags; 114e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (openFlags & SQLiteConnection::CREATE_IF_NECESSARY) { 115e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; 116e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (openFlags & SQLiteConnection::OPEN_READONLY) { 117e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqliteFlags = SQLITE_OPEN_READONLY; 118e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 119e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqliteFlags = SQLITE_OPEN_READWRITE; 120e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 121e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 122e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const char* pathChars = env->GetStringUTFChars(pathStr, NULL); 123e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown String8 path(pathChars); 124e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->ReleaseStringUTFChars(pathStr, pathChars); 125e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 126e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const char* labelChars = env->GetStringUTFChars(labelStr, NULL); 127e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown String8 label(labelChars); 128e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->ReleaseStringUTFChars(labelStr, labelChars); 129e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 130e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3* db; 131e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_open_v2(path.string(), &db, sqliteFlags, NULL); 132e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 133e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception_errcode(env, err, "Could not open database"); 134e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return 0; 135e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 136e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 137330ec91e02406ba0d62e5672c6f0e2ed271f6898Jeff Brown // Check that the database is really read/write when that is what we asked for. 138330ec91e02406ba0d62e5672c6f0e2ed271f6898Jeff Brown if ((sqliteFlags & SQLITE_OPEN_READWRITE) && sqlite3_db_readonly(db, NULL)) { 139330ec91e02406ba0d62e5672c6f0e2ed271f6898Jeff Brown throw_sqlite3_exception(env, db, "Could not open the database in read/write mode."); 140330ec91e02406ba0d62e5672c6f0e2ed271f6898Jeff Brown sqlite3_close(db); 141330ec91e02406ba0d62e5672c6f0e2ed271f6898Jeff Brown return 0; 142330ec91e02406ba0d62e5672c6f0e2ed271f6898Jeff Brown } 143330ec91e02406ba0d62e5672c6f0e2ed271f6898Jeff Brown 144676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown // Set the default busy handler to retry automatically before returning SQLITE_BUSY. 145676c519ec4509c799049bae5f6b20748ee5210c1Jeff Brown err = sqlite3_busy_timeout(db, BUSY_TIMEOUT_MS); 146e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 147e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, db, "Could not set busy timeout"); 148e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_close(db); 149e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return 0; 150e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 151e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 152e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Register custom Android functions. 153e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown err = register_android_functions(db, UTF16_STORAGE); 154e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err) { 155e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, db, "Could not register Android SQL functions."); 156e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_close(db); 157e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return 0; 158e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 159e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 160e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Create wrapper object. 161e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = new SQLiteConnection(db, openFlags, path, label); 162e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 163e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Enable tracing and profiling if requested. 164e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (enableTrace) { 165e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_trace(db, &sqliteTraceCallback, connection); 166e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 167e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (enableProfile) { 168e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_profile(db, &sqliteProfileCallback, connection); 169e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 170e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 171e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGV("Opened connection %p with label '%s'", db, label.string()); 172e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return reinterpret_cast<jint>(connection); 173e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 174e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 175e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void nativeClose(JNIEnv* env, jclass clazz, jint connectionPtr) { 176e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 177e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 178e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (connection) { 179e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGV("Closing connection %p", connection->db); 180e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_close(connection->db); 181e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 182e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // This can happen if sub-objects aren't closed first. Make sure the caller knows. 183e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGE("sqlite3_close(%p) failed: %d", connection->db, err); 184e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, "Count not close db."); 185e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return; 186e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 187e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 188e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown delete connection; 189e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 190e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 191e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 192e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown// Called each time a custom function is evaluated. 193e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void sqliteCustomFunctionCallback(sqlite3_context *context, 194e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int argc, sqlite3_value **argv) { 195e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown JNIEnv* env = AndroidRuntime::getJNIEnv(); 196e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 197e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Get the callback function object. 198e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Create a new local reference to it in case the callback tries to do something 199e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // dumb like unregister the function (thereby destroying the global ref) while it is running. 200e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jobject functionObjGlobal = reinterpret_cast<jobject>(sqlite3_user_data(context)); 201e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jobject functionObj = env->NewLocalRef(functionObjGlobal); 202e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 203e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jobjectArray argsArray = env->NewObjectArray(argc, gStringClassInfo.clazz, NULL); 204e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (argsArray) { 205e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (int i = 0; i < argc; i++) { 206e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const jchar* arg = static_cast<const jchar*>(sqlite3_value_text16(argv[i])); 207e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!arg) { 208e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGW("NULL argument in custom_function_callback. This should not happen."); 209e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 210e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown size_t argLen = sqlite3_value_bytes16(argv[i]) / sizeof(jchar); 211e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jstring argStr = env->NewString(arg, argLen); 212e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!argStr) { 213e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown goto error; // out of memory error 214e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 215e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->SetObjectArrayElement(argsArray, i, argStr); 216e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->DeleteLocalRef(argStr); 217e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 218e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 219e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 220e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // TODO: Support functions that return values. 221e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->CallVoidMethod(functionObj, 222e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown gSQLiteCustomFunctionClassInfo.dispatchCallback, argsArray); 223e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 224e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownerror: 225e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->DeleteLocalRef(argsArray); 226e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 227e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 228e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->DeleteLocalRef(functionObj); 229e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 230e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (env->ExceptionCheck()) { 231e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGE("An exception was thrown by custom SQLite function."); 232e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOGE_EX(env); 233e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->ExceptionClear(); 234e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 235e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 236e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 237e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown// Called when a custom function is destroyed. 238e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void sqliteCustomFunctionDestructor(void* data) { 239e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jobject functionObjGlobal = reinterpret_cast<jobject>(data); 240e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 241e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown JNIEnv* env = AndroidRuntime::getJNIEnv(); 242e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->DeleteGlobalRef(functionObjGlobal); 243e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 244e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 245e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void nativeRegisterCustomFunction(JNIEnv* env, jclass clazz, jint connectionPtr, 246e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jobject functionObj) { 247e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 248e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 249e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jstring nameStr = jstring(env->GetObjectField( 250e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown functionObj, gSQLiteCustomFunctionClassInfo.name)); 251e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint numArgs = env->GetIntField(functionObj, gSQLiteCustomFunctionClassInfo.numArgs); 252e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 253e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jobject functionObjGlobal = env->NewGlobalRef(functionObj); 254e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 255e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const char* name = env->GetStringUTFChars(nameStr, NULL); 256e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_create_function_v2(connection->db, name, numArgs, SQLITE_UTF16, 257e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown reinterpret_cast<void*>(functionObjGlobal), 258e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown &sqliteCustomFunctionCallback, NULL, NULL, &sqliteCustomFunctionDestructor); 259e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->ReleaseStringUTFChars(nameStr, name); 260e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 261e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 262e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGE("sqlite3_create_function returned %d", err); 263e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->DeleteGlobalRef(functionObjGlobal); 264e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db); 265e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return; 266e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 267e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 268e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 2691d9f742e001ed8280fa93fd9ba0b1125ce6d00aeJeff Brownstatic void nativeRegisterLocalizedCollators(JNIEnv* env, jclass clazz, jint connectionPtr, 2701d9f742e001ed8280fa93fd9ba0b1125ce6d00aeJeff Brown jstring localeStr) { 271e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 272e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 2731d9f742e001ed8280fa93fd9ba0b1125ce6d00aeJeff Brown const char* locale = env->GetStringUTFChars(localeStr, NULL); 2741d9f742e001ed8280fa93fd9ba0b1125ce6d00aeJeff Brown int err = register_localized_collators(connection->db, locale, UTF16_STORAGE); 2751d9f742e001ed8280fa93fd9ba0b1125ce6d00aeJeff Brown env->ReleaseStringUTFChars(localeStr, locale); 276e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 277e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 278e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db); 279e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 280e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 281e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 282e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jint nativePrepareStatement(JNIEnv* env, jclass clazz, jint connectionPtr, 283e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jstring sqlString) { 284e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 285e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 286e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jsize sqlLength = env->GetStringLength(sqlString); 287e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const jchar* sql = env->GetStringCritical(sqlString, NULL); 288e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement; 289e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_prepare16_v2(connection->db, 290e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sql, sqlLength * sizeof(jchar), &statement, NULL); 291e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->ReleaseStringCritical(sqlString, sql); 292e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 293e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 294e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Error messages like 'near ")": syntax error' are not 295e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // always helpful enough, so construct an error string that 296e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // includes the query itself. 297e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const char *query = env->GetStringUTFChars(sqlString, NULL); 298e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown char *message = (char*) malloc(strlen(query) + 50); 299e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (message) { 300e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown strcpy(message, ", while compiling: "); // less than 50 chars 301e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown strcat(message, query); 302e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 303e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->ReleaseStringUTFChars(sqlString, query); 304e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, message); 305e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown free(message); 306e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return 0; 307e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 308e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 309e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGV("Prepared statement %p on connection %p", statement, connection->db); 310e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return reinterpret_cast<jint>(statement); 311e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 312e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 313e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void nativeFinalizeStatement(JNIEnv* env, jclass clazz, jint connectionPtr, 314e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr) { 315e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 316e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 317e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 318958cbbab6a35e1668419a2f7e2a2b75b9c8db807Jeff Brown // We ignore the result of sqlite3_finalize because it is really telling us about 319958cbbab6a35e1668419a2f7e2a2b75b9c8db807Jeff Brown // whether any errors occurred while executing the statement. The statement itself 320958cbbab6a35e1668419a2f7e2a2b75b9c8db807Jeff Brown // is always finalized regardless. 321e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGV("Finalized statement %p on connection %p", statement, connection->db); 322958cbbab6a35e1668419a2f7e2a2b75b9c8db807Jeff Brown sqlite3_finalize(statement); 323e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 324e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 325e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jint nativeGetParameterCount(JNIEnv* env, jclass clazz, jint connectionPtr, 326e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr) { 327e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 328e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 329e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 330e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return sqlite3_bind_parameter_count(statement); 331e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 332e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 333e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jboolean nativeIsReadOnly(JNIEnv* env, jclass clazz, jint connectionPtr, 334e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr) { 335e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 336e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 337e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 338e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return sqlite3_stmt_readonly(statement) != 0; 339e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 340e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 341e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jint nativeGetColumnCount(JNIEnv* env, jclass clazz, jint connectionPtr, 342e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr) { 343e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 344e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 345e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 346e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return sqlite3_column_count(statement); 347e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 348e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 349e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jstring nativeGetColumnName(JNIEnv* env, jclass clazz, jint connectionPtr, 350e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr, jint index) { 351e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 352e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 353e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 354e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const jchar* name = static_cast<const jchar*>(sqlite3_column_name16(statement, index)); 355e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (name) { 356e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown size_t length = 0; 357e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown while (name[length]) { 358e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown length += 1; 359e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 360e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return env->NewString(name, length); 361e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 362e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return NULL; 363e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 364e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 365e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void nativeBindNull(JNIEnv* env, jclass clazz, jint connectionPtr, 366e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr, jint index) { 367e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 368e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 369e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 370e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_bind_null(statement, index); 371e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 372e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, NULL); 373e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 374e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 375e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 376e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void nativeBindLong(JNIEnv* env, jclass clazz, jint connectionPtr, 377e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr, jint index, jlong value) { 378e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 379e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 380e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 381e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_bind_int64(statement, index, value); 382e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 383e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, NULL); 384e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 385e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 386e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 387e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void nativeBindDouble(JNIEnv* env, jclass clazz, jint connectionPtr, 388e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr, jint index, jdouble value) { 389e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 390e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 391e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 392e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_bind_double(statement, index, value); 393e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 394e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, NULL); 395e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 396e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 397e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 398e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void nativeBindString(JNIEnv* env, jclass clazz, jint connectionPtr, 399e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr, jint index, jstring valueString) { 400e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 401e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 402e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 403e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jsize valueLength = env->GetStringLength(valueString); 404e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const jchar* value = env->GetStringCritical(valueString, NULL); 405e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_bind_text16(statement, index, value, valueLength * sizeof(jchar), 406e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLITE_TRANSIENT); 407e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->ReleaseStringCritical(valueString, value); 408e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 409e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, NULL); 410e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 411e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 412e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 413e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void nativeBindBlob(JNIEnv* env, jclass clazz, jint connectionPtr, 414e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr, jint index, jbyteArray valueArray) { 415e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 416e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 417e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 418e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jsize valueLength = env->GetArrayLength(valueArray); 419e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jbyte* value = static_cast<jbyte*>(env->GetPrimitiveArrayCritical(valueArray, NULL)); 420e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_bind_blob(statement, index, value, valueLength, SQLITE_TRANSIENT); 421e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown env->ReleasePrimitiveArrayCritical(valueArray, value, JNI_ABORT); 422e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 423e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, NULL); 424e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 425e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 426e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 427e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void nativeResetStatementAndClearBindings(JNIEnv* env, jclass clazz, jint connectionPtr, 428e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr) { 429e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 430e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 431e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 432e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_reset(statement); 433e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err == SQLITE_OK) { 434e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown err = sqlite3_clear_bindings(statement); 435e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 436e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_OK) { 437e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, NULL); 438e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 439e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 440e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 441e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic int executeNonQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement) { 442e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_step(statement); 443e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err == SQLITE_ROW) { 444e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, 445e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown "Queries can be performed using SQLiteDatabase query or rawQuery methods only."); 446e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (err != SQLITE_DONE) { 447e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception_errcode(env, err, sqlite3_errmsg(connection->db)); 448e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 449e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return err; 450e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 451e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 452e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic void nativeExecute(JNIEnv* env, jclass clazz, jint connectionPtr, 453e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint statementPtr) { 454e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 455e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 456e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 457e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown executeNonQuery(env, connection, statement); 458e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 459e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 460e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jint nativeExecuteForChangedRowCount(JNIEnv* env, jclass clazz, 461e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint connectionPtr, jint statementPtr) { 462e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 463e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 464e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 465e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = executeNonQuery(env, connection, statement); 466e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return err == SQLITE_DONE ? sqlite3_changes(connection->db) : -1; 467e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 468e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 469e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jlong nativeExecuteForLastInsertedRowId(JNIEnv* env, jclass clazz, 470e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint connectionPtr, jint statementPtr) { 471e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 472e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 473e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 474e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = executeNonQuery(env, connection, statement); 475e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return err == SQLITE_DONE && sqlite3_changes(connection->db) > 0 476e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ? sqlite3_last_insert_rowid(connection->db) : -1; 477e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 478e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 479e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic int executeOneRowQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement) { 480e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_step(statement); 481e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err != SQLITE_ROW) { 482e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception_errcode(env, err, sqlite3_errmsg(connection->db)); 483e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 484e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return err; 485e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 486e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 487e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jlong nativeExecuteForLong(JNIEnv* env, jclass clazz, 488e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint connectionPtr, jint statementPtr) { 489e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 490e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 491e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 492e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = executeOneRowQuery(env, connection, statement); 493e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err == SQLITE_ROW && sqlite3_column_count(statement) >= 1) { 494e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return sqlite3_column_int64(statement, 0); 495e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 496e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return -1; 497e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 498e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 499e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jstring nativeExecuteForString(JNIEnv* env, jclass clazz, 500e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint connectionPtr, jint statementPtr) { 501e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 502e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 503e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 504e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = executeOneRowQuery(env, connection, statement); 505e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err == SQLITE_ROW && sqlite3_column_count(statement) >= 1) { 506e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const jchar* text = static_cast<const jchar*>(sqlite3_column_text16(statement, 0)); 507e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (text) { 508e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown size_t length = sqlite3_column_bytes16(statement, 0) / sizeof(jchar); 509e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return env->NewString(text, length); 510e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 511e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 512e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return NULL; 513e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 514e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 515e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic int createAshmemRegionWithData(JNIEnv* env, const void* data, size_t length) { 516e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int error = 0; 517e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int fd = ashmem_create_region(NULL, length); 518e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (fd < 0) { 519e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown error = errno; 520e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGE("ashmem_create_region failed: %s", strerror(error)); 521e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 522e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (length > 0) { 523e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown void* ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 524e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (ptr == MAP_FAILED) { 525e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown error = errno; 526e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGE("mmap failed: %s", strerror(error)); 527e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 528e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown memcpy(ptr, data, length); 529e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown munmap(ptr, length); 530e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 531e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 532e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 533e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!error) { 534e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (ashmem_set_prot_region(fd, PROT_READ) < 0) { 535e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown error = errno; 536e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGE("ashmem_set_prot_region failed: %s", strerror(errno)); 537e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 538e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return fd; 539e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 540e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 541e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 542e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown close(fd); 543e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 544e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 545e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jniThrowIOException(env, error); 546e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return -1; 547e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 548e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 549e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jint nativeExecuteForBlobFileDescriptor(JNIEnv* env, jclass clazz, 550e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint connectionPtr, jint statementPtr) { 551e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 552e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 553e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 554e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = executeOneRowQuery(env, connection, statement); 555e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err == SQLITE_ROW && sqlite3_column_count(statement) >= 1) { 556e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const void* blob = sqlite3_column_blob(statement, 0); 557e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (blob) { 558e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int length = sqlite3_column_bytes(statement, 0); 559e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (length >= 0) { 560e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return createAshmemRegionWithData(env, blob, length); 561e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 562e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 563e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 564e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return -1; 565e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 566e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 567e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownenum CopyRowResult { 568e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown CPR_OK, 569e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown CPR_FULL, 570e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown CPR_ERROR, 571e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown}; 572e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 573e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic CopyRowResult copyRow(JNIEnv* env, CursorWindow* window, 574e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement, int numColumns, int startPos, int addedRows) { 575e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Allocate a new field directory for the row. 576e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown status_t status = window->allocRow(); 577e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (status) { 578e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("Failed allocating fieldDir at startPos %d row %d, error=%d", 579e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown startPos, addedRows, status); 580e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return CPR_FULL; 581e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 582e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 583e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Pack the row into the window. 584e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown CopyRowResult result = CPR_OK; 585e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (int i = 0; i < numColumns; i++) { 586e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int type = sqlite3_column_type(statement, i); 587e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (type == SQLITE_TEXT) { 588e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // TEXT data 589e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const char* text = reinterpret_cast<const char*>( 590e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_column_text(statement, i)); 591e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // SQLite does not include the NULL terminator in size, but does 592e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // ensure all strings are NULL terminated, so increase size by 593e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // one to make sure we store the terminator. 594e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown size_t sizeIncludingNull = sqlite3_column_bytes(statement, i) + 1; 595e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown status = window->putString(addedRows, i, text, sizeIncludingNull); 596e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (status) { 597e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("Failed allocating %u bytes for text at %d,%d, error=%d", 598e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sizeIncludingNull, startPos + addedRows, i, status); 599e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown result = CPR_FULL; 600e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 601e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 602e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("%d,%d is TEXT with %u bytes", 603e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown startPos + addedRows, i, sizeIncludingNull); 604e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (type == SQLITE_INTEGER) { 605e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // INTEGER data 606e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int64_t value = sqlite3_column_int64(statement, i); 607e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown status = window->putLong(addedRows, i, value); 608e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (status) { 609e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("Failed allocating space for a long in column %d, error=%d", 610e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown i, status); 611e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown result = CPR_FULL; 612e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 613e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 614e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("%d,%d is INTEGER 0x%016llx", startPos + addedRows, i, value); 615e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (type == SQLITE_FLOAT) { 616e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // FLOAT data 617e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown double value = sqlite3_column_double(statement, i); 618e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown status = window->putDouble(addedRows, i, value); 619e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (status) { 620e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("Failed allocating space for a double in column %d, error=%d", 621e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown i, status); 622e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown result = CPR_FULL; 623e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 624e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 625e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("%d,%d is FLOAT %lf", startPos + addedRows, i, value); 626e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (type == SQLITE_BLOB) { 627e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // BLOB data 628e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown const void* blob = sqlite3_column_blob(statement, i); 629e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown size_t size = sqlite3_column_bytes(statement, i); 630e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown status = window->putBlob(addedRows, i, blob, size); 631e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (status) { 632e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("Failed allocating %u bytes for blob at %d,%d, error=%d", 633e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown size, startPos + addedRows, i, status); 634e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown result = CPR_FULL; 635e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 636e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 637e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("%d,%d is Blob with %u bytes", 638e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown startPos + addedRows, i, size); 639e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (type == SQLITE_NULL) { 640e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // NULL field 641e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown status = window->putNull(addedRows, i); 642e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (status) { 643e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("Failed allocating space for a null in column %d, error=%d", 644e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown i, status); 645e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown result = CPR_FULL; 646e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 647e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 648e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 649e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("%d,%d is NULL", startPos + addedRows, i); 650e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 651e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Unknown data 652e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGE("Unknown column type when filling database window"); 653e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, "Unknown column type when filling window"); 654e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown result = CPR_ERROR; 655e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 656e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 657e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 658e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 659e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Free the last row if if was not successfully copied. 660e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (result != CPR_OK) { 661e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown window->freeLastRow(); 662e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 663e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return result; 664e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 665e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 666e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jlong nativeExecuteForCursorWindow(JNIEnv* env, jclass clazz, 667e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint connectionPtr, jint statementPtr, jint windowPtr, 668e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jint startPos, jint requiredPos, jboolean countAllRows) { 669e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 670e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 671e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 672e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 673e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown status_t status = window->clear(); 674e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (status) { 675e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown String8 msg; 676e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.appendFormat("Failed to clear the cursor window, status=%d", status); 677e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, msg.string()); 678e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return 0; 679e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 680e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 681e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int numColumns = sqlite3_column_count(statement); 682e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown status = window->setNumColumns(numColumns); 683e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (status) { 684e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown String8 msg; 685e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown msg.appendFormat("Failed to set the cursor window column count to %d, status=%d", 686e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown numColumns, status); 687e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, msg.string()); 688e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return 0; 689e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 690e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 691e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int retryCount = 0; 692e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int totalRows = 0; 693e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int addedRows = 0; 694e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown bool windowFull = false; 695e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown bool gotException = false; 696e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown while (!gotException && (!windowFull || countAllRows)) { 697e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int err = sqlite3_step(statement); 698e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (err == SQLITE_ROW) { 699e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("Stepped statement %p to row %d", statement, totalRows); 700e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown retryCount = 0; 701e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown totalRows += 1; 702e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 703e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Skip the row if the window is full or we haven't reached the start position yet. 704e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (startPos >= totalRows || windowFull) { 705e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown continue; 706e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 707e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 708e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown CopyRowResult cpr = copyRow(env, window, statement, numColumns, startPos, addedRows); 709e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (cpr == CPR_FULL && addedRows && startPos + addedRows < requiredPos) { 710e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // We filled the window before we got to the one row that we really wanted. 711e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Clear the window and start filling it again from here. 712e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // TODO: Would be nicer if we could progressively replace earlier rows. 713e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown window->clear(); 714e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown window->setNumColumns(numColumns); 715e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown startPos += addedRows; 716e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown addedRows = 0; 717e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown cpr = copyRow(env, window, statement, numColumns, startPos, addedRows); 718e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 719e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 720e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (cpr == CPR_OK) { 721e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown addedRows += 1; 722e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (cpr == CPR_FULL) { 723e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown windowFull = true; 724e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 725e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown gotException = true; 726e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 727e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (err == SQLITE_DONE) { 728e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // All rows processed, bail 729e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("Processed all rows"); 730e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 731e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else if (err == SQLITE_LOCKED || err == SQLITE_BUSY) { 732e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // The table is locked, retry 733e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("Database locked, retrying"); 734e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (retryCount > 50) { 735e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGE("Bailing on database busy retry"); 736e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db, "retrycount exceeded"); 737e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown gotException = true; 738e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 739e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Sleep to give the thread holding the lock a chance to finish 740e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown usleep(1000); 741e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown retryCount++; 742e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 743e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 744e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw_sqlite3_exception(env, connection->db); 745e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown gotException = true; 746e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 747e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 748e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 749e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_WINDOW("Resetting statement %p after fetching %d rows and adding %d rows" 750e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown "to the window in %d bytes", 751e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown statement, totalRows, addedRows, window->size() - window->freeSpace()); 752e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_reset(statement); 753e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 754e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Report the total number of rows on request. 755e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (startPos > totalRows) { 756e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown ALOGE("startPos %d > actual rows %d", startPos, totalRows); 757e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 758e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jlong result = jlong(startPos) << 32 | jlong(totalRows); 759e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return result; 760e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 761e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 762e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic jint nativeGetDbLookaside(JNIEnv* env, jobject clazz, jint connectionPtr) { 763e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 764e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 765e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int cur = -1; 766e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown int unused; 767e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sqlite3_db_status(connection->db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &unused, 0); 768e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return cur; 769e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 770e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 77175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brownstatic void nativeCancel(JNIEnv* env, jobject clazz, jint connectionPtr) { 77275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 77375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown connection->canceled = true; 77475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown} 77575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 77675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brownstatic void nativeResetCancel(JNIEnv* env, jobject clazz, jint connectionPtr, 77775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown jboolean cancelable) { 77875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 77975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown connection->canceled = false; 78075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 78175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown if (cancelable) { 78275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown sqlite3_progress_handler(connection->db, 4, sqliteProgressHandlerCallback, 78375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown connection); 78475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } else { 78575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown sqlite3_progress_handler(connection->db, 0, NULL, NULL); 78675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 78775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown} 78875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 789e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 790e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownstatic JNINativeMethod sMethods[] = 791e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown{ 792e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /* name, signature, funcPtr */ 793e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeOpen", "(Ljava/lang/String;ILjava/lang/String;ZZ)I", 794e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeOpen }, 795e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeClose", "(I)V", 796e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeClose }, 797e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeRegisterCustomFunction", "(ILandroid/database/sqlite/SQLiteCustomFunction;)V", 798e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeRegisterCustomFunction }, 7991d9f742e001ed8280fa93fd9ba0b1125ce6d00aeJeff Brown { "nativeRegisterLocalizedCollators", "(ILjava/lang/String;)V", 8001d9f742e001ed8280fa93fd9ba0b1125ce6d00aeJeff Brown (void*)nativeRegisterLocalizedCollators }, 801e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativePrepareStatement", "(ILjava/lang/String;)I", 802e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativePrepareStatement }, 803e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeFinalizeStatement", "(II)V", 804e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeFinalizeStatement }, 805e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeGetParameterCount", "(II)I", 806e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeGetParameterCount }, 807e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeIsReadOnly", "(II)Z", 808e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeIsReadOnly }, 809e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeGetColumnCount", "(II)I", 810e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeGetColumnCount }, 811e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeGetColumnName", "(III)Ljava/lang/String;", 812e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeGetColumnName }, 813e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeBindNull", "(III)V", 814e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeBindNull }, 815e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeBindLong", "(IIIJ)V", 816e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeBindLong }, 817e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeBindDouble", "(IIID)V", 818e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeBindDouble }, 819e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeBindString", "(IIILjava/lang/String;)V", 820e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeBindString }, 821e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeBindBlob", "(III[B)V", 822e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeBindBlob }, 823e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeResetStatementAndClearBindings", "(II)V", 824e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeResetStatementAndClearBindings }, 825e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeExecute", "(II)V", 826e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeExecute }, 827e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeExecuteForLong", "(II)J", 828e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeExecuteForLong }, 829e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeExecuteForString", "(II)Ljava/lang/String;", 830e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeExecuteForString }, 831e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeExecuteForBlobFileDescriptor", "(II)I", 832e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeExecuteForBlobFileDescriptor }, 833e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeExecuteForChangedRowCount", "(II)I", 834e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeExecuteForChangedRowCount }, 835e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeExecuteForLastInsertedRowId", "(II)J", 836e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeExecuteForLastInsertedRowId }, 837e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeExecuteForCursorWindow", "(IIIIIZ)J", 838e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeExecuteForCursorWindow }, 839e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown { "nativeGetDbLookaside", "(I)I", 840e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown (void*)nativeGetDbLookaside }, 84175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown { "nativeCancel", "(I)V", 84275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown (void*)nativeCancel }, 84375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown { "nativeResetCancel", "(IZ)V", 84475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown (void*)nativeResetCancel }, 845e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown}; 846e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 847e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#define FIND_CLASS(var, className) \ 848e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown var = env->FindClass(className); \ 849e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_FATAL_IF(! var, "Unable to find class " className); 850e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 851e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \ 852e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown var = env->GetMethodID(clazz, methodName, fieldDescriptor); \ 853e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_FATAL_IF(! var, "Unable to find method" methodName); 854e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 855e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 856e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 857e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown LOG_FATAL_IF(! var, "Unable to find field " fieldName); 858e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 859e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownint register_android_database_SQLiteConnection(JNIEnv *env) 860e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown{ 861e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown jclass clazz; 862e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown FIND_CLASS(clazz, "android/database/sqlite/SQLiteCustomFunction"); 863e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 864e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown GET_FIELD_ID(gSQLiteCustomFunctionClassInfo.name, clazz, 865e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown "name", "Ljava/lang/String;"); 866e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown GET_FIELD_ID(gSQLiteCustomFunctionClassInfo.numArgs, clazz, 867e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown "numArgs", "I"); 868e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown GET_METHOD_ID(gSQLiteCustomFunctionClassInfo.dispatchCallback, 869e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown clazz, "dispatchCallback", "([Ljava/lang/String;)V"); 870e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 871e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown FIND_CLASS(clazz, "java/lang/String"); 872e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown gStringClassInfo.clazz = jclass(env->NewGlobalRef(clazz)); 873e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 874e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return AndroidRuntime::registerNativeMethods(env, "android/database/sqlite/SQLiteConnection", 875e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown sMethods, NELEM(sMethods)); 876e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 877e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 878e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} // namespace android 879