static jlong nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFlags, jstring labelStr, jboolean enableTrace, jboolean enableProfile) { int sqliteFlags; if (openFlags & SQLiteConnection::CREATE_IF_NECESSARY) { sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; } else if (openFlags & SQLiteConnection::OPEN_READONLY) { sqliteFlags = SQLITE_OPEN_READONLY; } else { sqliteFlags = SQLITE_OPEN_READWRITE; } const char* pathChars = env->GetStringUTFChars(pathStr, NULL); String8 path(pathChars); env->ReleaseStringUTFChars(pathStr, pathChars); const char* labelChars = env->GetStringUTFChars(labelStr, NULL); String8 label(labelChars); env->ReleaseStringUTFChars(labelStr, labelChars); sqlite3* db; int err = sqlite3_open_v2(path.string(), &db, sqliteFlags, NULL); if (err != SQLITE_OK) { throw_sqlite3_exception_errcode(env, err, "Could not open database"); return 0; } // Check that the database is really read/write when that is what we asked for. if ((sqliteFlags & SQLITE_OPEN_READWRITE) && sqlite3_db_readonly(db, NULL)) { throw_sqlite3_exception(env, db, "Could not open the database in read/write mode."); sqlite3_close(db); return 0; } // Set the default busy handler to retry automatically before returning SQLITE_BUSY. err = sqlite3_busy_timeout(db, BUSY_TIMEOUT_MS); if (err != SQLITE_OK) { throw_sqlite3_exception(env, db, "Could not set busy timeout"); sqlite3_close(db); return 0; } // Register custom Android functions. err = register_android_functions(db, UTF16_STORAGE); if (err) { throw_sqlite3_exception(env, db, "Could not register Android SQL functions."); sqlite3_close(db); return 0; } // Create wrapper object. SQLiteConnection* connection = new SQLiteConnection(db, openFlags, path, label); // Enable tracing and profiling if requested. if (enableTrace) { sqlite3_trace(db, &sqliteTraceCallback, connection); } if (enableProfile) { sqlite3_profile(db, &sqliteProfileCallback, connection); } ALOGV("Opened connection %p with label '%s'", db, label.string()); return reinterpret_cast<jlong>(connection); }
/* public native void dbopen(String path, int flags, String locale); */ static void dbopen(JNIEnv* env, jobject object, jstring pathString, jint flags) { int err; sqlite3 * handle = NULL; sqlite3_stmt * statement = NULL; char const * path8 = env->GetStringUTFChars(pathString, NULL); int sqliteFlags; // register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called. registerLoggingFunc(path8); // convert our flags into the sqlite flags if (flags & CREATE_IF_NECESSARY) { sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; } else if (flags & OPEN_READONLY) { sqliteFlags = SQLITE_OPEN_READONLY; } else { sqliteFlags = SQLITE_OPEN_READWRITE; } err = sqlite3_open_v2(path8, &handle, sqliteFlags, NULL); if (err != SQLITE_OK) { LOGE("sqlite3_open_v2(\"%s\", &handle, %d, NULL) failed\n", path8, sqliteFlags); throw_sqlite3_exception(env, handle); goto done; } // The soft heap limit prevents the page cache allocations from growing // beyond the given limit, no matter what the max page cache sizes are // set to. The limit does not, as of 3.5.0, affect any other allocations. sqlite3_soft_heap_limit(sSqliteSoftHeapLimit); // Set the default busy handler to retry for 1000ms and then return SQLITE_BUSY err = sqlite3_busy_timeout(handle, 1000 /* ms */); if (err != SQLITE_OK) { LOGE("sqlite3_busy_timeout(handle, 1000) failed for \"%s\"\n", path8); throw_sqlite3_exception(env, handle); goto done; } #ifdef DB_INTEGRITY_CHECK static const char* integritySql = "pragma integrity_check(1);"; err = sqlite3_prepare_v2(handle, integritySql, -1, &statement, NULL); if (err != SQLITE_OK) { LOGE("sqlite_prepare_v2(handle, \"%s\") failed for \"%s\"\n", integritySql, path8); throw_sqlite3_exception(env, handle); goto done; } // first is OK or error message err = sqlite3_step(statement); if (err != SQLITE_ROW) { LOGE("integrity check failed for \"%s\"\n", integritySql, path8); throw_sqlite3_exception(env, handle); goto done; } else { const char *text = (const char*)sqlite3_column_text(statement, 0); if (strcmp(text, "ok") != 0) { LOGE("integrity check failed for \"%s\": %s\n", integritySql, path8, text); jniThrowException(env, "android/database/sqlite/SQLiteDatabaseCorruptException", text); goto done; } } #endif err = register_android_functions(handle, UTF16_STORAGE); if (err) { throw_sqlite3_exception(env, handle); goto done; } LOGV("Opened '%s' - %p\n", path8, handle); env->SetIntField(object, offset_db_handle, (int) handle); handle = NULL; // The caller owns the handle now. done: // Release allocated resources if (path8 != NULL) env->ReleaseStringUTFChars(pathString, path8); if (statement != NULL) sqlite3_finalize(statement); if (handle != NULL) sqlite3_close(handle); }
/* public native void dbopen(String path, int flags, String locale); */ static void dbopen(JNIEnv* env, jobject object, jstring pathString, jint flags) { int err; sqlite3 * handle = NULL; sqlite3_stmt * statement = NULL; char const * path8 = env->GetStringUTFChars(pathString, NULL); int sqliteFlags; // Error code handling for SQLite exec char* zErrMsg = NULL; // register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called. registerLoggingFunc(path8); // convert our flags into the sqlite flags if (flags & CREATE_IF_NECESSARY) { sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; } else if (flags & OPEN_READONLY) { sqliteFlags = SQLITE_OPEN_READONLY; } else { sqliteFlags = SQLITE_OPEN_READWRITE; } err = sqlite3_open_v2(path8, &handle, sqliteFlags, NULL); if (err != SQLITE_OK) { LOGE("sqlite3_open_v2(\"%s\", &handle, %d, NULL) failed\n", path8, sqliteFlags); throw_sqlite3_exception(env, handle); goto done; } // WAL is a new rollback method available in SQLite v3.7+. WAL speeds up writes to // SQLite databases. WAL cannot be used with Read Only databases or databases opened // in read only mode. // Check if DB can use WAL mode; Open in WAL mode for non-ReadOnly DBs if(!(flags & OPEN_READONLY) && (use_wal_mode(path8))) { // Configure databases to run in WAL mode. err = sqlite3_exec(handle,"PRAGMA journal_mode = WAL;", NULL, NULL,&zErrMsg); if (SQLITE_OK != err) { LOGE("sqlite3_exec - Failed to set WAL mode for [%s] \n", path8); err = sqlite3_exec(handle,"PRAGMA journal_mode = DELETE;", NULL, NULL,&zErrMsg); if(SQLITE_OK != err) { LOGE("sqlite3_exec - Failed to set DELETE mode for [%s] \n", path8); throw_sqlite3_exception(env, handle); goto done; } } else { LOGI("WAL succesfuly enabled for [%s] \n", path8); // Set autocheckpoint = 100 pages err = sqlite3_wal_autocheckpoint(handle, 100); if (SQLITE_OK != err) { LOGE("sqlite3_exec to set WAL autocheckpoint failed\n"); throw_sqlite3_exception(env, handle); goto done; } else if (use_wal_mode(path8) == 2) { /* Try to disable fsyncs. We don't care if it fails */ sqlite3_exec(handle,"PRAGMA synchronous = OFF;", NULL, NULL,&zErrMsg); } } } // The soft heap limit prevents the page cache allocations from growing // beyond the given limit, no matter what the max page cache sizes are // set to. The limit does not, as of 3.5.0, affect any other allocations. sqlite3_soft_heap_limit(SQLITE_SOFT_HEAP_LIMIT); // Set the default busy handler to retry for 1000ms and then return SQLITE_BUSY err = sqlite3_busy_timeout(handle, 1000 /* ms */); if (err != SQLITE_OK) { LOGE("sqlite3_busy_timeout(handle, 1000) failed for \"%s\"\n", path8); throw_sqlite3_exception(env, handle); goto done; } #ifdef DB_INTEGRITY_CHECK static const char* integritySql = "pragma integrity_check(1);"; err = sqlite3_prepare_v2(handle, integritySql, -1, &statement, NULL); if (err != SQLITE_OK) { LOGE("sqlite_prepare_v2(handle, \"%s\") failed for \"%s\"\n", integritySql, path8); throw_sqlite3_exception(env, handle); goto done; } // first is OK or error message err = sqlite3_step(statement); if (err != SQLITE_ROW) { LOGE("integrity check failed for \"%s\"\n", integritySql, path8); throw_sqlite3_exception(env, handle); goto done; } else { const char *text = (const char*)sqlite3_column_text(statement, 0); if (strcmp(text, "ok") != 0) { LOGE("integrity check failed for \"%s\": %s\n", integritySql, path8, text); jniThrowException(env, "android/database/sqlite/SQLiteDatabaseCorruptException", text); goto done; } } #endif err = register_android_functions(handle, UTF16_STORAGE); if (err) { throw_sqlite3_exception(env, handle); goto done; } LOGV("Opened '%s' - %p\n", path8, handle); env->SetIntField(object, offset_db_handle, (int) handle); handle = NULL; // The caller owns the handle now. done: // Release allocated resources if (path8 != NULL) env->ReleaseStringUTFChars(pathString, path8); if (statement != NULL) sqlite3_finalize(statement); if (handle != NULL) sqlite3_close(handle); }