1 /* 2 * Copyright (C) 2006 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 package android.database.sqlite; 18 19 import android.annotation.IntDef; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.StringDef; 24 import android.annotation.SuppressLint; 25 import android.app.ActivityManager; 26 import android.app.ActivityThread; 27 import android.compat.annotation.UnsupportedAppUsage; 28 import android.content.ContentResolver; 29 import android.content.ContentValues; 30 import android.database.Cursor; 31 import android.database.DatabaseErrorHandler; 32 import android.database.DatabaseUtils; 33 import android.database.DefaultDatabaseErrorHandler; 34 import android.database.SQLException; 35 import android.database.sqlite.SQLiteDebug.DbStats; 36 import android.os.Build; 37 import android.os.CancellationSignal; 38 import android.os.Looper; 39 import android.os.OperationCanceledException; 40 import android.os.SystemProperties; 41 import android.text.TextUtils; 42 import android.util.ArraySet; 43 import android.util.EventLog; 44 import android.util.Log; 45 import android.util.Pair; 46 import android.util.Printer; 47 import com.android.internal.util.Preconditions; 48 import dalvik.system.CloseGuard; 49 import java.io.File; 50 import java.io.FileFilter; 51 import java.io.IOException; 52 import java.lang.annotation.Retention; 53 import java.lang.annotation.RetentionPolicy; 54 import java.nio.file.FileSystems; 55 import java.nio.file.Files; 56 import java.nio.file.attribute.BasicFileAttributes; 57 import java.util.ArrayList; 58 import java.util.Arrays; 59 import java.util.HashMap; 60 import java.util.List; 61 import java.util.Locale; 62 import java.util.Map; 63 import java.util.Objects; 64 import java.util.WeakHashMap; 65 import java.util.function.BinaryOperator; 66 import java.util.function.UnaryOperator; 67 68 /** 69 * Exposes methods to manage a SQLite database. 70 * 71 * <p> 72 * SQLiteDatabase has methods to create, delete, execute SQL commands, and 73 * perform other common database management tasks. 74 * </p><p> 75 * See the Notepad sample application in the SDK for an example of creating 76 * and managing a database. 77 * </p><p> 78 * Database names must be unique within an application, not across all applications. 79 * </p> 80 * 81 * <h3>Localized Collation - ORDER BY</h3> 82 * <p> 83 * In addition to SQLite's default <code>BINARY</code> collator, Android supplies 84 * two more, <code>LOCALIZED</code>, which changes with the system's current locale, 85 * and <code>UNICODE</code>, which is the Unicode Collation Algorithm and not tailored 86 * to the current locale. 87 * </p> 88 */ 89 public final class SQLiteDatabase extends SQLiteClosable { 90 private static final String TAG = "SQLiteDatabase"; 91 92 private static final int EVENT_DB_CORRUPT = 75004; 93 94 // By default idle connections are not closed 95 private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties 96 .getBoolean("persist.debug.sqlite.close_idle_connections", false); 97 98 // Stores reference to all databases opened in the current process. 99 // (The referent Object is not used at this time.) 100 // INVARIANT: Guarded by sActiveDatabases. 101 private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>(); 102 103 // Thread-local for database sessions that belong to this database. 104 // Each thread has its own database session. 105 // INVARIANT: Immutable. 106 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 107 private final ThreadLocal<SQLiteSession> mThreadSession = ThreadLocal 108 .withInitial(this::createSession); 109 110 // The optional factory to use when creating new Cursors. May be null. 111 // INVARIANT: Immutable. 112 private final CursorFactory mCursorFactory; 113 114 // Error handler to be used when SQLite returns corruption errors. 115 // INVARIANT: Immutable. 116 private final DatabaseErrorHandler mErrorHandler; 117 118 // Shared database state lock. 119 // This lock guards all of the shared state of the database, such as its 120 // configuration, whether it is open or closed, and so on. This lock should 121 // be held for as little time as possible. 122 // 123 // The lock MUST NOT be held while attempting to acquire database connections or 124 // while executing SQL statements on behalf of the client as it can lead to deadlock. 125 // 126 // It is ok to hold the lock while reconfiguring the connection pool or dumping 127 // statistics because those operations are non-reentrant and do not try to acquire 128 // connections that might be held by other threads. 129 // 130 // Basic rule: grab the lock, access or modify global state, release the lock, then 131 // do the required SQL work. 132 private final Object mLock = new Object(); 133 134 // Warns if the database is finalized without being closed properly. 135 // INVARIANT: Guarded by mLock. 136 private final CloseGuard mCloseGuardLocked = CloseGuard.get(); 137 138 // The database configuration. 139 // INVARIANT: Guarded by mLock. 140 @UnsupportedAppUsage 141 private final SQLiteDatabaseConfiguration mConfigurationLocked; 142 143 // The connection pool for the database, null when closed. 144 // The pool itself is thread-safe, but the reference to it can only be acquired 145 // when the lock is held. 146 // INVARIANT: Guarded by mLock. 147 @UnsupportedAppUsage 148 private SQLiteConnectionPool mConnectionPoolLocked; 149 150 // True if the database has attached databases. 151 // INVARIANT: Guarded by mLock. 152 private boolean mHasAttachedDbsLocked; 153 154 /** 155 * When a constraint violation occurs, an immediate ROLLBACK occurs, 156 * thus ending the current transaction, and the command aborts with a 157 * return code of SQLITE_CONSTRAINT. If no transaction is active 158 * (other than the implied transaction that is created on every command) 159 * then this algorithm works the same as ABORT. 160 */ 161 public static final int CONFLICT_ROLLBACK = 1; 162 163 /** 164 * When a constraint violation occurs,no ROLLBACK is executed 165 * so changes from prior commands within the same transaction 166 * are preserved. This is the default behavior. 167 */ 168 public static final int CONFLICT_ABORT = 2; 169 170 /** 171 * When a constraint violation occurs, the command aborts with a return 172 * code SQLITE_CONSTRAINT. But any changes to the database that 173 * the command made prior to encountering the constraint violation 174 * are preserved and are not backed out. 175 */ 176 public static final int CONFLICT_FAIL = 3; 177 178 /** 179 * When a constraint violation occurs, the one row that contains 180 * the constraint violation is not inserted or changed. 181 * But the command continues executing normally. Other rows before and 182 * after the row that contained the constraint violation continue to be 183 * inserted or updated normally. No error is returned. 184 */ 185 public static final int CONFLICT_IGNORE = 4; 186 187 /** 188 * When a UNIQUE constraint violation occurs, the pre-existing rows that 189 * are causing the constraint violation are removed prior to inserting 190 * or updating the current row. Thus the insert or update always occurs. 191 * The command continues executing normally. No error is returned. 192 * If a NOT NULL constraint violation occurs, the NULL value is replaced 193 * by the default value for that column. If the column has no default 194 * value, then the ABORT algorithm is used. If a CHECK constraint 195 * violation occurs then the IGNORE algorithm is used. When this conflict 196 * resolution strategy deletes rows in order to satisfy a constraint, 197 * it does not invoke delete triggers on those rows. 198 * This behavior might change in a future release. 199 */ 200 public static final int CONFLICT_REPLACE = 5; 201 202 /** 203 * Use the following when no conflict action is specified. 204 */ 205 public static final int CONFLICT_NONE = 0; 206 207 /** {@hide} */ 208 @UnsupportedAppUsage 209 public static final String[] CONFLICT_VALUES = new String[] 210 {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "}; 211 212 /** 213 * Maximum Length Of A LIKE Or GLOB Pattern 214 * The pattern matching algorithm used in the default LIKE and GLOB implementation 215 * of SQLite can exhibit O(N^2) performance (where N is the number of characters in 216 * the pattern) for certain pathological cases. To avoid denial-of-service attacks 217 * the length of the LIKE or GLOB pattern is limited to SQLITE_MAX_LIKE_PATTERN_LENGTH bytes. 218 * The default value of this limit is 50000. A modern workstation can evaluate 219 * even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly. 220 * The denial of service problem only comes into play when the pattern length gets 221 * into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns 222 * are at most a few dozen bytes in length, cautious application developers may 223 * want to reduce this parameter to something in the range of a few hundred 224 * if they know that external users are able to generate arbitrary patterns. 225 */ 226 public static final int SQLITE_MAX_LIKE_PATTERN_LENGTH = 50000; 227 228 /** 229 * Open flag: Flag for {@link #openDatabase} to open the database for reading and writing. 230 * If the disk is full, this may fail even before you actually write anything. 231 * 232 * {@more} Note that the value of this flag is 0, so it is the default. 233 */ 234 public static final int OPEN_READWRITE = 0x00000000; // update native code if changing 235 236 /** 237 * Open flag: Flag for {@link #openDatabase} to open the database for reading only. 238 * This is the only reliable way to open a database if the disk may be full. 239 */ 240 public static final int OPEN_READONLY = 0x00000001; // update native code if changing 241 242 private static final int OPEN_READ_MASK = 0x00000001; // update native code if changing 243 244 /** 245 * Open flag: Flag for {@link #openDatabase} to open the database without support for 246 * localized collators. 247 * 248 * {@more} This causes the collator <code>LOCALIZED</code> not to be created. 249 * You must be consistent when using this flag to use the setting the database was 250 * created with. If this is set, {@link #setLocale} will do nothing. 251 */ 252 public static final int NO_LOCALIZED_COLLATORS = 0x00000010; // update native code if changing 253 254 /** 255 * Open flag: Flag for {@link #openDatabase} to create the database file if it does not 256 * already exist. 257 */ 258 public static final int CREATE_IF_NECESSARY = 0x10000000; // update native code if changing 259 260 /** 261 * Open flag: Flag for {@link #openDatabase} to open the database file with 262 * write-ahead logging enabled by default. Using this flag is more efficient 263 * than calling {@link #enableWriteAheadLogging}. 264 * 265 * Write-ahead logging cannot be used with read-only databases so the value of 266 * this flag is ignored if the database is opened read-only. 267 * 268 * @see #enableWriteAheadLogging 269 */ 270 public static final int ENABLE_WRITE_AHEAD_LOGGING = 0x20000000; 271 272 273 // Note: The below value was only used on Android Pie. 274 // public static final int DISABLE_COMPATIBILITY_WAL = 0x40000000; 275 276 /** 277 * Open flag: Flag for {@link #openDatabase} to enable the legacy Compatibility WAL when opening 278 * database. 279 * 280 * @hide 281 */ 282 public static final int ENABLE_LEGACY_COMPATIBILITY_WAL = 0x80000000; 283 284 /** 285 * Absolute max value that can be set by {@link #setMaxSqlCacheSize(int)}. 286 * 287 * Each prepared-statement is between 1K - 6K, depending on the complexity of the 288 * SQL statement & schema. A large SQL cache may use a significant amount of memory. 289 */ 290 public static final int MAX_SQL_CACHE_SIZE = 100; 291 292 /** 293 * @hide 294 */ 295 @StringDef(prefix = {"JOURNAL_MODE_"}, 296 value = 297 { 298 JOURNAL_MODE_WAL, 299 JOURNAL_MODE_PERSIST, 300 JOURNAL_MODE_TRUNCATE, 301 JOURNAL_MODE_MEMORY, 302 JOURNAL_MODE_DELETE, 303 JOURNAL_MODE_OFF, 304 }) 305 @Retention(RetentionPolicy.SOURCE) 306 public @interface JournalMode {} 307 308 /** 309 * The {@code WAL} journaling mode uses a write-ahead log instead of a rollback journal to 310 * implement transactions. The WAL journaling mode is persistent; after being set it stays 311 * in effect across multiple database connections and after closing and reopening the database. 312 * 313 * Performance Considerations: 314 * This mode is recommended when the goal is to improve write performance or parallel read/write 315 * performance. However, it is important to note that WAL introduces checkpoints which commit 316 * all transactions that have not been synced to the database thus to maximize read performance 317 * and lower checkpointing cost a small journal size is recommended. However, other modes such 318 * as {@code DELETE} will not perform checkpoints, so it is a trade off that needs to be 319 * considered as part of the decision of which journal mode to use. 320 * 321 * <p> See <a href=https://www.sqlite.org/pragma.html#pragma_journal_mode>here</a> for more 322 * details.</p> 323 */ 324 public static final String JOURNAL_MODE_WAL = "WAL"; 325 326 /** 327 * The {@code PERSIST} journaling mode prevents the rollback journal from being deleted at the 328 * end of each transaction. Instead, the header of the journal is overwritten with zeros. 329 * This will prevent other database connections from rolling the journal back. 330 * 331 * This mode is useful as an optimization on platforms where deleting or truncating a file is 332 * much more expensive than overwriting the first block of a file with zeros. 333 * 334 * <p> See <a href=https://www.sqlite.org/pragma.html#pragma_journal_mode>here</a> for more 335 * details.</p> 336 */ 337 public static final String JOURNAL_MODE_PERSIST = "PERSIST"; 338 339 /** 340 * The {@code TRUNCATE} journaling mode commits transactions by truncating the rollback journal 341 * to zero-length instead of deleting it. On many systems, truncating a file is much faster than 342 * deleting the file since the containing directory does not need to be changed. 343 * 344 * <p> See <a href=https://www.sqlite.org/pragma.html#pragma_journal_mode>here</a> for more 345 * details.</p> 346 */ 347 public static final String JOURNAL_MODE_TRUNCATE = "TRUNCATE"; 348 349 /** 350 * The {@code MEMORY} journaling mode stores the rollback journal in volatile RAM. 351 * This saves disk I/O but at the expense of database safety and integrity. If the application 352 * using SQLite crashes in the middle of a transaction when the MEMORY journaling mode is set, 353 * then the database file will very likely go corrupt. 354 * 355 * <p> See <a href=https://www.sqlite.org/pragma.html#pragma_journal_mode>here</a> for more 356 * details.</p> 357 */ 358 public static final String JOURNAL_MODE_MEMORY = "MEMORY"; 359 360 /** 361 * The {@code DELETE} journaling mode is the normal behavior. In the DELETE mode, the rollback 362 * journal is deleted at the conclusion of each transaction. 363 * 364 * <p> See <a href=https://www.sqlite.org/pragma.html#pragma_journal_mode>here</a> for more 365 * details.</p> 366 */ 367 public static final String JOURNAL_MODE_DELETE = "DELETE"; 368 369 /** 370 * The {@code OFF} journaling mode disables the rollback journal completely. No rollback journal 371 * is ever created and hence there is never a rollback journal to delete. The OFF journaling 372 * mode disables the atomic commit and rollback capabilities of SQLite. The ROLLBACK command 373 * behaves in an undefined way thus applications must avoid using the ROLLBACK command. 374 * If the application crashes in the middle of a transaction, then the database file will very 375 * likely go corrupt. 376 * 377 * <p> See <a href=https://www.sqlite.org/pragma.html#pragma_journal_mode>here</a> for more 378 * details.</p> 379 */ 380 public static final String JOURNAL_MODE_OFF = "OFF"; 381 382 /** 383 * @hide 384 */ 385 @StringDef(prefix = {"SYNC_MODE_"}, 386 value = 387 { 388 SYNC_MODE_EXTRA, 389 SYNC_MODE_FULL, 390 SYNC_MODE_NORMAL, 391 SYNC_MODE_OFF, 392 }) 393 @Retention(RetentionPolicy.SOURCE) 394 public @interface SyncMode {} 395 396 /** 397 * The {@code EXTRA} sync mode is like {@code FULL} sync mode with the addition that the 398 * directory containing a rollback journal is synced after that journal is unlinked to commit a 399 * transaction in {@code DELETE} journal mode. 400 * 401 * {@code EXTRA} provides additional durability if the commit is followed closely by a 402 * power loss. 403 * 404 * <p> See <a href=https://www.sqlite.org/pragma.html#pragma_synchronous>here</a> for more 405 * details.</p> 406 */ 407 @SuppressLint("IntentName") public static final String SYNC_MODE_EXTRA = "EXTRA"; 408 409 /** 410 * In {@code FULL} sync mode the SQLite database engine will use the xSync method of the VFS 411 * to ensure that all content is safely written to the disk surface prior to continuing. 412 * This ensures that an operating system crash or power failure will not corrupt the database. 413 * {@code FULL} is very safe, but it is also slower. 414 * 415 * {@code FULL} is the most commonly used synchronous setting when not in WAL mode. 416 * 417 * <p> See <a href=https://www.sqlite.org/pragma.html#pragma_synchronous>here</a> for more 418 * details.</p> 419 */ 420 public static final String SYNC_MODE_FULL = "FULL"; 421 422 /** 423 * The {@code NORMAL} sync mode, the SQLite database engine will still sync at the most critical 424 * moments, but less often than in {@code FULL} mode. There is a very small chance that a 425 * power failure at the wrong time could corrupt the database in {@code DELETE} journal mode on 426 * an older filesystem. 427 * 428 * {@code WAL} journal mode is safe from corruption with {@code NORMAL} sync mode, and probably 429 * {@code DELETE} sync mode is safe too on modern filesystems. WAL mode is always consistent 430 * with {@code NORMAL} sync mode, but WAL mode does lose durability. A transaction committed in 431 * WAL mode with {@code NORMAL} might roll back following a power loss or system crash. 432 * Transactions are durable across application crashes regardless of the synchronous setting 433 * or journal mode. 434 * 435 * The {@code NORMAL} sync mode is a good choice for most applications running in WAL mode. 436 * 437 * <p>Caveat: Even though this sync mode is safe Be careful when using {@code NORMAL} sync mode 438 * when dealing with data dependencies between multiple databases, unless those databases use 439 * the same durability or are somehow synced, there could be corruption.</p> 440 * 441 * <p> See <a href=https://www.sqlite.org/pragma.html#pragma_synchronous>here</a> for more 442 * details.</p> 443 */ 444 public static final String SYNC_MODE_NORMAL = "NORMAL"; 445 446 /** 447 * In {@code OFF} sync mode SQLite continues without syncing as soon as it has handed data off 448 * to the operating system. If the application running SQLite crashes, the data will be safe, 449 * but the database might become corrupted if the operating system crashes or the computer loses 450 * power before that data has been written to the disk surface. On the other hand, commits can 451 * be orders of magnitude faster with synchronous {@code OFF}. 452 * 453 * <p> See <a href=https://www.sqlite.org/pragma.html#pragma_synchronous>here</a> for more 454 * details.</p> 455 */ 456 public static final String SYNC_MODE_OFF = "OFF"; 457 SQLiteDatabase(@ullable final String path, @Nullable final int openFlags, @Nullable CursorFactory cursorFactory, @Nullable DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs, @Nullable String journalMode, @Nullable String syncMode)458 private SQLiteDatabase(@Nullable final String path, @Nullable final int openFlags, 459 @Nullable CursorFactory cursorFactory, @Nullable DatabaseErrorHandler errorHandler, 460 int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs, 461 @Nullable String journalMode, @Nullable String syncMode) { 462 mCursorFactory = cursorFactory; 463 mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler(); 464 mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags); 465 mConfigurationLocked.lookasideSlotSize = lookasideSlotSize; 466 mConfigurationLocked.lookasideSlotCount = lookasideSlotCount; 467 468 // Disable lookaside allocator on low-RAM devices 469 if (ActivityManager.isLowRamDeviceStatic()) { 470 mConfigurationLocked.lookasideSlotCount = 0; 471 mConfigurationLocked.lookasideSlotSize = 0; 472 } 473 long effectiveTimeoutMs = Long.MAX_VALUE; 474 // Never close idle connections for in-memory databases 475 if (!mConfigurationLocked.isInMemoryDb()) { 476 // First, check app-specific value. Otherwise use defaults 477 // -1 in idleConnectionTimeoutMs indicates unset value 478 if (idleConnectionTimeoutMs >= 0) { 479 effectiveTimeoutMs = idleConnectionTimeoutMs; 480 } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) { 481 effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout(); 482 } 483 } 484 mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs; 485 if (SQLiteCompatibilityWalFlags.isLegacyCompatibilityWalEnabled()) { 486 mConfigurationLocked.openFlags |= ENABLE_LEGACY_COMPATIBILITY_WAL; 487 } 488 mConfigurationLocked.journalMode = journalMode; 489 mConfigurationLocked.syncMode = syncMode; 490 } 491 492 @Override finalize()493 protected void finalize() throws Throwable { 494 try { 495 dispose(true); 496 } finally { 497 super.finalize(); 498 } 499 } 500 501 @Override onAllReferencesReleased()502 protected void onAllReferencesReleased() { 503 dispose(false); 504 } 505 dispose(boolean finalized)506 private void dispose(boolean finalized) { 507 final SQLiteConnectionPool pool; 508 synchronized (mLock) { 509 if (mCloseGuardLocked != null) { 510 if (finalized) { 511 mCloseGuardLocked.warnIfOpen(); 512 } 513 mCloseGuardLocked.close(); 514 } 515 516 pool = mConnectionPoolLocked; 517 mConnectionPoolLocked = null; 518 } 519 520 if (!finalized) { 521 synchronized (sActiveDatabases) { 522 sActiveDatabases.remove(this); 523 } 524 525 if (pool != null) { 526 pool.close(); 527 } 528 } 529 } 530 531 /** 532 * Attempts to release memory that SQLite holds but does not require to 533 * operate properly. Typically this memory will come from the page cache. 534 * 535 * @return the number of bytes actually released 536 */ releaseMemory()537 public static int releaseMemory() { 538 return SQLiteGlobal.releaseMemory(); 539 } 540 541 /** 542 * Control whether or not the SQLiteDatabase is made thread-safe by using locks 543 * around critical sections. This is pretty expensive, so if you know that your 544 * DB will only be used by a single thread then you should set this to false. 545 * The default is true. 546 * @param lockingEnabled set to true to enable locks, false otherwise 547 * 548 * @deprecated This method now does nothing. Do not use. 549 */ 550 @Deprecated setLockingEnabled(boolean lockingEnabled)551 public void setLockingEnabled(boolean lockingEnabled) { 552 } 553 554 /** 555 * Gets a label to use when describing the database in log messages. 556 * @return The label. 557 */ getLabel()558 String getLabel() { 559 synchronized (mLock) { 560 return mConfigurationLocked.label; 561 } 562 } 563 564 /** 565 * Sends a corruption message to the database error handler. 566 */ onCorruption()567 void onCorruption() { 568 EventLog.writeEvent(EVENT_DB_CORRUPT, getLabel()); 569 mErrorHandler.onCorruption(this); 570 } 571 572 /** 573 * Gets the {@link SQLiteSession} that belongs to this thread for this database. 574 * Once a thread has obtained a session, it will continue to obtain the same 575 * session even after the database has been closed (although the session will not 576 * be usable). However, a thread that does not already have a session cannot 577 * obtain one after the database has been closed. 578 * 579 * The idea is that threads that have active connections to the database may still 580 * have work to complete even after the call to {@link #close}. Active database 581 * connections are not actually disposed until they are released by the threads 582 * that own them. 583 * 584 * @return The session, never null. 585 * 586 * @throws IllegalStateException if the thread does not yet have a session and 587 * the database is not open. 588 */ 589 @UnsupportedAppUsage getThreadSession()590 SQLiteSession getThreadSession() { 591 return mThreadSession.get(); // initialValue() throws if database closed 592 } 593 createSession()594 SQLiteSession createSession() { 595 final SQLiteConnectionPool pool; 596 synchronized (mLock) { 597 throwIfNotOpenLocked(); 598 pool = mConnectionPoolLocked; 599 } 600 return new SQLiteSession(pool); 601 } 602 603 /** 604 * Gets default connection flags that are appropriate for this thread, taking into 605 * account whether the thread is acting on behalf of the UI. 606 * 607 * @param readOnly True if the connection should be read-only. 608 * @return The connection flags. 609 */ getThreadDefaultConnectionFlags(boolean readOnly)610 int getThreadDefaultConnectionFlags(boolean readOnly) { 611 int flags = readOnly ? SQLiteConnectionPool.CONNECTION_FLAG_READ_ONLY : 612 SQLiteConnectionPool.CONNECTION_FLAG_PRIMARY_CONNECTION_AFFINITY; 613 if (isMainThread()) { 614 flags |= SQLiteConnectionPool.CONNECTION_FLAG_INTERACTIVE; 615 } 616 return flags; 617 } 618 isMainThread()619 private static boolean isMainThread() { 620 // FIXME: There should be a better way to do this. 621 // Would also be nice to have something that would work across Binder calls. 622 Looper looper = Looper.myLooper(); 623 return looper != null && looper == Looper.getMainLooper(); 624 } 625 626 /** 627 * Begins a transaction in EXCLUSIVE mode. 628 * <p> 629 * Transactions can be nested. 630 * When the outer transaction is ended all of 631 * the work done in that transaction and all of the nested transactions will be committed or 632 * rolled back. The changes will be rolled back if any transaction is ended without being 633 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. 634 * </p> 635 * <p>Here is the standard idiom for transactions: 636 * 637 * <pre> 638 * db.beginTransaction(); 639 * try { 640 * ... 641 * db.setTransactionSuccessful(); 642 * } finally { 643 * db.endTransaction(); 644 * } 645 * </pre> 646 */ beginTransaction()647 public void beginTransaction() { 648 beginTransaction(null /* transactionStatusCallback */, true); 649 } 650 651 /** 652 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When 653 * the outer transaction is ended all of the work done in that transaction 654 * and all of the nested transactions will be committed or rolled back. The 655 * changes will be rolled back if any transaction is ended without being 656 * marked as clean (by calling setTransactionSuccessful). Otherwise they 657 * will be committed. 658 * <p> 659 * Here is the standard idiom for transactions: 660 * 661 * <pre> 662 * db.beginTransactionNonExclusive(); 663 * try { 664 * ... 665 * db.setTransactionSuccessful(); 666 * } finally { 667 * db.endTransaction(); 668 * } 669 * </pre> 670 */ beginTransactionNonExclusive()671 public void beginTransactionNonExclusive() { 672 beginTransaction(null /* transactionStatusCallback */, false); 673 } 674 675 /** 676 * Begins a transaction in EXCLUSIVE mode. 677 * <p> 678 * Transactions can be nested. 679 * When the outer transaction is ended all of 680 * the work done in that transaction and all of the nested transactions will be committed or 681 * rolled back. The changes will be rolled back if any transaction is ended without being 682 * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed. 683 * </p> 684 * <p>Here is the standard idiom for transactions: 685 * 686 * <pre> 687 * db.beginTransactionWithListener(listener); 688 * try { 689 * ... 690 * db.setTransactionSuccessful(); 691 * } finally { 692 * db.endTransaction(); 693 * } 694 * </pre> 695 * 696 * @param transactionListener listener that should be notified when the transaction begins, 697 * commits, or is rolled back, either explicitly or by a call to 698 * {@link #yieldIfContendedSafely}. 699 */ beginTransactionWithListener(SQLiteTransactionListener transactionListener)700 public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) { 701 beginTransaction(transactionListener, true); 702 } 703 704 /** 705 * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When 706 * the outer transaction is ended all of the work done in that transaction 707 * and all of the nested transactions will be committed or rolled back. The 708 * changes will be rolled back if any transaction is ended without being 709 * marked as clean (by calling setTransactionSuccessful). Otherwise they 710 * will be committed. 711 * <p> 712 * Here is the standard idiom for transactions: 713 * 714 * <pre> 715 * db.beginTransactionWithListenerNonExclusive(listener); 716 * try { 717 * ... 718 * db.setTransactionSuccessful(); 719 * } finally { 720 * db.endTransaction(); 721 * } 722 * </pre> 723 * 724 * @param transactionListener listener that should be notified when the 725 * transaction begins, commits, or is rolled back, either 726 * explicitly or by a call to {@link #yieldIfContendedSafely}. 727 */ beginTransactionWithListenerNonExclusive( SQLiteTransactionListener transactionListener)728 public void beginTransactionWithListenerNonExclusive( 729 SQLiteTransactionListener transactionListener) { 730 beginTransaction(transactionListener, false); 731 } 732 733 @UnsupportedAppUsage beginTransaction(SQLiteTransactionListener transactionListener, boolean exclusive)734 private void beginTransaction(SQLiteTransactionListener transactionListener, 735 boolean exclusive) { 736 acquireReference(); 737 try { 738 getThreadSession().beginTransaction( 739 exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE : 740 SQLiteSession.TRANSACTION_MODE_IMMEDIATE, 741 transactionListener, 742 getThreadDefaultConnectionFlags(false /*readOnly*/), null); 743 } finally { 744 releaseReference(); 745 } 746 } 747 748 /** 749 * End a transaction. See beginTransaction for notes about how to use this and when transactions 750 * are committed and rolled back. 751 */ endTransaction()752 public void endTransaction() { 753 acquireReference(); 754 try { 755 getThreadSession().endTransaction(null); 756 } finally { 757 releaseReference(); 758 } 759 } 760 761 /** 762 * Marks the current transaction as successful. Do not do any more database work between 763 * calling this and calling endTransaction. Do as little non-database work as possible in that 764 * situation too. If any errors are encountered between this and endTransaction the transaction 765 * will still be committed. 766 * 767 * @throws IllegalStateException if the current thread is not in a transaction or the 768 * transaction is already marked as successful. 769 */ setTransactionSuccessful()770 public void setTransactionSuccessful() { 771 acquireReference(); 772 try { 773 getThreadSession().setTransactionSuccessful(); 774 } finally { 775 releaseReference(); 776 } 777 } 778 779 /** 780 * Returns true if the current thread has a transaction pending. 781 * 782 * @return True if the current thread is in a transaction. 783 */ inTransaction()784 public boolean inTransaction() { 785 acquireReference(); 786 try { 787 return getThreadSession().hasTransaction(); 788 } finally { 789 releaseReference(); 790 } 791 } 792 793 /** 794 * Returns true if the current thread is holding an active connection to the database. 795 * <p> 796 * The name of this method comes from a time when having an active connection 797 * to the database meant that the thread was holding an actual lock on the 798 * database. Nowadays, there is no longer a true "database lock" although threads 799 * may block if they cannot acquire a database connection to perform a 800 * particular operation. 801 * </p> 802 * 803 * @return True if the current thread is holding an active connection to the database. 804 */ isDbLockedByCurrentThread()805 public boolean isDbLockedByCurrentThread() { 806 acquireReference(); 807 try { 808 return getThreadSession().hasConnection(); 809 } finally { 810 releaseReference(); 811 } 812 } 813 814 /** 815 * Always returns false. 816 * <p> 817 * There is no longer the concept of a database lock, so this method always returns false. 818 * </p> 819 * 820 * @return False. 821 * @deprecated Always returns false. Do not use this method. 822 */ 823 @Deprecated isDbLockedByOtherThreads()824 public boolean isDbLockedByOtherThreads() { 825 return false; 826 } 827 828 /** 829 * Temporarily end the transaction to let other threads run. The transaction is assumed to be 830 * successful so far. Do not call setTransactionSuccessful before calling this. When this 831 * returns a new transaction will have been created but not marked as successful. 832 * @return true if the transaction was yielded 833 * @deprecated if the db is locked more than once (because of nested transactions) then the lock 834 * will not be yielded. Use yieldIfContendedSafely instead. 835 */ 836 @Deprecated yieldIfContended()837 public boolean yieldIfContended() { 838 return yieldIfContendedHelper(false /* do not check yielding */, 839 -1 /* sleepAfterYieldDelay */); 840 } 841 842 /** 843 * Temporarily end the transaction to let other threads run. The transaction is assumed to be 844 * successful so far. Do not call setTransactionSuccessful before calling this. When this 845 * returns a new transaction will have been created but not marked as successful. This assumes 846 * that there are no nested transactions (beginTransaction has only been called once) and will 847 * throw an exception if that is not the case. 848 * @return true if the transaction was yielded 849 */ yieldIfContendedSafely()850 public boolean yieldIfContendedSafely() { 851 return yieldIfContendedHelper(true /* check yielding */, -1 /* sleepAfterYieldDelay*/); 852 } 853 854 /** 855 * Temporarily end the transaction to let other threads run. The transaction is assumed to be 856 * successful so far. Do not call setTransactionSuccessful before calling this. When this 857 * returns a new transaction will have been created but not marked as successful. This assumes 858 * that there are no nested transactions (beginTransaction has only been called once) and will 859 * throw an exception if that is not the case. 860 * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if 861 * the lock was actually yielded. This will allow other background threads to make some 862 * more progress than they would if we started the transaction immediately. 863 * @return true if the transaction was yielded 864 */ yieldIfContendedSafely(long sleepAfterYieldDelay)865 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) { 866 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay); 867 } 868 yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay)869 private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) { 870 acquireReference(); 871 try { 872 return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null); 873 } finally { 874 releaseReference(); 875 } 876 } 877 878 /** 879 * Deprecated. 880 * @deprecated This method no longer serves any useful purpose and has been deprecated. 881 */ 882 @Deprecated getSyncedTables()883 public Map<String, String> getSyncedTables() { 884 return new HashMap<String, String>(0); 885 } 886 887 /** 888 * Open the database according to the flags {@link #OPEN_READWRITE} 889 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}. 890 * 891 * <p>Sets the locale of the database to the the system's current locale. 892 * Call {@link #setLocale} if you would like something else.</p> 893 * 894 * @param path to database file to open and/or create 895 * @param factory an optional factory class that is called to instantiate a 896 * cursor when query is called, or null for default 897 * @param flags to control database access mode 898 * @return the newly opened database 899 * @throws SQLiteException if the database cannot be opened 900 */ openDatabase(@onNull String path, @Nullable CursorFactory factory, @DatabaseOpenFlags int flags)901 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory, 902 @DatabaseOpenFlags int flags) { 903 return openDatabase(path, factory, flags, null); 904 } 905 906 /** 907 * Open the database according to the specified {@link OpenParams parameters} 908 * 909 * @param path path to database file to open and/or create. 910 * <p><strong>Important:</strong> The file should be constructed either from an absolute path or 911 * by using {@link android.content.Context#getDatabasePath(String)}. 912 * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase} 913 * @return the newly opened database 914 * @throws SQLiteException if the database cannot be opened 915 */ openDatabase(@onNull File path, @NonNull OpenParams openParams)916 public static SQLiteDatabase openDatabase(@NonNull File path, 917 @NonNull OpenParams openParams) { 918 return openDatabase(path.getPath(), openParams); 919 } 920 921 @UnsupportedAppUsage openDatabase(@onNull String path, @NonNull OpenParams openParams)922 private static SQLiteDatabase openDatabase(@NonNull String path, 923 @NonNull OpenParams openParams) { 924 Preconditions.checkArgument(openParams != null, "OpenParams cannot be null"); 925 SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags, 926 openParams.mCursorFactory, openParams.mErrorHandler, 927 openParams.mLookasideSlotSize, openParams.mLookasideSlotCount, 928 openParams.mIdleConnectionTimeout, openParams.mJournalMode, openParams.mSyncMode); 929 db.open(); 930 return db; 931 } 932 933 /** 934 * Open the database according to the flags {@link #OPEN_READWRITE} 935 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}. 936 * 937 * <p>Sets the locale of the database to the the system's current locale. 938 * Call {@link #setLocale} if you would like something else.</p> 939 * 940 * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be 941 * used to handle corruption when sqlite reports database corruption.</p> 942 * 943 * @param path to database file to open and/or create 944 * @param factory an optional factory class that is called to instantiate a 945 * cursor when query is called, or null for default 946 * @param flags to control database access mode 947 * @param errorHandler the {@link DatabaseErrorHandler} obj to be used to handle corruption 948 * when sqlite reports database corruption 949 * @return the newly opened database 950 * @throws SQLiteException if the database cannot be opened 951 */ openDatabase(@onNull String path, @Nullable CursorFactory factory, @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler)952 public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory, 953 @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) { 954 SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1, -1, null, 955 null); 956 db.open(); 957 return db; 958 } 959 960 /** 961 * Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY). 962 */ openOrCreateDatabase(@onNull File file, @Nullable CursorFactory factory)963 public static SQLiteDatabase openOrCreateDatabase(@NonNull File file, 964 @Nullable CursorFactory factory) { 965 return openOrCreateDatabase(file.getPath(), factory); 966 } 967 968 /** 969 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY). 970 */ openOrCreateDatabase(@onNull String path, @Nullable CursorFactory factory)971 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path, 972 @Nullable CursorFactory factory) { 973 return openDatabase(path, factory, CREATE_IF_NECESSARY, null); 974 } 975 976 /** 977 * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler). 978 */ openOrCreateDatabase(@onNull String path, @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler)979 public static SQLiteDatabase openOrCreateDatabase(@NonNull String path, 980 @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) { 981 return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler); 982 } 983 984 /** 985 * Deletes a database including its journal file and other auxiliary files 986 * that may have been created by the database engine. 987 * 988 * @param file The database file path. 989 * @return True if the database was successfully deleted. 990 */ deleteDatabase(@onNull File file)991 public static boolean deleteDatabase(@NonNull File file) { 992 return deleteDatabase(file, /*removeCheckFile=*/ true); 993 } 994 995 996 /** @hide */ deleteDatabase(@onNull File file, boolean removeCheckFile)997 public static boolean deleteDatabase(@NonNull File file, boolean removeCheckFile) { 998 if (file == null) { 999 throw new IllegalArgumentException("file must not be null"); 1000 } 1001 1002 boolean deleted = false; 1003 deleted |= file.delete(); 1004 deleted |= new File(file.getPath() + "-journal").delete(); 1005 deleted |= new File(file.getPath() + "-shm").delete(); 1006 deleted |= new File(file.getPath() + "-wal").delete(); 1007 1008 // This file is not a standard SQLite file, so don't update the deleted flag. 1009 new File(file.getPath() + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX).delete(); 1010 1011 File dir = file.getParentFile(); 1012 if (dir != null) { 1013 final String prefix = file.getName() + "-mj"; 1014 File[] files = dir.listFiles(new FileFilter() { 1015 @Override 1016 public boolean accept(File candidate) { 1017 return candidate.getName().startsWith(prefix); 1018 } 1019 }); 1020 if (files != null) { 1021 for (File masterJournal : files) { 1022 deleted |= masterJournal.delete(); 1023 } 1024 } 1025 } 1026 return deleted; 1027 } 1028 1029 /** 1030 * Reopens the database in read-write mode. 1031 * If the database is already read-write, does nothing. 1032 * 1033 * @throws SQLiteException if the database could not be reopened as requested, in which 1034 * case it remains open in read only mode. 1035 * @throws IllegalStateException if the database is not open. 1036 * 1037 * @see #isReadOnly() 1038 * @hide 1039 */ 1040 @UnsupportedAppUsage reopenReadWrite()1041 public void reopenReadWrite() { 1042 synchronized (mLock) { 1043 throwIfNotOpenLocked(); 1044 1045 if (!isReadOnlyLocked()) { 1046 return; // nothing to do 1047 } 1048 1049 // Reopen the database in read-write mode. 1050 final int oldOpenFlags = mConfigurationLocked.openFlags; 1051 mConfigurationLocked.openFlags = (mConfigurationLocked.openFlags & ~OPEN_READ_MASK) 1052 | OPEN_READWRITE; 1053 try { 1054 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 1055 } catch (RuntimeException ex) { 1056 mConfigurationLocked.openFlags = oldOpenFlags; 1057 throw ex; 1058 } 1059 } 1060 } 1061 open()1062 private void open() { 1063 try { 1064 try { 1065 openInner(); 1066 } catch (RuntimeException ex) { 1067 if (SQLiteDatabaseCorruptException.isCorruptException(ex)) { 1068 Log.e(TAG, "Database corruption detected in open()", ex); 1069 onCorruption(); 1070 openInner(); 1071 } else { 1072 throw ex; 1073 } 1074 } 1075 } catch (SQLiteException ex) { 1076 Log.e(TAG, "Failed to open database '" + getLabel() + "'.", ex); 1077 close(); 1078 throw ex; 1079 } 1080 } 1081 openInner()1082 private void openInner() { 1083 synchronized (mLock) { 1084 assert mConnectionPoolLocked == null; 1085 mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked); 1086 mCloseGuardLocked.open("close"); 1087 } 1088 1089 synchronized (sActiveDatabases) { 1090 sActiveDatabases.put(this, null); 1091 } 1092 } 1093 1094 /** 1095 * Create a memory backed SQLite database. Its contents will be destroyed 1096 * when the database is closed. 1097 * 1098 * <p>Sets the locale of the database to the the system's current locale. 1099 * Call {@link #setLocale} if you would like something else.</p> 1100 * 1101 * @param factory an optional factory class that is called to instantiate a 1102 * cursor when query is called 1103 * @return a SQLiteDatabase instance 1104 * @throws SQLiteException if the database cannot be created 1105 */ 1106 @NonNull create(@ullable CursorFactory factory)1107 public static SQLiteDatabase create(@Nullable CursorFactory factory) { 1108 // This is a magic string with special meaning for SQLite. 1109 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH, 1110 factory, CREATE_IF_NECESSARY); 1111 } 1112 1113 /** 1114 * Create a memory backed SQLite database. Its contents will be destroyed 1115 * when the database is closed. 1116 * 1117 * <p>Sets the locale of the database to the the system's current locale. 1118 * Call {@link #setLocale} if you would like something else.</p> 1119 * @param openParams configuration parameters that are used for opening SQLiteDatabase 1120 * @return a SQLiteDatabase instance 1121 * @throws SQLException if the database cannot be created 1122 */ 1123 @NonNull createInMemory(@onNull OpenParams openParams)1124 public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) { 1125 return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH, 1126 openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build()); 1127 } 1128 1129 /** 1130 * Register a custom scalar function that can be called from SQL 1131 * expressions. 1132 * <p> 1133 * For example, registering a custom scalar function named {@code REVERSE} 1134 * could be used in a query like 1135 * {@code SELECT REVERSE(name) FROM employees}. 1136 * <p> 1137 * When attempting to register multiple functions with the same function 1138 * name, SQLite will replace any previously defined functions with the 1139 * latest definition, regardless of what function type they are. SQLite does 1140 * not support unregistering functions. 1141 * 1142 * @param functionName Case-insensitive name to register this function 1143 * under, limited to 255 UTF-8 bytes in length. 1144 * @param scalarFunction Functional interface that will be invoked when the 1145 * function name is used by a SQL statement. The argument values 1146 * from the SQL statement are passed to the functional interface, 1147 * and the return values from the functional interface are 1148 * returned back into the SQL statement. 1149 * @throws SQLiteException if the custom function could not be registered. 1150 * @see #setCustomAggregateFunction(String, BinaryOperator) 1151 */ setCustomScalarFunction(@onNull String functionName, @NonNull UnaryOperator<String> scalarFunction)1152 public void setCustomScalarFunction(@NonNull String functionName, 1153 @NonNull UnaryOperator<String> scalarFunction) throws SQLiteException { 1154 Objects.requireNonNull(functionName); 1155 Objects.requireNonNull(scalarFunction); 1156 1157 synchronized (mLock) { 1158 throwIfNotOpenLocked(); 1159 1160 mConfigurationLocked.customScalarFunctions.put(functionName, scalarFunction); 1161 try { 1162 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 1163 } catch (RuntimeException ex) { 1164 mConfigurationLocked.customScalarFunctions.remove(functionName); 1165 throw ex; 1166 } 1167 } 1168 } 1169 1170 /** 1171 * Register a custom aggregate function that can be called from SQL 1172 * expressions. 1173 * <p> 1174 * For example, registering a custom aggregation function named 1175 * {@code LONGEST} could be used in a query like 1176 * {@code SELECT LONGEST(name) FROM employees}. 1177 * <p> 1178 * The implementation of this method follows the reduction flow outlined in 1179 * {@link java.util.stream.Stream#reduce(BinaryOperator)}, and the custom 1180 * aggregation function is expected to be an associative accumulation 1181 * function, as defined by that class. 1182 * <p> 1183 * When attempting to register multiple functions with the same function 1184 * name, SQLite will replace any previously defined functions with the 1185 * latest definition, regardless of what function type they are. SQLite does 1186 * not support unregistering functions. 1187 * 1188 * @param functionName Case-insensitive name to register this function 1189 * under, limited to 255 UTF-8 bytes in length. 1190 * @param aggregateFunction Functional interface that will be invoked when 1191 * the function name is used by a SQL statement. The argument 1192 * values from the SQL statement are passed to the functional 1193 * interface, and the return values from the functional interface 1194 * are returned back into the SQL statement. 1195 * @throws SQLiteException if the custom function could not be registered. 1196 * @see #setCustomScalarFunction(String, UnaryOperator) 1197 */ setCustomAggregateFunction(@onNull String functionName, @NonNull BinaryOperator<String> aggregateFunction)1198 public void setCustomAggregateFunction(@NonNull String functionName, 1199 @NonNull BinaryOperator<String> aggregateFunction) throws SQLiteException { 1200 Objects.requireNonNull(functionName); 1201 Objects.requireNonNull(aggregateFunction); 1202 1203 synchronized (mLock) { 1204 throwIfNotOpenLocked(); 1205 1206 mConfigurationLocked.customAggregateFunctions.put(functionName, aggregateFunction); 1207 try { 1208 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 1209 } catch (RuntimeException ex) { 1210 mConfigurationLocked.customAggregateFunctions.remove(functionName); 1211 throw ex; 1212 } 1213 } 1214 } 1215 1216 /** 1217 * Execute the given SQL statement on all connections to this database. 1218 * <p> 1219 * This statement will be immediately executed on all existing connections, 1220 * and will be automatically executed on all future connections. 1221 * <p> 1222 * Some example usages are changes like {@code PRAGMA trusted_schema=OFF} or 1223 * functions like {@code SELECT icu_load_collation()}. If you execute these 1224 * statements using {@link #execSQL} then they will only apply to a single 1225 * database connection; using this method will ensure that they are 1226 * uniformly applied to all current and future connections. 1227 * 1228 * @param sql The SQL statement to be executed. Multiple statements 1229 * separated by semicolons are not supported. 1230 * @param bindArgs The arguments that should be bound to the SQL statement. 1231 */ execPerConnectionSQL(@onNull String sql, @Nullable Object[] bindArgs)1232 public void execPerConnectionSQL(@NonNull String sql, @Nullable Object[] bindArgs) 1233 throws SQLException { 1234 Objects.requireNonNull(sql); 1235 1236 // Copy arguments to ensure that the caller doesn't accidentally change 1237 // the values used by future connections 1238 bindArgs = DatabaseUtils.deepCopyOf(bindArgs); 1239 1240 synchronized (mLock) { 1241 throwIfNotOpenLocked(); 1242 1243 final int index = mConfigurationLocked.perConnectionSql.size(); 1244 mConfigurationLocked.perConnectionSql.add(Pair.create(sql, bindArgs)); 1245 try { 1246 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 1247 } catch (RuntimeException ex) { 1248 mConfigurationLocked.perConnectionSql.remove(index); 1249 throw ex; 1250 } 1251 } 1252 } 1253 1254 /** 1255 * Gets the database version. 1256 * 1257 * @return the database version 1258 */ getVersion()1259 public int getVersion() { 1260 return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue(); 1261 } 1262 1263 /** 1264 * Sets the database version. 1265 * 1266 * @param version the new database version 1267 */ setVersion(int version)1268 public void setVersion(int version) { 1269 execSQL("PRAGMA user_version = " + version); 1270 } 1271 1272 /** 1273 * Returns the maximum size the database may grow to. 1274 * 1275 * @return the new maximum database size 1276 */ getMaximumSize()1277 public long getMaximumSize() { 1278 long pageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count;", null); 1279 return pageCount * getPageSize(); 1280 } 1281 1282 /** 1283 * Sets the maximum size the database will grow to. The maximum size cannot 1284 * be set below the current size. 1285 * 1286 * @param numBytes the maximum database size, in bytes 1287 * @return the new maximum database size 1288 */ setMaximumSize(long numBytes)1289 public long setMaximumSize(long numBytes) { 1290 long pageSize = getPageSize(); 1291 long numPages = numBytes / pageSize; 1292 // If numBytes isn't a multiple of pageSize, bump up a page 1293 if ((numBytes % pageSize) != 0) { 1294 numPages++; 1295 } 1296 long newPageCount = DatabaseUtils.longForQuery(this, "PRAGMA max_page_count = " + numPages, 1297 null); 1298 return newPageCount * pageSize; 1299 } 1300 1301 /** 1302 * Returns the current database page size, in bytes. 1303 * 1304 * @return the database page size, in bytes 1305 */ getPageSize()1306 public long getPageSize() { 1307 return DatabaseUtils.longForQuery(this, "PRAGMA page_size;", null); 1308 } 1309 1310 /** 1311 * Sets the database page size. The page size must be a power of two. This 1312 * method does not work if any data has been written to the database file, 1313 * and must be called right after the database has been created. 1314 * 1315 * @param numBytes the database page size, in bytes 1316 */ setPageSize(long numBytes)1317 public void setPageSize(long numBytes) { 1318 execSQL("PRAGMA page_size = " + numBytes); 1319 } 1320 1321 /** 1322 * Mark this table as syncable. When an update occurs in this table the 1323 * _sync_dirty field will be set to ensure proper syncing operation. 1324 * 1325 * @param table the table to mark as syncable 1326 * @param deletedTable The deleted table that corresponds to the 1327 * syncable table 1328 * @deprecated This method no longer serves any useful purpose and has been deprecated. 1329 */ 1330 @Deprecated markTableSyncable(String table, String deletedTable)1331 public void markTableSyncable(String table, String deletedTable) { 1332 } 1333 1334 /** 1335 * Mark this table as syncable, with the _sync_dirty residing in another 1336 * table. When an update occurs in this table the _sync_dirty field of the 1337 * row in updateTable with the _id in foreignKey will be set to 1338 * ensure proper syncing operation. 1339 * 1340 * @param table an update on this table will trigger a sync time removal 1341 * @param foreignKey this is the column in table whose value is an _id in 1342 * updateTable 1343 * @param updateTable this is the table that will have its _sync_dirty 1344 * @deprecated This method no longer serves any useful purpose and has been deprecated. 1345 */ 1346 @Deprecated markTableSyncable(String table, String foreignKey, String updateTable)1347 public void markTableSyncable(String table, String foreignKey, String updateTable) { 1348 } 1349 1350 /** 1351 * Finds the name of the first table, which is editable. 1352 * 1353 * @param tables a list of tables 1354 * @return the first table listed 1355 */ findEditTable(String tables)1356 public static String findEditTable(String tables) { 1357 if (!TextUtils.isEmpty(tables)) { 1358 // find the first word terminated by either a space or a comma 1359 int spacepos = tables.indexOf(' '); 1360 int commapos = tables.indexOf(','); 1361 1362 if (spacepos > 0 && (spacepos < commapos || commapos < 0)) { 1363 return tables.substring(0, spacepos); 1364 } else if (commapos > 0 && (commapos < spacepos || spacepos < 0) ) { 1365 return tables.substring(0, commapos); 1366 } 1367 return tables; 1368 } else { 1369 throw new IllegalStateException("Invalid tables"); 1370 } 1371 } 1372 1373 /** 1374 * Compiles an SQL statement into a reusable pre-compiled statement object. 1375 * The parameters are identical to {@link #execSQL(String)}. You may put ?s in the 1376 * statement and fill in those values with {@link SQLiteProgram#bindString} 1377 * and {@link SQLiteProgram#bindLong} each time you want to run the 1378 * statement. Statements may not return result sets larger than 1x1. 1379 *<p> 1380 * No two threads should be using the same {@link SQLiteStatement} at the same time. 1381 * 1382 * @param sql The raw SQL statement, may contain ? for unknown values to be 1383 * bound later. 1384 * @return A pre-compiled {@link SQLiteStatement} object. Note that 1385 * {@link SQLiteStatement}s are not synchronized, see the documentation for more details. 1386 */ compileStatement(String sql)1387 public SQLiteStatement compileStatement(String sql) throws SQLException { 1388 acquireReference(); 1389 try { 1390 return new SQLiteStatement(this, sql, null); 1391 } finally { 1392 releaseReference(); 1393 } 1394 } 1395 1396 /** 1397 * Query the given URL, returning a {@link Cursor} over the result set. 1398 * 1399 * @param distinct true if you want each row to be unique, false otherwise. 1400 * @param table The table name to compile the query against. 1401 * @param columns A list of which columns to return. Passing null will 1402 * return all columns, which is discouraged to prevent reading 1403 * data from storage that isn't going to be used. 1404 * @param selection A filter declaring which rows to return, formatted as an 1405 * SQL WHERE clause (excluding the WHERE itself). Passing null 1406 * will return all rows for the given table. 1407 * @param selectionArgs You may include ?s in selection, which will be 1408 * replaced by the values from selectionArgs, in order that they 1409 * appear in the selection. The values will be bound as Strings. 1410 * @param groupBy A filter declaring how to group rows, formatted as an SQL 1411 * GROUP BY clause (excluding the GROUP BY itself). Passing null 1412 * will cause the rows to not be grouped. 1413 * @param having A filter declare which row groups to include in the cursor, 1414 * if row grouping is being used, formatted as an SQL HAVING 1415 * clause (excluding the HAVING itself). Passing null will cause 1416 * all row groups to be included, and is required when row 1417 * grouping is not being used. 1418 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 1419 * (excluding the ORDER BY itself). Passing null will use the 1420 * default sort order, which may be unordered. 1421 * @param limit Limits the number of rows returned by the query, 1422 * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 1423 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1424 * {@link Cursor}s are not synchronized, see the documentation for more details. 1425 * @see Cursor 1426 */ query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)1427 public Cursor query(boolean distinct, String table, String[] columns, 1428 String selection, String[] selectionArgs, String groupBy, 1429 String having, String orderBy, String limit) { 1430 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs, 1431 groupBy, having, orderBy, limit, null); 1432 } 1433 1434 /** 1435 * Query the given URL, returning a {@link Cursor} over the result set. 1436 * 1437 * @param distinct true if you want each row to be unique, false otherwise. 1438 * @param table The table name to compile the query against. 1439 * @param columns A list of which columns to return. Passing null will 1440 * return all columns, which is discouraged to prevent reading 1441 * data from storage that isn't going to be used. 1442 * @param selection A filter declaring which rows to return, formatted as an 1443 * SQL WHERE clause (excluding the WHERE itself). Passing null 1444 * will return all rows for the given table. 1445 * @param selectionArgs You may include ?s in selection, which will be 1446 * replaced by the values from selectionArgs, in order that they 1447 * appear in the selection. The values will be bound as Strings. 1448 * @param groupBy A filter declaring how to group rows, formatted as an SQL 1449 * GROUP BY clause (excluding the GROUP BY itself). Passing null 1450 * will cause the rows to not be grouped. 1451 * @param having A filter declare which row groups to include in the cursor, 1452 * if row grouping is being used, formatted as an SQL HAVING 1453 * clause (excluding the HAVING itself). Passing null will cause 1454 * all row groups to be included, and is required when row 1455 * grouping is not being used. 1456 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 1457 * (excluding the ORDER BY itself). Passing null will use the 1458 * default sort order, which may be unordered. 1459 * @param limit Limits the number of rows returned by the query, 1460 * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 1461 * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 1462 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 1463 * when the query is executed. 1464 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1465 * {@link Cursor}s are not synchronized, see the documentation for more details. 1466 * @see Cursor 1467 */ query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)1468 public Cursor query(boolean distinct, String table, String[] columns, 1469 String selection, String[] selectionArgs, String groupBy, 1470 String having, String orderBy, String limit, CancellationSignal cancellationSignal) { 1471 return queryWithFactory(null, distinct, table, columns, selection, selectionArgs, 1472 groupBy, having, orderBy, limit, cancellationSignal); 1473 } 1474 1475 /** 1476 * Query the given URL, returning a {@link Cursor} over the result set. 1477 * 1478 * @param cursorFactory the cursor factory to use, or null for the default factory 1479 * @param distinct true if you want each row to be unique, false otherwise. 1480 * @param table The table name to compile the query against. 1481 * @param columns A list of which columns to return. Passing null will 1482 * return all columns, which is discouraged to prevent reading 1483 * data from storage that isn't going to be used. 1484 * @param selection A filter declaring which rows to return, formatted as an 1485 * SQL WHERE clause (excluding the WHERE itself). Passing null 1486 * will return all rows for the given table. 1487 * @param selectionArgs You may include ?s in selection, which will be 1488 * replaced by the values from selectionArgs, in order that they 1489 * appear in the selection. The values will be bound as Strings. 1490 * @param groupBy A filter declaring how to group rows, formatted as an SQL 1491 * GROUP BY clause (excluding the GROUP BY itself). Passing null 1492 * will cause the rows to not be grouped. 1493 * @param having A filter declare which row groups to include in the cursor, 1494 * if row grouping is being used, formatted as an SQL HAVING 1495 * clause (excluding the HAVING itself). Passing null will cause 1496 * all row groups to be included, and is required when row 1497 * grouping is not being used. 1498 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 1499 * (excluding the ORDER BY itself). Passing null will use the 1500 * default sort order, which may be unordered. 1501 * @param limit Limits the number of rows returned by the query, 1502 * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 1503 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1504 * {@link Cursor}s are not synchronized, see the documentation for more details. 1505 * @see Cursor 1506 */ queryWithFactory(CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)1507 public Cursor queryWithFactory(CursorFactory cursorFactory, 1508 boolean distinct, String table, String[] columns, 1509 String selection, String[] selectionArgs, String groupBy, 1510 String having, String orderBy, String limit) { 1511 return queryWithFactory(cursorFactory, distinct, table, columns, selection, 1512 selectionArgs, groupBy, having, orderBy, limit, null); 1513 } 1514 1515 /** 1516 * Query the given URL, returning a {@link Cursor} over the result set. 1517 * 1518 * @param cursorFactory the cursor factory to use, or null for the default factory 1519 * @param distinct true if you want each row to be unique, false otherwise. 1520 * @param table The table name to compile the query against. 1521 * @param columns A list of which columns to return. Passing null will 1522 * return all columns, which is discouraged to prevent reading 1523 * data from storage that isn't going to be used. 1524 * @param selection A filter declaring which rows to return, formatted as an 1525 * SQL WHERE clause (excluding the WHERE itself). Passing null 1526 * will return all rows for the given table. 1527 * @param selectionArgs You may include ?s in selection, which will be 1528 * replaced by the values from selectionArgs, in order that they 1529 * appear in the selection. The values will be bound as Strings. 1530 * @param groupBy A filter declaring how to group rows, formatted as an SQL 1531 * GROUP BY clause (excluding the GROUP BY itself). Passing null 1532 * will cause the rows to not be grouped. 1533 * @param having A filter declare which row groups to include in the cursor, 1534 * if row grouping is being used, formatted as an SQL HAVING 1535 * clause (excluding the HAVING itself). Passing null will cause 1536 * all row groups to be included, and is required when row 1537 * grouping is not being used. 1538 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 1539 * (excluding the ORDER BY itself). Passing null will use the 1540 * default sort order, which may be unordered. 1541 * @param limit Limits the number of rows returned by the query, 1542 * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 1543 * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 1544 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 1545 * when the query is executed. 1546 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1547 * {@link Cursor}s are not synchronized, see the documentation for more details. 1548 * @see Cursor 1549 */ queryWithFactory(CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)1550 public Cursor queryWithFactory(CursorFactory cursorFactory, 1551 boolean distinct, String table, String[] columns, 1552 String selection, String[] selectionArgs, String groupBy, 1553 String having, String orderBy, String limit, CancellationSignal cancellationSignal) { 1554 acquireReference(); 1555 try { 1556 String sql = SQLiteQueryBuilder.buildQueryString( 1557 distinct, table, columns, selection, groupBy, having, orderBy, limit); 1558 1559 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, 1560 findEditTable(table), cancellationSignal); 1561 } finally { 1562 releaseReference(); 1563 } 1564 } 1565 1566 /** 1567 * Query the given table, returning a {@link Cursor} over the result set. 1568 * 1569 * @param table The table name to compile the query against. 1570 * @param columns A list of which columns to return. Passing null will 1571 * return all columns, which is discouraged to prevent reading 1572 * data from storage that isn't going to be used. 1573 * @param selection A filter declaring which rows to return, formatted as an 1574 * SQL WHERE clause (excluding the WHERE itself). Passing null 1575 * will return all rows for the given table. 1576 * @param selectionArgs You may include ?s in selection, which will be 1577 * replaced by the values from selectionArgs, in order that they 1578 * appear in the selection. The values will be bound as Strings. 1579 * @param groupBy A filter declaring how to group rows, formatted as an SQL 1580 * GROUP BY clause (excluding the GROUP BY itself). Passing null 1581 * will cause the rows to not be grouped. 1582 * @param having A filter declare which row groups to include in the cursor, 1583 * if row grouping is being used, formatted as an SQL HAVING 1584 * clause (excluding the HAVING itself). Passing null will cause 1585 * all row groups to be included, and is required when row 1586 * grouping is not being used. 1587 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 1588 * (excluding the ORDER BY itself). Passing null will use the 1589 * default sort order, which may be unordered. 1590 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1591 * {@link Cursor}s are not synchronized, see the documentation for more details. 1592 * @see Cursor 1593 */ query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)1594 public Cursor query(String table, String[] columns, String selection, 1595 String[] selectionArgs, String groupBy, String having, 1596 String orderBy) { 1597 1598 return query(false, table, columns, selection, selectionArgs, groupBy, 1599 having, orderBy, null /* limit */); 1600 } 1601 1602 /** 1603 * Query the given table, returning a {@link Cursor} over the result set. 1604 * 1605 * @param table The table name to compile the query against. 1606 * @param columns A list of which columns to return. Passing null will 1607 * return all columns, which is discouraged to prevent reading 1608 * data from storage that isn't going to be used. 1609 * @param selection A filter declaring which rows to return, formatted as an 1610 * SQL WHERE clause (excluding the WHERE itself). Passing null 1611 * will return all rows for the given table. 1612 * @param selectionArgs You may include ?s in selection, which will be 1613 * replaced by the values from selectionArgs, in order that they 1614 * appear in the selection. The values will be bound as Strings. 1615 * @param groupBy A filter declaring how to group rows, formatted as an SQL 1616 * GROUP BY clause (excluding the GROUP BY itself). Passing null 1617 * will cause the rows to not be grouped. 1618 * @param having A filter declare which row groups to include in the cursor, 1619 * if row grouping is being used, formatted as an SQL HAVING 1620 * clause (excluding the HAVING itself). Passing null will cause 1621 * all row groups to be included, and is required when row 1622 * grouping is not being used. 1623 * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause 1624 * (excluding the ORDER BY itself). Passing null will use the 1625 * default sort order, which may be unordered. 1626 * @param limit Limits the number of rows returned by the query, 1627 * formatted as LIMIT clause. Passing null denotes no LIMIT clause. 1628 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1629 * {@link Cursor}s are not synchronized, see the documentation for more details. 1630 * @see Cursor 1631 */ query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)1632 public Cursor query(String table, String[] columns, String selection, 1633 String[] selectionArgs, String groupBy, String having, 1634 String orderBy, String limit) { 1635 1636 return query(false, table, columns, selection, selectionArgs, groupBy, 1637 having, orderBy, limit); 1638 } 1639 1640 /** 1641 * Runs the provided SQL and returns a {@link Cursor} over the result set. 1642 * 1643 * @param sql the SQL query. The SQL string must not be ; terminated 1644 * @param selectionArgs You may include ?s in where clause in the query, 1645 * which will be replaced by the values from selectionArgs. The 1646 * values will be bound as Strings. 1647 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1648 * {@link Cursor}s are not synchronized, see the documentation for more details. 1649 */ rawQuery(String sql, String[] selectionArgs)1650 public Cursor rawQuery(String sql, String[] selectionArgs) { 1651 return rawQueryWithFactory(null, sql, selectionArgs, null, null); 1652 } 1653 1654 /** 1655 * Runs the provided SQL and returns a {@link Cursor} over the result set. 1656 * 1657 * @param sql the SQL query. The SQL string must not be ; terminated 1658 * @param selectionArgs You may include ?s in where clause in the query, 1659 * which will be replaced by the values from selectionArgs. The 1660 * values will be bound as Strings. 1661 * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 1662 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 1663 * when the query is executed. 1664 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1665 * {@link Cursor}s are not synchronized, see the documentation for more details. 1666 */ rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal)1667 public Cursor rawQuery(String sql, String[] selectionArgs, 1668 CancellationSignal cancellationSignal) { 1669 return rawQueryWithFactory(null, sql, selectionArgs, null, cancellationSignal); 1670 } 1671 1672 /** 1673 * Runs the provided SQL and returns a cursor over the result set. 1674 * 1675 * @param cursorFactory the cursor factory to use, or null for the default factory 1676 * @param sql the SQL query. The SQL string must not be ; terminated 1677 * @param selectionArgs You may include ?s in where clause in the query, 1678 * which will be replaced by the values from selectionArgs. The 1679 * values will be bound as Strings. 1680 * @param editTable the name of the first table, which is editable 1681 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1682 * {@link Cursor}s are not synchronized, see the documentation for more details. 1683 */ rawQueryWithFactory( CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable)1684 public Cursor rawQueryWithFactory( 1685 CursorFactory cursorFactory, String sql, String[] selectionArgs, 1686 String editTable) { 1687 return rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, null); 1688 } 1689 1690 /** 1691 * Runs the provided SQL and returns a cursor over the result set. 1692 * 1693 * @param cursorFactory the cursor factory to use, or null for the default factory 1694 * @param sql the SQL query. The SQL string must not be ; terminated 1695 * @param selectionArgs You may include ?s in where clause in the query, 1696 * which will be replaced by the values from selectionArgs. The 1697 * values will be bound as Strings. 1698 * @param editTable the name of the first table, which is editable 1699 * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 1700 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 1701 * when the query is executed. 1702 * @return A {@link Cursor} object, which is positioned before the first entry. Note that 1703 * {@link Cursor}s are not synchronized, see the documentation for more details. 1704 */ rawQueryWithFactory( CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable, CancellationSignal cancellationSignal)1705 public Cursor rawQueryWithFactory( 1706 CursorFactory cursorFactory, String sql, String[] selectionArgs, 1707 String editTable, CancellationSignal cancellationSignal) { 1708 acquireReference(); 1709 try { 1710 SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable, 1711 cancellationSignal); 1712 return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory, 1713 selectionArgs); 1714 } finally { 1715 releaseReference(); 1716 } 1717 } 1718 1719 /** 1720 * Convenience method for inserting a row into the database. 1721 * 1722 * @param table the table to insert the row into 1723 * @param nullColumnHack optional; may be <code>null</code>. 1724 * SQL doesn't allow inserting a completely empty row without 1725 * naming at least one column name. If your provided <code>values</code> is 1726 * empty, no column names are known and an empty row can't be inserted. 1727 * If not set to null, the <code>nullColumnHack</code> parameter 1728 * provides the name of nullable column name to explicitly insert a NULL into 1729 * in the case where your <code>values</code> is empty. 1730 * @param values this map contains the initial column values for the 1731 * row. The keys should be the column names and the values the 1732 * column values 1733 * @return the row ID of the newly inserted row, or -1 if an error occurred 1734 */ insert(String table, String nullColumnHack, ContentValues values)1735 public long insert(String table, String nullColumnHack, ContentValues values) { 1736 try { 1737 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE); 1738 } catch (SQLException e) { 1739 Log.e(TAG, "Error inserting " + values, e); 1740 return -1; 1741 } 1742 } 1743 1744 /** 1745 * Convenience method for inserting a row into the database. 1746 * 1747 * @param table the table to insert the row into 1748 * @param nullColumnHack optional; may be <code>null</code>. 1749 * SQL doesn't allow inserting a completely empty row without 1750 * naming at least one column name. If your provided <code>values</code> is 1751 * empty, no column names are known and an empty row can't be inserted. 1752 * If not set to null, the <code>nullColumnHack</code> parameter 1753 * provides the name of nullable column name to explicitly insert a NULL into 1754 * in the case where your <code>values</code> is empty. 1755 * @param values this map contains the initial column values for the 1756 * row. The keys should be the column names and the values the 1757 * column values 1758 * @throws SQLException 1759 * @return the row ID of the newly inserted row, or -1 if an error occurred 1760 */ insertOrThrow(String table, String nullColumnHack, ContentValues values)1761 public long insertOrThrow(String table, String nullColumnHack, ContentValues values) 1762 throws SQLException { 1763 return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE); 1764 } 1765 1766 /** 1767 * Convenience method for replacing a row in the database. 1768 * Inserts a new row if a row does not already exist. 1769 * 1770 * @param table the table in which to replace the row 1771 * @param nullColumnHack optional; may be <code>null</code>. 1772 * SQL doesn't allow inserting a completely empty row without 1773 * naming at least one column name. If your provided <code>initialValues</code> is 1774 * empty, no column names are known and an empty row can't be inserted. 1775 * If not set to null, the <code>nullColumnHack</code> parameter 1776 * provides the name of nullable column name to explicitly insert a NULL into 1777 * in the case where your <code>initialValues</code> is empty. 1778 * @param initialValues this map contains the initial column values for 1779 * the row. The keys should be the column names and the values the column values. 1780 * @return the row ID of the newly inserted row, or -1 if an error occurred 1781 */ replace(String table, String nullColumnHack, ContentValues initialValues)1782 public long replace(String table, String nullColumnHack, ContentValues initialValues) { 1783 try { 1784 return insertWithOnConflict(table, nullColumnHack, initialValues, 1785 CONFLICT_REPLACE); 1786 } catch (SQLException e) { 1787 Log.e(TAG, "Error inserting " + initialValues, e); 1788 return -1; 1789 } 1790 } 1791 1792 /** 1793 * Convenience method for replacing a row in the database. 1794 * Inserts a new row if a row does not already exist. 1795 * 1796 * @param table the table in which to replace the row 1797 * @param nullColumnHack optional; may be <code>null</code>. 1798 * SQL doesn't allow inserting a completely empty row without 1799 * naming at least one column name. If your provided <code>initialValues</code> is 1800 * empty, no column names are known and an empty row can't be inserted. 1801 * If not set to null, the <code>nullColumnHack</code> parameter 1802 * provides the name of nullable column name to explicitly insert a NULL into 1803 * in the case where your <code>initialValues</code> is empty. 1804 * @param initialValues this map contains the initial column values for 1805 * the row. The keys should be the column names and the values the column values. 1806 * @throws SQLException 1807 * @return the row ID of the newly inserted row, or -1 if an error occurred 1808 */ replaceOrThrow(String table, String nullColumnHack, ContentValues initialValues)1809 public long replaceOrThrow(String table, String nullColumnHack, 1810 ContentValues initialValues) throws SQLException { 1811 return insertWithOnConflict(table, nullColumnHack, initialValues, 1812 CONFLICT_REPLACE); 1813 } 1814 1815 /** 1816 * General method for inserting a row into the database. 1817 * 1818 * @param table the table to insert the row into 1819 * @param nullColumnHack optional; may be <code>null</code>. 1820 * SQL doesn't allow inserting a completely empty row without 1821 * naming at least one column name. If your provided <code>initialValues</code> is 1822 * empty, no column names are known and an empty row can't be inserted. 1823 * If not set to null, the <code>nullColumnHack</code> parameter 1824 * provides the name of nullable column name to explicitly insert a NULL into 1825 * in the case where your <code>initialValues</code> is empty. 1826 * @param initialValues this map contains the initial column values for the 1827 * row. The keys should be the column names and the values the 1828 * column values 1829 * @param conflictAlgorithm for insert conflict resolver 1830 * @return the row ID of the newly inserted row OR <code>-1</code> if either the 1831 * input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE} 1832 * or an error occurred. 1833 */ insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm)1834 public long insertWithOnConflict(String table, String nullColumnHack, 1835 ContentValues initialValues, int conflictAlgorithm) { 1836 acquireReference(); 1837 try { 1838 StringBuilder sql = new StringBuilder(); 1839 sql.append("INSERT"); 1840 sql.append(CONFLICT_VALUES[conflictAlgorithm]); 1841 sql.append(" INTO "); 1842 sql.append(table); 1843 sql.append('('); 1844 1845 Object[] bindArgs = null; 1846 int size = (initialValues != null && !initialValues.isEmpty()) 1847 ? initialValues.size() : 0; 1848 if (size > 0) { 1849 bindArgs = new Object[size]; 1850 int i = 0; 1851 for (String colName : initialValues.keySet()) { 1852 sql.append((i > 0) ? "," : ""); 1853 sql.append(colName); 1854 bindArgs[i++] = initialValues.get(colName); 1855 } 1856 sql.append(')'); 1857 sql.append(" VALUES ("); 1858 for (i = 0; i < size; i++) { 1859 sql.append((i > 0) ? ",?" : "?"); 1860 } 1861 } else { 1862 sql.append(nullColumnHack).append(") VALUES (NULL"); 1863 } 1864 sql.append(')'); 1865 1866 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs); 1867 try { 1868 return statement.executeInsert(); 1869 } finally { 1870 statement.close(); 1871 } 1872 } finally { 1873 releaseReference(); 1874 } 1875 } 1876 1877 /** 1878 * Convenience method for deleting rows in the database. 1879 * 1880 * @param table the table to delete from 1881 * @param whereClause the optional WHERE clause to apply when deleting. 1882 * Passing null will delete all rows. 1883 * @param whereArgs You may include ?s in the where clause, which 1884 * will be replaced by the values from whereArgs. The values 1885 * will be bound as Strings. 1886 * @return the number of rows affected if a whereClause is passed in, 0 1887 * otherwise. To remove all rows and get a count pass "1" as the 1888 * whereClause. 1889 */ delete(String table, String whereClause, String[] whereArgs)1890 public int delete(String table, String whereClause, String[] whereArgs) { 1891 acquireReference(); 1892 try { 1893 SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table + 1894 (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs); 1895 try { 1896 return statement.executeUpdateDelete(); 1897 } finally { 1898 statement.close(); 1899 } 1900 } finally { 1901 releaseReference(); 1902 } 1903 } 1904 1905 /** 1906 * Convenience method for updating rows in the database. 1907 * 1908 * @param table the table to update in 1909 * @param values a map from column names to new column values. null is a 1910 * valid value that will be translated to NULL. 1911 * @param whereClause the optional WHERE clause to apply when updating. 1912 * Passing null will update all rows. 1913 * @param whereArgs You may include ?s in the where clause, which 1914 * will be replaced by the values from whereArgs. The values 1915 * will be bound as Strings. 1916 * @return the number of rows affected 1917 */ update(String table, ContentValues values, String whereClause, String[] whereArgs)1918 public int update(String table, ContentValues values, String whereClause, String[] whereArgs) { 1919 return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE); 1920 } 1921 1922 /** 1923 * Convenience method for updating rows in the database. 1924 * 1925 * @param table the table to update in 1926 * @param values a map from column names to new column values. null is a 1927 * valid value that will be translated to NULL. 1928 * @param whereClause the optional WHERE clause to apply when updating. 1929 * Passing null will update all rows. 1930 * @param whereArgs You may include ?s in the where clause, which 1931 * will be replaced by the values from whereArgs. The values 1932 * will be bound as Strings. 1933 * @param conflictAlgorithm for update conflict resolver 1934 * @return the number of rows affected 1935 */ updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm)1936 public int updateWithOnConflict(String table, ContentValues values, 1937 String whereClause, String[] whereArgs, int conflictAlgorithm) { 1938 if (values == null || values.isEmpty()) { 1939 throw new IllegalArgumentException("Empty values"); 1940 } 1941 1942 acquireReference(); 1943 try { 1944 StringBuilder sql = new StringBuilder(120); 1945 sql.append("UPDATE "); 1946 sql.append(CONFLICT_VALUES[conflictAlgorithm]); 1947 sql.append(table); 1948 sql.append(" SET "); 1949 1950 // move all bind args to one array 1951 int setValuesSize = values.size(); 1952 int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length); 1953 Object[] bindArgs = new Object[bindArgsSize]; 1954 int i = 0; 1955 for (String colName : values.keySet()) { 1956 sql.append((i > 0) ? "," : ""); 1957 sql.append(colName); 1958 bindArgs[i++] = values.get(colName); 1959 sql.append("=?"); 1960 } 1961 if (whereArgs != null) { 1962 for (i = setValuesSize; i < bindArgsSize; i++) { 1963 bindArgs[i] = whereArgs[i - setValuesSize]; 1964 } 1965 } 1966 if (!TextUtils.isEmpty(whereClause)) { 1967 sql.append(" WHERE "); 1968 sql.append(whereClause); 1969 } 1970 1971 SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs); 1972 try { 1973 return statement.executeUpdateDelete(); 1974 } finally { 1975 statement.close(); 1976 } 1977 } finally { 1978 releaseReference(); 1979 } 1980 } 1981 1982 /** 1983 * Execute a single SQL statement that is NOT a SELECT 1984 * or any other SQL statement that returns data. 1985 * <p> 1986 * It has no means to return any data (such as the number of affected rows). 1987 * Instead, you're encouraged to use {@link #insert(String, String, ContentValues)}, 1988 * {@link #update(String, ContentValues, String, String[])}, et al, when possible. 1989 * </p> 1990 * <p> 1991 * When using {@link #enableWriteAheadLogging()}, journal_mode is 1992 * automatically managed by this class. So, do not set journal_mode 1993 * using "PRAGMA journal_mode'<value>" statement if your app is using 1994 * {@link #enableWriteAheadLogging()} 1995 * </p> 1996 * <p> 1997 * Note that {@code PRAGMA} values which apply on a per-connection basis 1998 * should <em>not</em> be configured using this method; you should instead 1999 * use {@link #execPerConnectionSQL} to ensure that they are uniformly 2000 * applied to all current and future connections. 2001 * </p> 2002 * 2003 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are 2004 * not supported. 2005 * @throws SQLException if the SQL string is invalid 2006 */ execSQL(String sql)2007 public void execSQL(String sql) throws SQLException { 2008 executeSql(sql, null); 2009 } 2010 2011 /** 2012 * Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE. 2013 * <p> 2014 * For INSERT statements, use any of the following instead. 2015 * <ul> 2016 * <li>{@link #insert(String, String, ContentValues)}</li> 2017 * <li>{@link #insertOrThrow(String, String, ContentValues)}</li> 2018 * <li>{@link #insertWithOnConflict(String, String, ContentValues, int)}</li> 2019 * </ul> 2020 * <p> 2021 * For UPDATE statements, use any of the following instead. 2022 * <ul> 2023 * <li>{@link #update(String, ContentValues, String, String[])}</li> 2024 * <li>{@link #updateWithOnConflict(String, ContentValues, String, String[], int)}</li> 2025 * </ul> 2026 * <p> 2027 * For DELETE statements, use any of the following instead. 2028 * <ul> 2029 * <li>{@link #delete(String, String, String[])}</li> 2030 * </ul> 2031 * <p> 2032 * For example, the following are good candidates for using this method: 2033 * <ul> 2034 * <li>ALTER TABLE</li> 2035 * <li>CREATE or DROP table / trigger / view / index / virtual table</li> 2036 * <li>REINDEX</li> 2037 * <li>RELEASE</li> 2038 * <li>SAVEPOINT</li> 2039 * <li>PRAGMA that returns no data</li> 2040 * </ul> 2041 * </p> 2042 * <p> 2043 * When using {@link #enableWriteAheadLogging()}, journal_mode is 2044 * automatically managed by this class. So, do not set journal_mode 2045 * using "PRAGMA journal_mode'<value>" statement if your app is using 2046 * {@link #enableWriteAheadLogging()} 2047 * </p> 2048 * <p> 2049 * Note that {@code PRAGMA} values which apply on a per-connection basis 2050 * should <em>not</em> be configured using this method; you should instead 2051 * use {@link #execPerConnectionSQL} to ensure that they are uniformly 2052 * applied to all current and future connections. 2053 * </p> 2054 * 2055 * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are 2056 * not supported. 2057 * @param bindArgs only byte[], String, Long and Double are supported in bindArgs. 2058 * @throws SQLException if the SQL string is invalid 2059 */ execSQL(String sql, Object[] bindArgs)2060 public void execSQL(String sql, Object[] bindArgs) throws SQLException { 2061 if (bindArgs == null) { 2062 throw new IllegalArgumentException("Empty bindArgs"); 2063 } 2064 executeSql(sql, bindArgs); 2065 } 2066 2067 /** {@hide} */ executeSql(String sql, Object[] bindArgs)2068 public int executeSql(String sql, Object[] bindArgs) throws SQLException { 2069 acquireReference(); 2070 try { 2071 final int statementType = DatabaseUtils.getSqlStatementType(sql); 2072 if (statementType == DatabaseUtils.STATEMENT_ATTACH) { 2073 boolean disableWal = false; 2074 synchronized (mLock) { 2075 if (!mHasAttachedDbsLocked) { 2076 mHasAttachedDbsLocked = true; 2077 disableWal = true; 2078 mConnectionPoolLocked.disableIdleConnectionHandler(); 2079 } 2080 } 2081 if (disableWal) { 2082 disableWriteAheadLogging(); 2083 } 2084 } 2085 2086 try (SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs)) { 2087 return statement.executeUpdateDelete(); 2088 } finally { 2089 // If schema was updated, close non-primary connections, otherwise they might 2090 // have outdated schema information 2091 if (statementType == DatabaseUtils.STATEMENT_DDL) { 2092 mConnectionPoolLocked.closeAvailableNonPrimaryConnectionsAndLogExceptions(); 2093 } 2094 } 2095 } finally { 2096 releaseReference(); 2097 } 2098 } 2099 2100 /** 2101 * Verifies that a SQL SELECT statement is valid by compiling it. 2102 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}. 2103 * 2104 * @param sql SQL to be validated 2105 * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 2106 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 2107 * when the query is executed. 2108 * @throws SQLiteException if {@code sql} is invalid 2109 */ validateSql(@onNull String sql, @Nullable CancellationSignal cancellationSignal)2110 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) { 2111 getThreadSession().prepare(sql, 2112 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null); 2113 } 2114 2115 /** 2116 * Returns true if the database is opened as read only. 2117 * 2118 * @return True if database is opened as read only. 2119 */ isReadOnly()2120 public boolean isReadOnly() { 2121 synchronized (mLock) { 2122 return isReadOnlyLocked(); 2123 } 2124 } 2125 isReadOnlyLocked()2126 private boolean isReadOnlyLocked() { 2127 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY; 2128 } 2129 2130 /** 2131 * Returns true if the database is in-memory db. 2132 * 2133 * @return True if the database is in-memory. 2134 * @hide 2135 */ isInMemoryDatabase()2136 public boolean isInMemoryDatabase() { 2137 synchronized (mLock) { 2138 return mConfigurationLocked.isInMemoryDb(); 2139 } 2140 } 2141 2142 /** 2143 * Returns true if the database is currently open. 2144 * 2145 * @return True if the database is currently open (has not been closed). 2146 */ isOpen()2147 public boolean isOpen() { 2148 synchronized (mLock) { 2149 return mConnectionPoolLocked != null; 2150 } 2151 } 2152 2153 /** 2154 * Returns true if the new version code is greater than the current database version. 2155 * 2156 * @param newVersion The new version code. 2157 * @return True if the new version code is greater than the current database version. 2158 */ needUpgrade(int newVersion)2159 public boolean needUpgrade(int newVersion) { 2160 return newVersion > getVersion(); 2161 } 2162 2163 /** 2164 * Gets the path to the database file. 2165 * 2166 * @return The path to the database file. 2167 */ getPath()2168 public final String getPath() { 2169 synchronized (mLock) { 2170 return mConfigurationLocked.path; 2171 } 2172 } 2173 2174 /** 2175 * Sets the locale for this database. Does nothing if this database has 2176 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only. 2177 * 2178 * @param locale The new locale. 2179 * 2180 * @throws SQLException if the locale could not be set. The most common reason 2181 * for this is that there is no collator available for the locale you requested. 2182 * In this case the database remains unchanged. 2183 */ setLocale(Locale locale)2184 public void setLocale(Locale locale) { 2185 if (locale == null) { 2186 throw new IllegalArgumentException("locale must not be null."); 2187 } 2188 2189 synchronized (mLock) { 2190 throwIfNotOpenLocked(); 2191 2192 final Locale oldLocale = mConfigurationLocked.locale; 2193 mConfigurationLocked.locale = locale; 2194 try { 2195 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 2196 } catch (RuntimeException ex) { 2197 mConfigurationLocked.locale = oldLocale; 2198 throw ex; 2199 } 2200 } 2201 } 2202 2203 /** 2204 * Sets the maximum size of the prepared-statement cache for this database. 2205 * (size of the cache = number of compiled-sql-statements stored in the cache). 2206 *<p> 2207 * Maximum cache size can ONLY be increased from its current size (default = 10). 2208 * If this method is called with smaller size than the current maximum value, 2209 * then IllegalStateException is thrown. 2210 *<p> 2211 * This method is thread-safe. 2212 * 2213 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE}) 2214 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}. 2215 */ setMaxSqlCacheSize(int cacheSize)2216 public void setMaxSqlCacheSize(int cacheSize) { 2217 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) { 2218 throw new IllegalStateException( 2219 "expected value between 0 and " + MAX_SQL_CACHE_SIZE); 2220 } 2221 2222 synchronized (mLock) { 2223 throwIfNotOpenLocked(); 2224 2225 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize; 2226 mConfigurationLocked.maxSqlCacheSize = cacheSize; 2227 try { 2228 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 2229 } catch (RuntimeException ex) { 2230 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize; 2231 throw ex; 2232 } 2233 } 2234 } 2235 2236 /** 2237 * Sets whether foreign key constraints are enabled for the database. 2238 * <p> 2239 * By default, foreign key constraints are not enforced by the database. 2240 * This method allows an application to enable foreign key constraints. 2241 * It must be called each time the database is opened to ensure that foreign 2242 * key constraints are enabled for the session. 2243 * </p><p> 2244 * A good time to call this method is right after calling {@link #openOrCreateDatabase} 2245 * or in the {@link SQLiteOpenHelper#onConfigure} callback. 2246 * </p><p> 2247 * When foreign key constraints are disabled, the database does not check whether 2248 * changes to the database will violate foreign key constraints. Likewise, when 2249 * foreign key constraints are disabled, the database will not execute cascade 2250 * delete or update triggers. As a result, it is possible for the database 2251 * state to become inconsistent. To perform a database integrity check, 2252 * call {@link #isDatabaseIntegrityOk}. 2253 * </p><p> 2254 * This method must not be called while a transaction is in progress. 2255 * </p><p> 2256 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a> 2257 * for more details about foreign key constraint support. 2258 * </p> 2259 * 2260 * @param enable True to enable foreign key constraints, false to disable them. 2261 * 2262 * @throws IllegalStateException if the are transactions is in progress 2263 * when this method is called. 2264 */ setForeignKeyConstraintsEnabled(boolean enable)2265 public void setForeignKeyConstraintsEnabled(boolean enable) { 2266 synchronized (mLock) { 2267 throwIfNotOpenLocked(); 2268 2269 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) { 2270 return; 2271 } 2272 2273 mConfigurationLocked.foreignKeyConstraintsEnabled = enable; 2274 try { 2275 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 2276 } catch (RuntimeException ex) { 2277 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable; 2278 throw ex; 2279 } 2280 } 2281 } 2282 2283 /** 2284 * This method enables parallel execution of queries from multiple threads on the 2285 * same database. It does this by opening multiple connections to the database 2286 * and using a different database connection for each query. The database 2287 * journal mode is also changed to enable writes to proceed concurrently with reads. 2288 * <p> 2289 * When write-ahead logging is not enabled (the default), it is not possible for 2290 * reads and writes to occur on the database at the same time. Before modifying the 2291 * database, the writer implicitly acquires an exclusive lock on the database which 2292 * prevents readers from accessing the database until the write is completed. 2293 * </p><p> 2294 * In contrast, when write-ahead logging is enabled (by calling this method), write 2295 * operations occur in a separate log file which allows reads to proceed concurrently. 2296 * While a write is in progress, readers on other threads will perceive the state 2297 * of the database as it was before the write began. When the write completes, readers 2298 * on other threads will then perceive the new state of the database. 2299 * </p><p> 2300 * It is a good idea to enable write-ahead logging whenever a database will be 2301 * concurrently accessed and modified by multiple threads at the same time. 2302 * However, write-ahead logging uses significantly more memory than ordinary 2303 * journaling because there are multiple connections to the same database. 2304 * So if a database will only be used by a single thread, or if optimizing 2305 * concurrency is not very important, then write-ahead logging should be disabled. 2306 * </p><p> 2307 * After calling this method, execution of queries in parallel is enabled as long as 2308 * the database remains open. To disable execution of queries in parallel, either 2309 * call {@link #disableWriteAheadLogging} or close the database and reopen it. 2310 * </p><p> 2311 * The maximum number of connections used to execute queries in parallel is 2312 * dependent upon the device memory and possibly other properties. 2313 * </p><p> 2314 * If a query is part of a transaction, then it is executed on the same database handle the 2315 * transaction was begun. 2316 * </p><p> 2317 * Writers should use {@link #beginTransactionNonExclusive()} or 2318 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)} 2319 * to start a transaction. Non-exclusive mode allows database file to be in readable 2320 * by other threads executing queries. 2321 * </p><p> 2322 * If the database has any attached databases, then execution of queries in parallel is NOT 2323 * possible. Likewise, write-ahead logging is not supported for read-only databases 2324 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false. 2325 * </p><p> 2326 * The best way to enable write-ahead logging is to pass the 2327 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is 2328 * more efficient than calling {@link #enableWriteAheadLogging}. 2329 * <code><pre> 2330 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory, 2331 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING, 2332 * myDatabaseErrorHandler); 2333 * </pre></code> 2334 * </p><p> 2335 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging} 2336 * after opening the database. 2337 * <code><pre> 2338 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory, 2339 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler); 2340 * db.enableWriteAheadLogging(); 2341 * </pre></code> 2342 * </p><p> 2343 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for 2344 * more details about how write-ahead logging works. 2345 * </p> 2346 * 2347 * @return True if write-ahead logging is enabled. 2348 * 2349 * @throws IllegalStateException if there are transactions in progress at the 2350 * time this method is called. WAL mode can only be changed when there are no 2351 * transactions in progress. 2352 * 2353 * @see #ENABLE_WRITE_AHEAD_LOGGING 2354 * @see #disableWriteAheadLogging 2355 */ enableWriteAheadLogging()2356 public boolean enableWriteAheadLogging() { 2357 synchronized (mLock) { 2358 throwIfNotOpenLocked(); 2359 2360 if (mConfigurationLocked.resolveJournalMode().equalsIgnoreCase( 2361 SQLiteDatabase.JOURNAL_MODE_WAL)) { 2362 return true; 2363 } 2364 2365 if (isReadOnlyLocked()) { 2366 // WAL doesn't make sense for readonly-databases. 2367 // TODO: True, but connection pooling does still make sense... 2368 return false; 2369 } 2370 2371 if (mConfigurationLocked.isInMemoryDb()) { 2372 Log.i(TAG, "can't enable WAL for memory databases."); 2373 return false; 2374 } 2375 2376 // make sure this database has NO attached databases because sqlite's write-ahead-logging 2377 // doesn't work for databases with attached databases 2378 if (mHasAttachedDbsLocked) { 2379 if (Log.isLoggable(TAG, Log.DEBUG)) { 2380 Log.d(TAG, "this database: " + mConfigurationLocked.label 2381 + " has attached databases. can't enable WAL."); 2382 } 2383 return false; 2384 } 2385 2386 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING; 2387 try { 2388 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 2389 } catch (RuntimeException ex) { 2390 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING; 2391 throw ex; 2392 } 2393 } 2394 return true; 2395 } 2396 2397 /** 2398 * This method disables the features enabled by {@link #enableWriteAheadLogging()}. 2399 * 2400 * @throws IllegalStateException if there are transactions in progress at the 2401 * time this method is called. WAL mode can only be changed when there are no 2402 * transactions in progress. 2403 * 2404 * @see #enableWriteAheadLogging 2405 */ disableWriteAheadLogging()2406 public void disableWriteAheadLogging() { 2407 synchronized (mLock) { 2408 throwIfNotOpenLocked(); 2409 2410 final int oldFlags = mConfigurationLocked.openFlags; 2411 // WAL was never enabled for this database, so there's nothing left to do. 2412 if (!mConfigurationLocked.resolveJournalMode().equalsIgnoreCase( 2413 SQLiteDatabase.JOURNAL_MODE_WAL)) { 2414 return; 2415 } 2416 2417 // If an app explicitly disables WAL, it takes priority over any directive 2418 // to use the legacy "compatibility WAL" mode. 2419 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING; 2420 mConfigurationLocked.openFlags &= ~ENABLE_LEGACY_COMPATIBILITY_WAL; 2421 2422 try { 2423 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 2424 } catch (RuntimeException ex) { 2425 mConfigurationLocked.openFlags = oldFlags; 2426 throw ex; 2427 } 2428 } 2429 } 2430 2431 /** 2432 * Returns true if write-ahead logging has been enabled for this database. 2433 * 2434 * @return True if write-ahead logging has been enabled for this database. 2435 * 2436 * @see #enableWriteAheadLogging 2437 * @see #ENABLE_WRITE_AHEAD_LOGGING 2438 */ isWriteAheadLoggingEnabled()2439 public boolean isWriteAheadLoggingEnabled() { 2440 synchronized (mLock) { 2441 throwIfNotOpenLocked(); 2442 2443 return mConfigurationLocked.resolveJournalMode().equalsIgnoreCase( 2444 SQLiteDatabase.JOURNAL_MODE_WAL); 2445 } 2446 } 2447 2448 /** 2449 * Collect statistics about all open databases in the current process. 2450 * Used by bug report. 2451 */ getDbStats()2452 static ArrayList<DbStats> getDbStats() { 2453 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>(); 2454 for (SQLiteDatabase db : getActiveDatabases()) { 2455 db.collectDbStats(dbStatsList); 2456 } 2457 return dbStatsList; 2458 } 2459 2460 @UnsupportedAppUsage collectDbStats(ArrayList<DbStats> dbStatsList)2461 private void collectDbStats(ArrayList<DbStats> dbStatsList) { 2462 synchronized (mLock) { 2463 if (mConnectionPoolLocked != null) { 2464 mConnectionPoolLocked.collectDbStats(dbStatsList); 2465 } 2466 } 2467 } 2468 2469 @UnsupportedAppUsage getActiveDatabases()2470 private static ArrayList<SQLiteDatabase> getActiveDatabases() { 2471 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>(); 2472 synchronized (sActiveDatabases) { 2473 databases.addAll(sActiveDatabases.keySet()); 2474 } 2475 return databases; 2476 } 2477 getActiveDatabasePools()2478 private static ArrayList<SQLiteConnectionPool> getActiveDatabasePools() { 2479 ArrayList<SQLiteConnectionPool> connectionPools = new ArrayList<SQLiteConnectionPool>(); 2480 synchronized (sActiveDatabases) { 2481 for (SQLiteDatabase db : sActiveDatabases.keySet()) { 2482 synchronized (db.mLock) { 2483 if (db.mConnectionPoolLocked != null) { 2484 connectionPools.add(db.mConnectionPoolLocked); 2485 } 2486 } 2487 } 2488 } 2489 return connectionPools; 2490 } 2491 2492 /** 2493 * Dump detailed information about all open databases in the current process. 2494 * Used by bug report. 2495 */ dumpAll(Printer printer, boolean verbose, boolean isSystem)2496 static void dumpAll(Printer printer, boolean verbose, boolean isSystem) { 2497 // Use this ArraySet to collect file paths. 2498 final ArraySet<String> directories = new ArraySet<>(); 2499 2500 // Accounting across all databases 2501 long totalStatementsTimeInMs = 0; 2502 long totalStatementsCount = 0; 2503 2504 ArrayList<SQLiteConnectionPool> activeConnectionPools = getActiveDatabasePools(); 2505 2506 activeConnectionPools.sort( 2507 (a, b) -> Long.compare(b.getTotalStatementsCount(), a.getTotalStatementsCount())); 2508 for (SQLiteConnectionPool dbPool : activeConnectionPools) { 2509 dbPool.dump(printer, verbose, directories); 2510 totalStatementsTimeInMs += dbPool.getTotalStatementsTime(); 2511 totalStatementsCount += dbPool.getTotalStatementsCount(); 2512 } 2513 2514 if (totalStatementsCount > 0) { 2515 // Only print when there is information available 2516 2517 // Sorted statements per database 2518 printer.println("Statements Executed per Database"); 2519 for (SQLiteConnectionPool dbPool : activeConnectionPools) { 2520 printer.println( 2521 " " + dbPool.getPath() + " : " + dbPool.getTotalStatementsCount()); 2522 } 2523 printer.println(""); 2524 printer.println( 2525 "Total Statements Executed for all Active Databases: " + totalStatementsCount); 2526 2527 // Sorted execution time per database 2528 activeConnectionPools.sort( 2529 (a, b) -> Long.compare(b.getTotalStatementsTime(), a.getTotalStatementsTime())); 2530 printer.println(""); 2531 printer.println(""); 2532 printer.println("Statement Time per Database (ms)"); 2533 for (SQLiteConnectionPool dbPool : activeConnectionPools) { 2534 printer.println( 2535 " " + dbPool.getPath() + " : " + dbPool.getTotalStatementsTime()); 2536 } 2537 printer.println("Total Statements Time for all Active Databases (ms): " 2538 + totalStatementsTimeInMs); 2539 } 2540 2541 // Dump DB files in the directories. 2542 if (directories.size() > 0) { 2543 final String[] dirs = directories.toArray(new String[directories.size()]); 2544 Arrays.sort(dirs); 2545 for (String dir : dirs) { 2546 dumpDatabaseDirectory(printer, new File(dir), isSystem); 2547 } 2548 } 2549 } 2550 dumpDatabaseDirectory(Printer pw, File dir, boolean isSystem)2551 private static void dumpDatabaseDirectory(Printer pw, File dir, boolean isSystem) { 2552 pw.println(""); 2553 pw.println("Database files in " + dir.getAbsolutePath() + ":"); 2554 final File[] files = dir.listFiles(); 2555 if (files == null || files.length == 0) { 2556 pw.println(" [none]"); 2557 return; 2558 } 2559 Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName())); 2560 2561 for (File f : files) { 2562 if (isSystem) { 2563 // If called within the system server, the directory contains other files too, so 2564 // filter by file extensions. 2565 // (If it's an app, just print all files because they may not use *.db 2566 // extension.) 2567 final String name = f.getName(); 2568 if (!(name.endsWith(".db") || name.endsWith(".db-wal") 2569 || name.endsWith(".db-journal") 2570 || name.endsWith(SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX))) { 2571 continue; 2572 } 2573 } 2574 pw.println(String.format(" %-40s %7db %s", f.getName(), f.length(), 2575 SQLiteDatabase.getFileTimestamps(f.getAbsolutePath()))); 2576 } 2577 } 2578 2579 /** 2580 * Returns list of full pathnames of all attached databases including the main database 2581 * by executing 'pragma database_list' on the database. 2582 * 2583 * @return ArrayList of pairs of (database name, database file path) or null if the database 2584 * is not open. 2585 */ getAttachedDbs()2586 public List<Pair<String, String>> getAttachedDbs() { 2587 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>(); 2588 synchronized (mLock) { 2589 if (mConnectionPoolLocked == null) { 2590 return null; // not open 2591 } 2592 2593 if (!mHasAttachedDbsLocked) { 2594 // No attached databases. 2595 // There is a small window where attached databases exist but this flag is not 2596 // set yet. This can occur when this thread is in a race condition with another 2597 // thread that is executing the SQL statement: "attach database <blah> as <foo>" 2598 // If this thread is NOT ok with such a race condition (and thus possibly not 2599 // receivethe entire list of attached databases), then the caller should ensure 2600 // that no thread is executing any SQL statements while a thread is calling this 2601 // method. Typically, this method is called when 'adb bugreport' is done or the 2602 // caller wants to collect stats on the database and all its attached databases. 2603 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path)); 2604 return attachedDbs; 2605 } 2606 2607 acquireReference(); 2608 } 2609 2610 try { 2611 // has attached databases. query sqlite to get the list of attached databases. 2612 Cursor c = null; 2613 try { 2614 c = rawQuery("pragma database_list;", null); 2615 while (c.moveToNext()) { 2616 // sqlite returns a row for each database in the returned list of databases. 2617 // in each row, 2618 // 1st column is the database name such as main, or the database 2619 // name specified on the "ATTACH" command 2620 // 2nd column is the database file path. 2621 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2))); 2622 } 2623 } finally { 2624 if (c != null) { 2625 c.close(); 2626 } 2627 } 2628 return attachedDbs; 2629 } finally { 2630 releaseReference(); 2631 } 2632 } 2633 2634 /** 2635 * Runs 'pragma integrity_check' on the given database (and all the attached databases) 2636 * and returns true if the given database (and all its attached databases) pass integrity_check, 2637 * false otherwise. 2638 *<p> 2639 * If the result is false, then this method logs the errors reported by the integrity_check 2640 * command execution. 2641 *<p> 2642 * Note that 'pragma integrity_check' on a database can take a long time. 2643 * 2644 * @return true if the given database (and all its attached databases) pass integrity_check, 2645 * false otherwise. 2646 */ isDatabaseIntegrityOk()2647 public boolean isDatabaseIntegrityOk() { 2648 acquireReference(); 2649 try { 2650 List<Pair<String, String>> attachedDbs = null; 2651 try { 2652 attachedDbs = getAttachedDbs(); 2653 if (attachedDbs == null) { 2654 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " + 2655 "be retrieved. probably because the database is closed"); 2656 } 2657 } catch (SQLiteException e) { 2658 // can't get attachedDb list. do integrity check on the main database 2659 attachedDbs = new ArrayList<Pair<String, String>>(); 2660 attachedDbs.add(new Pair<String, String>("main", getPath())); 2661 } 2662 2663 for (int i = 0; i < attachedDbs.size(); i++) { 2664 Pair<String, String> p = attachedDbs.get(i); 2665 SQLiteStatement prog = null; 2666 try { 2667 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);"); 2668 String rslt = prog.simpleQueryForString(); 2669 if (!rslt.equalsIgnoreCase("ok")) { 2670 // integrity_checker failed on main or attached databases 2671 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt); 2672 return false; 2673 } 2674 } finally { 2675 if (prog != null) prog.close(); 2676 } 2677 } 2678 } finally { 2679 releaseReference(); 2680 } 2681 return true; 2682 } 2683 2684 @Override toString()2685 public String toString() { 2686 return "SQLiteDatabase: " + getPath(); 2687 } 2688 throwIfNotOpenLocked()2689 private void throwIfNotOpenLocked() { 2690 if (mConnectionPoolLocked == null) { 2691 throw new IllegalStateException("The database '" + mConfigurationLocked.label 2692 + "' is not open."); 2693 } 2694 } 2695 2696 /** 2697 * Used to allow returning sub-classes of {@link Cursor} when calling query. 2698 */ 2699 public interface CursorFactory { 2700 /** 2701 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}. 2702 */ newCursor(SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable, SQLiteQuery query)2703 public Cursor newCursor(SQLiteDatabase db, 2704 SQLiteCursorDriver masterQuery, String editTable, 2705 SQLiteQuery query); 2706 } 2707 2708 /** 2709 * A callback interface for a custom sqlite3 function. 2710 * This can be used to create a function that can be called from 2711 * sqlite3 database triggers. 2712 * @hide 2713 */ 2714 public interface CustomFunction { callback(String[] args)2715 public void callback(String[] args); 2716 } 2717 2718 /** 2719 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase} 2720 */ 2721 public static final class OpenParams { 2722 private final int mOpenFlags; 2723 private final CursorFactory mCursorFactory; 2724 private final DatabaseErrorHandler mErrorHandler; 2725 private final int mLookasideSlotSize; 2726 private final int mLookasideSlotCount; 2727 private final long mIdleConnectionTimeout; 2728 private final String mJournalMode; 2729 private final String mSyncMode; 2730 OpenParams(int openFlags, CursorFactory cursorFactory, DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeout, String journalMode, String syncMode)2731 private OpenParams(int openFlags, CursorFactory cursorFactory, 2732 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount, 2733 long idleConnectionTimeout, String journalMode, String syncMode) { 2734 mOpenFlags = openFlags; 2735 mCursorFactory = cursorFactory; 2736 mErrorHandler = errorHandler; 2737 mLookasideSlotSize = lookasideSlotSize; 2738 mLookasideSlotCount = lookasideSlotCount; 2739 mIdleConnectionTimeout = idleConnectionTimeout; 2740 mJournalMode = journalMode; 2741 mSyncMode = syncMode; 2742 } 2743 2744 /** 2745 * Returns size in bytes of each lookaside slot or -1 if not set. 2746 * 2747 * @see Builder#setLookasideConfig(int, int) 2748 */ 2749 @IntRange(from = -1) getLookasideSlotSize()2750 public int getLookasideSlotSize() { 2751 return mLookasideSlotSize; 2752 } 2753 2754 /** 2755 * Returns total number of lookaside memory slots per database connection or -1 if not 2756 * set. 2757 * 2758 * @see Builder#setLookasideConfig(int, int) 2759 */ 2760 @IntRange(from = -1) getLookasideSlotCount()2761 public int getLookasideSlotCount() { 2762 return mLookasideSlotCount; 2763 } 2764 2765 /** 2766 * Returns flags to control database access mode. Default value is 0. 2767 * 2768 * @see Builder#setOpenFlags(int) 2769 */ 2770 @DatabaseOpenFlags getOpenFlags()2771 public int getOpenFlags() { 2772 return mOpenFlags; 2773 } 2774 2775 /** 2776 * Returns an optional factory class that is called to instantiate a cursor when query 2777 * is called 2778 * 2779 * @see Builder#setCursorFactory(CursorFactory) 2780 */ 2781 @Nullable getCursorFactory()2782 public CursorFactory getCursorFactory() { 2783 return mCursorFactory; 2784 } 2785 2786 /** 2787 * Returns handler for database corruption errors 2788 * 2789 * @see Builder#setErrorHandler(DatabaseErrorHandler) 2790 */ 2791 @Nullable getErrorHandler()2792 public DatabaseErrorHandler getErrorHandler() { 2793 return mErrorHandler; 2794 } 2795 2796 /** 2797 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle 2798 * before it is closed and removed from the pool. 2799 * <p>If the value isn't set, the timeout defaults to the system wide timeout 2800 * 2801 * @return timeout in milliseconds or -1 if the value wasn't set. 2802 */ getIdleConnectionTimeout()2803 public long getIdleConnectionTimeout() { 2804 return mIdleConnectionTimeout; 2805 } 2806 2807 /** 2808 * Returns <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a>. 2809 * set via {@link Builder#setJournalMode(String)}. 2810 */ 2811 @Nullable getJournalMode()2812 public String getJournalMode() { 2813 return mJournalMode; 2814 } 2815 2816 /** 2817 * Returns <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>. 2818 * If not set, a system wide default will be used. 2819 * @see Builder#setSynchronousMode(String) 2820 */ 2821 @Nullable getSynchronousMode()2822 public String getSynchronousMode() { 2823 return mSyncMode; 2824 } 2825 2826 /** 2827 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with 2828 * {@code this} parameters. 2829 * @hide 2830 */ 2831 @NonNull toBuilder()2832 public Builder toBuilder() { 2833 return new Builder(this); 2834 } 2835 2836 /** 2837 * Builder for {@link OpenParams}. 2838 */ 2839 public static final class Builder { 2840 private int mLookasideSlotSize = -1; 2841 private int mLookasideSlotCount = -1; 2842 private long mIdleConnectionTimeout = -1; 2843 private int mOpenFlags; 2844 private CursorFactory mCursorFactory; 2845 private DatabaseErrorHandler mErrorHandler; 2846 private String mJournalMode; 2847 private String mSyncMode; 2848 Builder()2849 public Builder() { 2850 } 2851 Builder(OpenParams params)2852 public Builder(OpenParams params) { 2853 mLookasideSlotSize = params.mLookasideSlotSize; 2854 mLookasideSlotCount = params.mLookasideSlotCount; 2855 mOpenFlags = params.mOpenFlags; 2856 mCursorFactory = params.mCursorFactory; 2857 mErrorHandler = params.mErrorHandler; 2858 mJournalMode = params.mJournalMode; 2859 mSyncMode = params.mSyncMode; 2860 } 2861 2862 /** 2863 * Configures 2864 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a> 2865 * 2866 * <p>SQLite default settings will be used, if this method isn't called. 2867 * Use {@code setLookasideConfig(0,0)} to disable lookaside 2868 * 2869 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a 2870 * recommendation. The system may choose different values depending on a device, e.g. 2871 * lookaside allocations can be disabled on low-RAM devices 2872 * 2873 * @param slotSize The size in bytes of each lookaside slot. 2874 * @param slotCount The total number of lookaside memory slots per database connection. 2875 */ setLookasideConfig(@ntRangefrom = 0) final int slotSize, @IntRange(from = 0) final int slotCount)2876 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize, 2877 @IntRange(from = 0) final int slotCount) { 2878 Preconditions.checkArgument(slotSize >= 0, 2879 "lookasideSlotCount cannot be negative"); 2880 Preconditions.checkArgument(slotCount >= 0, 2881 "lookasideSlotSize cannot be negative"); 2882 Preconditions.checkArgument( 2883 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0), 2884 "Invalid configuration: %d, %d", slotSize, slotCount); 2885 2886 mLookasideSlotSize = slotSize; 2887 mLookasideSlotCount = slotCount; 2888 return this; 2889 } 2890 2891 /** 2892 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set 2893 * @hide 2894 */ isWriteAheadLoggingEnabled()2895 public boolean isWriteAheadLoggingEnabled() { 2896 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0; 2897 } 2898 2899 /** 2900 * Sets flags to control database access mode 2901 * @param openFlags The new flags to set 2902 * @see #OPEN_READWRITE 2903 * @see #OPEN_READONLY 2904 * @see #CREATE_IF_NECESSARY 2905 * @see #NO_LOCALIZED_COLLATORS 2906 * @see #ENABLE_WRITE_AHEAD_LOGGING 2907 * @return same builder instance for chaining multiple calls into a single statement 2908 */ 2909 @NonNull setOpenFlags(@atabaseOpenFlags int openFlags)2910 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) { 2911 mOpenFlags = openFlags; 2912 return this; 2913 } 2914 2915 /** 2916 * Adds flags to control database access mode 2917 * 2918 * @param openFlags The new flags to add 2919 * @return same builder instance for chaining multiple calls into a single statement 2920 */ 2921 @NonNull addOpenFlags(@atabaseOpenFlags int openFlags)2922 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) { 2923 mOpenFlags |= openFlags; 2924 return this; 2925 } 2926 2927 /** 2928 * Removes database access mode flags 2929 * 2930 * @param openFlags Flags to remove 2931 * @return same builder instance for chaining multiple calls into a single statement 2932 */ 2933 @NonNull removeOpenFlags(@atabaseOpenFlags int openFlags)2934 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) { 2935 mOpenFlags &= ~openFlags; 2936 return this; 2937 } 2938 2939 /** 2940 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true}, 2941 * unsets otherwise 2942 * @hide 2943 */ setWriteAheadLoggingEnabled(boolean enabled)2944 public void setWriteAheadLoggingEnabled(boolean enabled) { 2945 if (enabled) { 2946 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING); 2947 } else { 2948 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING); 2949 } 2950 } 2951 2952 /** 2953 * Set an optional factory class that is called to instantiate a cursor when query 2954 * is called. 2955 * 2956 * @param cursorFactory instance 2957 * @return same builder instance for chaining multiple calls into a single statement 2958 */ 2959 @NonNull setCursorFactory(@ullable CursorFactory cursorFactory)2960 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) { 2961 mCursorFactory = cursorFactory; 2962 return this; 2963 } 2964 2965 2966 /** 2967 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors 2968 */ 2969 @NonNull setErrorHandler(@ullable DatabaseErrorHandler errorHandler)2970 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) { 2971 mErrorHandler = errorHandler; 2972 return this; 2973 } 2974 2975 /** 2976 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle 2977 * before it is closed and removed from the pool. 2978 * 2979 * <p><b>DO NOT USE</b> this method. 2980 * This feature has negative side effects that are very hard to foresee. 2981 * <p>A connection timeout allows the system to internally close a connection to 2982 * a SQLite database after a given timeout, which is good for reducing app's memory 2983 * consumption. 2984 * <b>However</b> the side effect is it <b>will reset all of SQLite's per-connection 2985 * states</b>, which are typically modified with a {@code PRAGMA} statement, and 2986 * these states <b>will not be restored</b> when a connection is re-established 2987 * internally, and the system does not provide a callback for an app to reconfigure a 2988 * connection. 2989 * This feature may only be used if an app relies on none of such per-connection states. 2990 * 2991 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE} 2992 * to allow unlimited idle connections. 2993 * 2994 * @see SQLiteOpenHelper#setIdleConnectionTimeout(long) 2995 * 2996 * @deprecated DO NOT USE this method. See the javadoc for the details. 2997 */ 2998 @NonNull 2999 @Deprecated setIdleConnectionTimeout( @ntRangefrom = 0) long idleConnectionTimeoutMs)3000 public Builder setIdleConnectionTimeout( 3001 @IntRange(from = 0) long idleConnectionTimeoutMs) { 3002 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0, 3003 "idle connection timeout cannot be negative"); 3004 mIdleConnectionTimeout = idleConnectionTimeoutMs; 3005 return this; 3006 } 3007 3008 /** 3009 * Sets <a href="https://sqlite.org/pragma.html#pragma_journal_mode">journal mode</a> 3010 * to use. 3011 * 3012 * <p>Note: If journal mode is not set, the platform will use a manufactured-specified 3013 * default which can vary across devices. 3014 */ 3015 @NonNull setJournalMode(@ournalMode @onNull String journalMode)3016 public Builder setJournalMode(@JournalMode @NonNull String journalMode) { 3017 Objects.requireNonNull(journalMode); 3018 mJournalMode = journalMode; 3019 return this; 3020 } 3021 3022 /** 3023 * Sets <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a> 3024 * 3025 * <p>Note: If sync mode is not set, the platform will use a manufactured-specified 3026 * default which can vary across devices. 3027 */ 3028 @NonNull setSynchronousMode(@yncMode @onNull String syncMode)3029 public Builder setSynchronousMode(@SyncMode @NonNull String syncMode) { 3030 Objects.requireNonNull(syncMode); 3031 mSyncMode = syncMode; 3032 return this; 3033 } 3034 3035 /** 3036 * Creates an instance of {@link OpenParams} with the options that were previously set 3037 * on this builder 3038 */ 3039 @NonNull build()3040 public OpenParams build() { 3041 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize, 3042 mLookasideSlotCount, mIdleConnectionTimeout, mJournalMode, mSyncMode); 3043 } 3044 } 3045 } 3046 3047 /** @hide */ 3048 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = { 3049 OPEN_READWRITE, 3050 OPEN_READONLY, 3051 CREATE_IF_NECESSARY, 3052 NO_LOCALIZED_COLLATORS, 3053 ENABLE_WRITE_AHEAD_LOGGING 3054 }) 3055 @Retention(RetentionPolicy.SOURCE) 3056 public @interface DatabaseOpenFlags {} 3057 3058 /** @hide */ wipeDetected(String filename, String reason)3059 public static void wipeDetected(String filename, String reason) { 3060 wtfAsSystemServer(TAG, "DB wipe detected:" 3061 + " package=" + ActivityThread.currentPackageName() 3062 + " reason=" + reason 3063 + " file=" + filename 3064 + " " + getFileTimestamps(filename) 3065 + " checkfile " + getFileTimestamps(filename + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX), 3066 new Throwable("STACKTRACE")); 3067 } 3068 3069 /** @hide */ getFileTimestamps(String path)3070 public static String getFileTimestamps(String path) { 3071 try { 3072 BasicFileAttributes attr = Files.readAttributes( 3073 FileSystems.getDefault().getPath(path), BasicFileAttributes.class); 3074 return "ctime=" + attr.creationTime() 3075 + " mtime=" + attr.lastModifiedTime() 3076 + " atime=" + attr.lastAccessTime(); 3077 } catch (IOException e) { 3078 return "[unable to obtain timestamp]"; 3079 } 3080 } 3081 3082 /** @hide */ wtfAsSystemServer(String tag, String message, Throwable stacktrace)3083 static void wtfAsSystemServer(String tag, String message, Throwable stacktrace) { 3084 Log.e(tag, message, stacktrace); 3085 ContentResolver.onDbCorruption(tag, message, stacktrace); 3086 } 3087 } 3088 3089