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