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