1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "SQLiteConnection" 18 19 #include <jni.h> 20 #include <nativehelper/JNIHelp.h> 21 #include <android_runtime/AndroidRuntime.h> 22 #include <android_runtime/Log.h> 23 24 #include <utils/Log.h> 25 #include <utils/String8.h> 26 #include <utils/String16.h> 27 #include <cutils/ashmem.h> 28 #include <sys/mman.h> 29 30 #include <string.h> 31 #include <unistd.h> 32 33 #include <androidfw/CursorWindow.h> 34 35 #include <sqlite3.h> 36 #include <sqlite3_android.h> 37 38 #include "android_database_SQLiteCommon.h" 39 40 #include "core_jni_helpers.h" 41 42 // Set to 1 to use UTF16 storage for localized indexes. 43 #define UTF16_STORAGE 0 44 45 namespace android { 46 47 /* Busy timeout in milliseconds. 48 * If another connection (possibly in another process) has the database locked for 49 * longer than this amount of time then SQLite will generate a SQLITE_BUSY error. 50 * The SQLITE_BUSY error is then raised as a SQLiteDatabaseLockedException. 51 * 52 * In ordinary usage, busy timeouts are quite rare. Most databases only ever 53 * have a single open connection at a time unless they are using WAL. When using 54 * WAL, a timeout could occur if one connection is busy performing an auto-checkpoint 55 * operation. The busy timeout needs to be long enough to tolerate slow I/O write 56 * operations but not so long as to cause the application to hang indefinitely if 57 * there is a problem acquiring a database lock. 58 */ 59 static const int BUSY_TIMEOUT_MS = 2500; 60 61 static struct { 62 jmethodID apply; 63 } gUnaryOperator; 64 65 static struct { 66 jmethodID apply; 67 } gBinaryOperator; 68 69 struct SQLiteConnection { 70 // Open flags. 71 // Must be kept in sync with the constants defined in SQLiteDatabase.java. 72 enum { 73 OPEN_READWRITE = 0x00000000, 74 OPEN_READONLY = 0x00000001, 75 OPEN_READ_MASK = 0x00000001, 76 NO_LOCALIZED_COLLATORS = 0x00000010, 77 CREATE_IF_NECESSARY = 0x10000000, 78 }; 79 80 sqlite3* const db; 81 const int openFlags; 82 const String8 path; 83 const String8 label; 84 85 volatile bool canceled; 86 87 SQLiteConnection(sqlite3* db, int openFlags, const String8& path, const String8& label) : 88 db(db), openFlags(openFlags), path(path), label(label), canceled(false) { } 89 }; 90 91 // Called each time a statement begins execution, when tracing is enabled. 92 static void sqliteTraceCallback(void *data, const char *sql) { 93 SQLiteConnection* connection = static_cast<SQLiteConnection*>(data); 94 ALOG(LOG_VERBOSE, SQLITE_TRACE_TAG, "%s: \"%s\"\n", 95 connection->label.string(), sql); 96 } 97 98 // Called each time a statement finishes execution, when profiling is enabled. 99 static void sqliteProfileCallback(void *data, const char *sql, sqlite3_uint64 tm) { 100 SQLiteConnection* connection = static_cast<SQLiteConnection*>(data); 101 ALOG(LOG_VERBOSE, SQLITE_PROFILE_TAG, "%s: \"%s\" took %0.3f ms\n", 102 connection->label.string(), sql, tm * 0.000001f); 103 } 104 105 // Called after each SQLite VM instruction when cancelation is enabled. 106 static int sqliteProgressHandlerCallback(void* data) { 107 SQLiteConnection* connection = static_cast<SQLiteConnection*>(data); 108 return connection->canceled; 109 } 110 111 112 static jlong nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFlags, 113 jstring labelStr, jboolean enableTrace, jboolean enableProfile, jint lookasideSz, 114 jint lookasideCnt) { 115 int sqliteFlags; 116 if (openFlags & SQLiteConnection::CREATE_IF_NECESSARY) { 117 sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; 118 } else if (openFlags & SQLiteConnection::OPEN_READONLY) { 119 sqliteFlags = SQLITE_OPEN_READONLY; 120 } else { 121 sqliteFlags = SQLITE_OPEN_READWRITE; 122 } 123 124 const char* pathChars = env->GetStringUTFChars(pathStr, NULL); 125 String8 path(pathChars); 126 env->ReleaseStringUTFChars(pathStr, pathChars); 127 128 const char* labelChars = env->GetStringUTFChars(labelStr, NULL); 129 String8 label(labelChars); 130 env->ReleaseStringUTFChars(labelStr, labelChars); 131 132 sqlite3* db; 133 int err = sqlite3_open_v2(path.string(), &db, sqliteFlags, NULL); 134 if (err != SQLITE_OK) { 135 throw_sqlite3_exception_errcode(env, err, "Could not open database"); 136 return 0; 137 } 138 139 if (lookasideSz >= 0 && lookasideCnt >= 0) { 140 int err = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, NULL, lookasideSz, lookasideCnt); 141 if (err != SQLITE_OK) { 142 ALOGE("sqlite3_db_config(..., %d, %d) failed: %d", lookasideSz, lookasideCnt, err); 143 throw_sqlite3_exception(env, db, "Cannot set lookaside"); 144 sqlite3_close(db); 145 return 0; 146 } 147 } 148 149 // Check that the database is really read/write when that is what we asked for. 150 if ((sqliteFlags & SQLITE_OPEN_READWRITE) && sqlite3_db_readonly(db, NULL)) { 151 throw_sqlite3_exception(env, db, "Could not open the database in read/write mode."); 152 sqlite3_close(db); 153 return 0; 154 } 155 156 // Set the default busy handler to retry automatically before returning SQLITE_BUSY. 157 err = sqlite3_busy_timeout(db, BUSY_TIMEOUT_MS); 158 if (err != SQLITE_OK) { 159 throw_sqlite3_exception(env, db, "Could not set busy timeout"); 160 sqlite3_close(db); 161 return 0; 162 } 163 164 // Register custom Android functions. 165 err = register_android_functions(db, UTF16_STORAGE); 166 if (err) { 167 throw_sqlite3_exception(env, db, "Could not register Android SQL functions."); 168 sqlite3_close(db); 169 return 0; 170 } 171 172 // Create wrapper object. 173 SQLiteConnection* connection = new SQLiteConnection(db, openFlags, path, label); 174 175 // Enable tracing and profiling if requested. 176 if (enableTrace) { 177 sqlite3_trace(db, &sqliteTraceCallback, connection); 178 } 179 if (enableProfile) { 180 sqlite3_profile(db, &sqliteProfileCallback, connection); 181 } 182 183 ALOGV("Opened connection %p with label '%s'", db, label.string()); 184 return reinterpret_cast<jlong>(connection); 185 } 186 187 static void nativeClose(JNIEnv* env, jclass clazz, jlong connectionPtr) { 188 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 189 190 if (connection) { 191 ALOGV("Closing connection %p", connection->db); 192 int err = sqlite3_close(connection->db); 193 if (err != SQLITE_OK) { 194 // This can happen if sub-objects aren't closed first. Make sure the caller knows. 195 ALOGE("sqlite3_close(%p) failed: %d", connection->db, err); 196 throw_sqlite3_exception(env, connection->db, "Count not close db."); 197 return; 198 } 199 200 delete connection; 201 } 202 } 203 204 static void sqliteCustomScalarFunctionCallback(sqlite3_context *context, 205 int argc, sqlite3_value **argv) { 206 JNIEnv* env = AndroidRuntime::getJNIEnv(); 207 jobject functionObjGlobal = reinterpret_cast<jobject>(sqlite3_user_data(context)); 208 ScopedLocalRef<jobject> functionObj(env, env->NewLocalRef(functionObjGlobal)); 209 ScopedLocalRef<jstring> argString(env, 210 env->NewStringUTF(reinterpret_cast<const char*>(sqlite3_value_text(argv[0])))); 211 ScopedLocalRef<jstring> resString(env, 212 (jstring) env->CallObjectMethod(functionObj.get(), gUnaryOperator.apply, argString.get())); 213 214 if (env->ExceptionCheck()) { 215 ALOGE("Exception thrown by custom scalar function"); 216 sqlite3_result_error(context, "Exception thrown by custom scalar function", -1); 217 env->ExceptionDescribe(); 218 env->ExceptionClear(); 219 return; 220 } 221 222 if (resString.get() == nullptr) { 223 sqlite3_result_null(context); 224 } else { 225 ScopedUtfChars res(env, resString.get()); 226 sqlite3_result_text(context, res.c_str(), -1, SQLITE_TRANSIENT); 227 } 228 } 229 230 static void sqliteCustomScalarFunctionDestructor(void* data) { 231 jobject functionObjGlobal = reinterpret_cast<jobject>(data); 232 233 JNIEnv* env = AndroidRuntime::getJNIEnv(); 234 env->DeleteGlobalRef(functionObjGlobal); 235 } 236 237 static void nativeRegisterCustomScalarFunction(JNIEnv* env, jclass clazz, jlong connectionPtr, 238 jstring functionName, jobject functionObj) { 239 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 240 241 jobject functionObjGlobal = env->NewGlobalRef(functionObj); 242 ScopedUtfChars functionNameChars(env, functionName); 243 int err = sqlite3_create_function_v2(connection->db, 244 functionNameChars.c_str(), 1, SQLITE_UTF8, 245 reinterpret_cast<void*>(functionObjGlobal), 246 &sqliteCustomScalarFunctionCallback, 247 nullptr, 248 nullptr, 249 &sqliteCustomScalarFunctionDestructor); 250 251 if (err != SQLITE_OK) { 252 ALOGE("sqlite3_create_function returned %d", err); 253 env->DeleteGlobalRef(functionObjGlobal); 254 throw_sqlite3_exception(env, connection->db); 255 return; 256 } 257 } 258 259 static void sqliteCustomAggregateFunctionStep(sqlite3_context *context, 260 int argc, sqlite3_value **argv) { 261 char** agg = reinterpret_cast<char**>( 262 sqlite3_aggregate_context(context, sizeof(const char**))); 263 if (agg == nullptr) { 264 return; 265 } else if (*agg == nullptr) { 266 // During our first call the best we can do is allocate our result 267 // holder and populate it with our first value; we'll reduce it 268 // against any additional values in future calls 269 const char* res = reinterpret_cast<const char*>(sqlite3_value_text(argv[0])); 270 if (res == nullptr) { 271 *agg = nullptr; 272 } else { 273 *agg = strdup(res); 274 } 275 return; 276 } 277 278 JNIEnv* env = AndroidRuntime::getJNIEnv(); 279 jobject functionObjGlobal = reinterpret_cast<jobject>(sqlite3_user_data(context)); 280 ScopedLocalRef<jobject> functionObj(env, env->NewLocalRef(functionObjGlobal)); 281 ScopedLocalRef<jstring> arg0String(env, 282 env->NewStringUTF(reinterpret_cast<const char*>(*agg))); 283 ScopedLocalRef<jstring> arg1String(env, 284 env->NewStringUTF(reinterpret_cast<const char*>(sqlite3_value_text(argv[0])))); 285 ScopedLocalRef<jstring> resString(env, 286 (jstring) env->CallObjectMethod(functionObj.get(), gBinaryOperator.apply, 287 arg0String.get(), arg1String.get())); 288 289 if (env->ExceptionCheck()) { 290 ALOGE("Exception thrown by custom aggregate function"); 291 sqlite3_result_error(context, "Exception thrown by custom aggregate function", -1); 292 env->ExceptionDescribe(); 293 env->ExceptionClear(); 294 return; 295 } 296 297 // One way or another, we have a new value to collect, and we need to 298 // free our previous value 299 if (*agg != nullptr) { 300 free(*agg); 301 } 302 if (resString.get() == nullptr) { 303 *agg = nullptr; 304 } else { 305 ScopedUtfChars res(env, resString.get()); 306 *agg = strdup(res.c_str()); 307 } 308 } 309 310 static void sqliteCustomAggregateFunctionFinal(sqlite3_context *context) { 311 // We pass zero size here to avoid allocating for empty sets 312 char** agg = reinterpret_cast<char**>( 313 sqlite3_aggregate_context(context, 0)); 314 if (agg == nullptr) { 315 return; 316 } else if (*agg == nullptr) { 317 sqlite3_result_null(context); 318 } else { 319 sqlite3_result_text(context, *agg, -1, SQLITE_TRANSIENT); 320 free(*agg); 321 } 322 } 323 324 static void sqliteCustomAggregateFunctionDestructor(void* data) { 325 jobject functionObjGlobal = reinterpret_cast<jobject>(data); 326 327 JNIEnv* env = AndroidRuntime::getJNIEnv(); 328 env->DeleteGlobalRef(functionObjGlobal); 329 } 330 331 static void nativeRegisterCustomAggregateFunction(JNIEnv* env, jclass clazz, jlong connectionPtr, 332 jstring functionName, jobject functionObj) { 333 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 334 335 jobject functionObjGlobal = env->NewGlobalRef(functionObj); 336 ScopedUtfChars functionNameChars(env, functionName); 337 int err = sqlite3_create_function_v2(connection->db, 338 functionNameChars.c_str(), 1, SQLITE_UTF8, 339 reinterpret_cast<void*>(functionObjGlobal), 340 nullptr, 341 &sqliteCustomAggregateFunctionStep, 342 &sqliteCustomAggregateFunctionFinal, 343 &sqliteCustomAggregateFunctionDestructor); 344 345 if (err != SQLITE_OK) { 346 ALOGE("sqlite3_create_function returned %d", err); 347 env->DeleteGlobalRef(functionObjGlobal); 348 throw_sqlite3_exception(env, connection->db); 349 return; 350 } 351 } 352 353 static void nativeRegisterLocalizedCollators(JNIEnv* env, jclass clazz, jlong connectionPtr, 354 jstring localeStr) { 355 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 356 357 const char* locale = env->GetStringUTFChars(localeStr, NULL); 358 int err = register_localized_collators(connection->db, locale, UTF16_STORAGE); 359 env->ReleaseStringUTFChars(localeStr, locale); 360 361 if (err != SQLITE_OK) { 362 throw_sqlite3_exception(env, connection->db); 363 } 364 } 365 366 static jlong nativePrepareStatement(JNIEnv* env, jclass clazz, jlong connectionPtr, 367 jstring sqlString) { 368 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 369 370 jsize sqlLength = env->GetStringLength(sqlString); 371 const jchar* sql = env->GetStringCritical(sqlString, NULL); 372 sqlite3_stmt* statement; 373 int err = sqlite3_prepare16_v2(connection->db, 374 sql, sqlLength * sizeof(jchar), &statement, NULL); 375 env->ReleaseStringCritical(sqlString, sql); 376 377 if (err != SQLITE_OK) { 378 // Error messages like 'near ")": syntax error' are not 379 // always helpful enough, so construct an error string that 380 // includes the query itself. 381 const char *query = env->GetStringUTFChars(sqlString, NULL); 382 char *message = (char*) malloc(strlen(query) + 50); 383 if (message) { 384 strcpy(message, ", while compiling: "); // less than 50 chars 385 strcat(message, query); 386 } 387 env->ReleaseStringUTFChars(sqlString, query); 388 throw_sqlite3_exception(env, connection->db, message); 389 free(message); 390 return 0; 391 } 392 393 ALOGV("Prepared statement %p on connection %p", statement, connection->db); 394 return reinterpret_cast<jlong>(statement); 395 } 396 397 static void nativeFinalizeStatement(JNIEnv* env, jclass clazz, jlong connectionPtr, 398 jlong statementPtr) { 399 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 400 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 401 402 // We ignore the result of sqlite3_finalize because it is really telling us about 403 // whether any errors occurred while executing the statement. The statement itself 404 // is always finalized regardless. 405 ALOGV("Finalized statement %p on connection %p", statement, connection->db); 406 sqlite3_finalize(statement); 407 } 408 409 static jint nativeGetParameterCount(JNIEnv* env, jclass clazz, jlong connectionPtr, 410 jlong statementPtr) { 411 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 412 413 return sqlite3_bind_parameter_count(statement); 414 } 415 416 static jboolean nativeIsReadOnly(JNIEnv* env, jclass clazz, jlong connectionPtr, 417 jlong statementPtr) { 418 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 419 420 return sqlite3_stmt_readonly(statement) != 0; 421 } 422 423 static jint nativeGetColumnCount(JNIEnv* env, jclass clazz, jlong connectionPtr, 424 jlong statementPtr) { 425 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 426 427 return sqlite3_column_count(statement); 428 } 429 430 static jstring nativeGetColumnName(JNIEnv* env, jclass clazz, jlong connectionPtr, 431 jlong statementPtr, jint index) { 432 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 433 434 const jchar* name = static_cast<const jchar*>(sqlite3_column_name16(statement, index)); 435 if (name) { 436 size_t length = 0; 437 while (name[length]) { 438 length += 1; 439 } 440 return env->NewString(name, length); 441 } 442 return NULL; 443 } 444 445 static void nativeBindNull(JNIEnv* env, jclass clazz, jlong connectionPtr, 446 jlong statementPtr, jint index) { 447 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 448 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 449 450 int err = sqlite3_bind_null(statement, index); 451 if (err != SQLITE_OK) { 452 throw_sqlite3_exception(env, connection->db, NULL); 453 } 454 } 455 456 static void nativeBindLong(JNIEnv* env, jclass clazz, jlong connectionPtr, 457 jlong statementPtr, jint index, jlong value) { 458 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 459 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 460 461 int err = sqlite3_bind_int64(statement, index, value); 462 if (err != SQLITE_OK) { 463 throw_sqlite3_exception(env, connection->db, NULL); 464 } 465 } 466 467 static void nativeBindDouble(JNIEnv* env, jclass clazz, jlong connectionPtr, 468 jlong statementPtr, jint index, jdouble value) { 469 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 470 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 471 472 int err = sqlite3_bind_double(statement, index, value); 473 if (err != SQLITE_OK) { 474 throw_sqlite3_exception(env, connection->db, NULL); 475 } 476 } 477 478 static void nativeBindString(JNIEnv* env, jclass clazz, jlong connectionPtr, 479 jlong statementPtr, jint index, jstring valueString) { 480 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 481 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 482 483 jsize valueLength = env->GetStringLength(valueString); 484 const jchar* value = env->GetStringCritical(valueString, NULL); 485 int err = sqlite3_bind_text16(statement, index, value, valueLength * sizeof(jchar), 486 SQLITE_TRANSIENT); 487 env->ReleaseStringCritical(valueString, value); 488 if (err != SQLITE_OK) { 489 throw_sqlite3_exception(env, connection->db, NULL); 490 } 491 } 492 493 static void nativeBindBlob(JNIEnv* env, jclass clazz, jlong connectionPtr, 494 jlong statementPtr, jint index, jbyteArray valueArray) { 495 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 496 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 497 498 jsize valueLength = env->GetArrayLength(valueArray); 499 jbyte* value = static_cast<jbyte*>(env->GetPrimitiveArrayCritical(valueArray, NULL)); 500 int err = sqlite3_bind_blob(statement, index, value, valueLength, SQLITE_TRANSIENT); 501 env->ReleasePrimitiveArrayCritical(valueArray, value, JNI_ABORT); 502 if (err != SQLITE_OK) { 503 throw_sqlite3_exception(env, connection->db, NULL); 504 } 505 } 506 507 static void nativeResetStatementAndClearBindings(JNIEnv* env, jclass clazz, jlong connectionPtr, 508 jlong statementPtr) { 509 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 510 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 511 512 int err = sqlite3_reset(statement); 513 if (err == SQLITE_OK) { 514 err = sqlite3_clear_bindings(statement); 515 } 516 if (err != SQLITE_OK) { 517 throw_sqlite3_exception(env, connection->db, NULL); 518 } 519 } 520 521 static int executeNonQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement) { 522 int err = sqlite3_step(statement); 523 if (err == SQLITE_ROW) { 524 throw_sqlite3_exception(env, 525 "Queries can be performed using SQLiteDatabase query or rawQuery methods only."); 526 } else if (err != SQLITE_DONE) { 527 throw_sqlite3_exception(env, connection->db); 528 } 529 return err; 530 } 531 532 static void nativeExecute(JNIEnv* env, jclass clazz, jlong connectionPtr, 533 jlong statementPtr) { 534 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 535 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 536 537 executeNonQuery(env, connection, statement); 538 } 539 540 static jint nativeExecuteForChangedRowCount(JNIEnv* env, jclass clazz, 541 jlong connectionPtr, jlong statementPtr) { 542 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 543 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 544 545 int err = executeNonQuery(env, connection, statement); 546 return err == SQLITE_DONE ? sqlite3_changes(connection->db) : -1; 547 } 548 549 static jlong nativeExecuteForLastInsertedRowId(JNIEnv* env, jclass clazz, 550 jlong connectionPtr, jlong statementPtr) { 551 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 552 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 553 554 int err = executeNonQuery(env, connection, statement); 555 return err == SQLITE_DONE && sqlite3_changes(connection->db) > 0 556 ? sqlite3_last_insert_rowid(connection->db) : -1; 557 } 558 559 static int executeOneRowQuery(JNIEnv* env, SQLiteConnection* connection, sqlite3_stmt* statement) { 560 int err = sqlite3_step(statement); 561 if (err != SQLITE_ROW) { 562 throw_sqlite3_exception(env, connection->db); 563 } 564 return err; 565 } 566 567 static jlong nativeExecuteForLong(JNIEnv* env, jclass clazz, 568 jlong connectionPtr, jlong statementPtr) { 569 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 570 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 571 572 int err = executeOneRowQuery(env, connection, statement); 573 if (err == SQLITE_ROW && sqlite3_column_count(statement) >= 1) { 574 return sqlite3_column_int64(statement, 0); 575 } 576 return -1; 577 } 578 579 static jstring nativeExecuteForString(JNIEnv* env, jclass clazz, 580 jlong connectionPtr, jlong statementPtr) { 581 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 582 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 583 584 int err = executeOneRowQuery(env, connection, statement); 585 if (err == SQLITE_ROW && sqlite3_column_count(statement) >= 1) { 586 const jchar* text = static_cast<const jchar*>(sqlite3_column_text16(statement, 0)); 587 if (text) { 588 size_t length = sqlite3_column_bytes16(statement, 0) / sizeof(jchar); 589 return env->NewString(text, length); 590 } 591 } 592 return NULL; 593 } 594 595 static int createAshmemRegionWithData(JNIEnv* env, const void* data, size_t length) { 596 int error = 0; 597 int fd = ashmem_create_region(NULL, length); 598 if (fd < 0) { 599 error = errno; 600 ALOGE("ashmem_create_region failed: %s", strerror(error)); 601 } else { 602 if (length > 0) { 603 void* ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 604 if (ptr == MAP_FAILED) { 605 error = errno; 606 ALOGE("mmap failed: %s", strerror(error)); 607 } else { 608 memcpy(ptr, data, length); 609 munmap(ptr, length); 610 } 611 } 612 613 if (!error) { 614 if (ashmem_set_prot_region(fd, PROT_READ) < 0) { 615 error = errno; 616 ALOGE("ashmem_set_prot_region failed: %s", strerror(errno)); 617 } else { 618 return fd; 619 } 620 } 621 622 close(fd); 623 } 624 625 jniThrowIOException(env, error); 626 return -1; 627 } 628 629 static jint nativeExecuteForBlobFileDescriptor(JNIEnv* env, jclass clazz, 630 jlong connectionPtr, jlong statementPtr) { 631 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 632 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 633 634 int err = executeOneRowQuery(env, connection, statement); 635 if (err == SQLITE_ROW && sqlite3_column_count(statement) >= 1) { 636 const void* blob = sqlite3_column_blob(statement, 0); 637 if (blob) { 638 int length = sqlite3_column_bytes(statement, 0); 639 if (length >= 0) { 640 return createAshmemRegionWithData(env, blob, length); 641 } 642 } 643 } 644 return -1; 645 } 646 647 enum CopyRowResult { 648 CPR_OK, 649 CPR_FULL, 650 CPR_ERROR, 651 }; 652 653 static CopyRowResult copyRow(JNIEnv* env, CursorWindow* window, 654 sqlite3_stmt* statement, int numColumns, int startPos, int addedRows) { 655 // Allocate a new field directory for the row. 656 status_t status = window->allocRow(); 657 if (status) { 658 LOG_WINDOW("Failed allocating fieldDir at startPos %d row %d, error=%d", 659 startPos, addedRows, status); 660 return CPR_FULL; 661 } 662 663 // Pack the row into the window. 664 CopyRowResult result = CPR_OK; 665 for (int i = 0; i < numColumns; i++) { 666 int type = sqlite3_column_type(statement, i); 667 if (type == SQLITE_TEXT) { 668 // TEXT data 669 const char* text = reinterpret_cast<const char*>( 670 sqlite3_column_text(statement, i)); 671 // SQLite does not include the NULL terminator in size, but does 672 // ensure all strings are NULL terminated, so increase size by 673 // one to make sure we store the terminator. 674 size_t sizeIncludingNull = sqlite3_column_bytes(statement, i) + 1; 675 status = window->putString(addedRows, i, text, sizeIncludingNull); 676 if (status) { 677 LOG_WINDOW("Failed allocating %zu bytes for text at %d,%d, error=%d", 678 sizeIncludingNull, startPos + addedRows, i, status); 679 result = CPR_FULL; 680 break; 681 } 682 LOG_WINDOW("%d,%d is TEXT with %zu bytes", 683 startPos + addedRows, i, sizeIncludingNull); 684 } else if (type == SQLITE_INTEGER) { 685 // INTEGER data 686 int64_t value = sqlite3_column_int64(statement, i); 687 status = window->putLong(addedRows, i, value); 688 if (status) { 689 LOG_WINDOW("Failed allocating space for a long in column %d, error=%d", 690 i, status); 691 result = CPR_FULL; 692 break; 693 } 694 LOG_WINDOW("%d,%d is INTEGER %" PRId64, startPos + addedRows, i, value); 695 } else if (type == SQLITE_FLOAT) { 696 // FLOAT data 697 double value = sqlite3_column_double(statement, i); 698 status = window->putDouble(addedRows, i, value); 699 if (status) { 700 LOG_WINDOW("Failed allocating space for a double in column %d, error=%d", 701 i, status); 702 result = CPR_FULL; 703 break; 704 } 705 LOG_WINDOW("%d,%d is FLOAT %lf", startPos + addedRows, i, value); 706 } else if (type == SQLITE_BLOB) { 707 // BLOB data 708 const void* blob = sqlite3_column_blob(statement, i); 709 size_t size = sqlite3_column_bytes(statement, i); 710 status = window->putBlob(addedRows, i, blob, size); 711 if (status) { 712 LOG_WINDOW("Failed allocating %zu bytes for blob at %d,%d, error=%d", 713 size, startPos + addedRows, i, status); 714 result = CPR_FULL; 715 break; 716 } 717 LOG_WINDOW("%d,%d is Blob with %zu bytes", 718 startPos + addedRows, i, size); 719 } else if (type == SQLITE_NULL) { 720 // NULL field 721 status = window->putNull(addedRows, i); 722 if (status) { 723 LOG_WINDOW("Failed allocating space for a null in column %d, error=%d", 724 i, status); 725 result = CPR_FULL; 726 break; 727 } 728 729 LOG_WINDOW("%d,%d is NULL", startPos + addedRows, i); 730 } else { 731 // Unknown data 732 ALOGE("Unknown column type when filling database window"); 733 throw_sqlite3_exception(env, "Unknown column type when filling window"); 734 result = CPR_ERROR; 735 break; 736 } 737 } 738 739 // Free the last row if if was not successfully copied. 740 if (result != CPR_OK) { 741 window->freeLastRow(); 742 } 743 return result; 744 } 745 746 static jlong nativeExecuteForCursorWindow(JNIEnv* env, jclass clazz, 747 jlong connectionPtr, jlong statementPtr, jlong windowPtr, 748 jint startPos, jint requiredPos, jboolean countAllRows) { 749 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 750 sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 751 CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 752 753 status_t status = window->clear(); 754 if (status) { 755 String8 msg; 756 msg.appendFormat("Failed to clear the cursor window, status=%d", status); 757 throw_sqlite3_exception(env, connection->db, msg.string()); 758 return 0; 759 } 760 761 int numColumns = sqlite3_column_count(statement); 762 status = window->setNumColumns(numColumns); 763 if (status) { 764 String8 msg; 765 msg.appendFormat("Failed to set the cursor window column count to %d, status=%d", 766 numColumns, status); 767 throw_sqlite3_exception(env, connection->db, msg.string()); 768 return 0; 769 } 770 771 int retryCount = 0; 772 int totalRows = 0; 773 int addedRows = 0; 774 bool windowFull = false; 775 bool gotException = false; 776 while (!gotException && (!windowFull || countAllRows)) { 777 int err = sqlite3_step(statement); 778 if (err == SQLITE_ROW) { 779 LOG_WINDOW("Stepped statement %p to row %d", statement, totalRows); 780 retryCount = 0; 781 totalRows += 1; 782 783 // Skip the row if the window is full or we haven't reached the start position yet. 784 if (startPos >= totalRows || windowFull) { 785 continue; 786 } 787 788 CopyRowResult cpr = copyRow(env, window, statement, numColumns, startPos, addedRows); 789 if (cpr == CPR_FULL && addedRows && startPos + addedRows <= requiredPos) { 790 // We filled the window before we got to the one row that we really wanted. 791 // Clear the window and start filling it again from here. 792 // TODO: Would be nicer if we could progressively replace earlier rows. 793 window->clear(); 794 window->setNumColumns(numColumns); 795 startPos += addedRows; 796 addedRows = 0; 797 cpr = copyRow(env, window, statement, numColumns, startPos, addedRows); 798 } 799 800 if (cpr == CPR_OK) { 801 addedRows += 1; 802 } else if (cpr == CPR_FULL) { 803 windowFull = true; 804 } else { 805 gotException = true; 806 } 807 } else if (err == SQLITE_DONE) { 808 // All rows processed, bail 809 LOG_WINDOW("Processed all rows"); 810 break; 811 } else if (err == SQLITE_LOCKED || err == SQLITE_BUSY) { 812 // The table is locked, retry 813 LOG_WINDOW("Database locked, retrying"); 814 if (retryCount > 50) { 815 ALOGE("Bailing on database busy retry"); 816 throw_sqlite3_exception(env, connection->db, "retrycount exceeded"); 817 gotException = true; 818 } else { 819 // Sleep to give the thread holding the lock a chance to finish 820 usleep(1000); 821 retryCount++; 822 } 823 } else { 824 throw_sqlite3_exception(env, connection->db); 825 gotException = true; 826 } 827 } 828 829 LOG_WINDOW("Resetting statement %p after fetching %d rows and adding %d rows " 830 "to the window in %zu bytes", 831 statement, totalRows, addedRows, window->size() - window->freeSpace()); 832 sqlite3_reset(statement); 833 834 // Report the total number of rows on request. 835 if (startPos > totalRows) { 836 ALOGE("startPos %d > actual rows %d", startPos, totalRows); 837 } 838 if (totalRows > 0 && addedRows == 0) { 839 String8 msg; 840 msg.appendFormat("Row too big to fit into CursorWindow requiredPos=%d, totalRows=%d", 841 requiredPos, totalRows); 842 throw_sqlite3_exception(env, SQLITE_TOOBIG, NULL, msg.string()); 843 return 0; 844 } 845 846 jlong result = jlong(startPos) << 32 | jlong(totalRows); 847 return result; 848 } 849 850 static jint nativeGetDbLookaside(JNIEnv* env, jobject clazz, jlong connectionPtr) { 851 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 852 853 int cur = -1; 854 int unused; 855 sqlite3_db_status(connection->db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &unused, 0); 856 return cur; 857 } 858 859 static void nativeCancel(JNIEnv* env, jobject clazz, jlong connectionPtr) { 860 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 861 connection->canceled = true; 862 } 863 864 static void nativeResetCancel(JNIEnv* env, jobject clazz, jlong connectionPtr, 865 jboolean cancelable) { 866 SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr); 867 connection->canceled = false; 868 869 if (cancelable) { 870 sqlite3_progress_handler(connection->db, 4, sqliteProgressHandlerCallback, 871 connection); 872 } else { 873 sqlite3_progress_handler(connection->db, 0, NULL, NULL); 874 } 875 } 876 877 878 static const JNINativeMethod sMethods[] = 879 { 880 /* name, signature, funcPtr */ 881 { "nativeOpen", "(Ljava/lang/String;ILjava/lang/String;ZZII)J", 882 (void*)nativeOpen }, 883 { "nativeClose", "(J)V", 884 (void*)nativeClose }, 885 { "nativeRegisterCustomScalarFunction", "(JLjava/lang/String;Ljava/util/function/UnaryOperator;)V", 886 (void*)nativeRegisterCustomScalarFunction }, 887 { "nativeRegisterCustomAggregateFunction", "(JLjava/lang/String;Ljava/util/function/BinaryOperator;)V", 888 (void*)nativeRegisterCustomAggregateFunction }, 889 { "nativeRegisterLocalizedCollators", "(JLjava/lang/String;)V", 890 (void*)nativeRegisterLocalizedCollators }, 891 { "nativePrepareStatement", "(JLjava/lang/String;)J", 892 (void*)nativePrepareStatement }, 893 { "nativeFinalizeStatement", "(JJ)V", 894 (void*)nativeFinalizeStatement }, 895 { "nativeGetParameterCount", "(JJ)I", 896 (void*)nativeGetParameterCount }, 897 { "nativeIsReadOnly", "(JJ)Z", 898 (void*)nativeIsReadOnly }, 899 { "nativeGetColumnCount", "(JJ)I", 900 (void*)nativeGetColumnCount }, 901 { "nativeGetColumnName", "(JJI)Ljava/lang/String;", 902 (void*)nativeGetColumnName }, 903 { "nativeBindNull", "(JJI)V", 904 (void*)nativeBindNull }, 905 { "nativeBindLong", "(JJIJ)V", 906 (void*)nativeBindLong }, 907 { "nativeBindDouble", "(JJID)V", 908 (void*)nativeBindDouble }, 909 { "nativeBindString", "(JJILjava/lang/String;)V", 910 (void*)nativeBindString }, 911 { "nativeBindBlob", "(JJI[B)V", 912 (void*)nativeBindBlob }, 913 { "nativeResetStatementAndClearBindings", "(JJ)V", 914 (void*)nativeResetStatementAndClearBindings }, 915 { "nativeExecute", "(JJ)V", 916 (void*)nativeExecute }, 917 { "nativeExecuteForLong", "(JJ)J", 918 (void*)nativeExecuteForLong }, 919 { "nativeExecuteForString", "(JJ)Ljava/lang/String;", 920 (void*)nativeExecuteForString }, 921 { "nativeExecuteForBlobFileDescriptor", "(JJ)I", 922 (void*)nativeExecuteForBlobFileDescriptor }, 923 { "nativeExecuteForChangedRowCount", "(JJ)I", 924 (void*)nativeExecuteForChangedRowCount }, 925 { "nativeExecuteForLastInsertedRowId", "(JJ)J", 926 (void*)nativeExecuteForLastInsertedRowId }, 927 { "nativeExecuteForCursorWindow", "(JJJIIZ)J", 928 (void*)nativeExecuteForCursorWindow }, 929 { "nativeGetDbLookaside", "(J)I", 930 (void*)nativeGetDbLookaside }, 931 { "nativeCancel", "(J)V", 932 (void*)nativeCancel }, 933 { "nativeResetCancel", "(JZ)V", 934 (void*)nativeResetCancel }, 935 }; 936 937 int register_android_database_SQLiteConnection(JNIEnv *env) 938 { 939 jclass unaryClazz = FindClassOrDie(env, "java/util/function/UnaryOperator"); 940 gUnaryOperator.apply = GetMethodIDOrDie(env, unaryClazz, 941 "apply", "(Ljava/lang/Object;)Ljava/lang/Object;"); 942 943 jclass binaryClazz = FindClassOrDie(env, "java/util/function/BinaryOperator"); 944 gBinaryOperator.apply = GetMethodIDOrDie(env, binaryClazz, 945 "apply", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 946 947 return RegisterMethodsOrDie(env, "android/database/sqlite/SQLiteConnection", sMethods, 948 NELEM(sMethods)); 949 } 950 951 } // namespace android 952