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