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