1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.database.sqlite; 18 19 import android.annotation.IntDef; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.app.ActivityManager; 24 import android.content.ContentValues; 25 import android.database.Cursor; 26 import android.database.DatabaseErrorHandler; 27 import android.database.DatabaseUtils; 28 import android.database.DefaultDatabaseErrorHandler; 29 import android.database.SQLException; 30 import android.database.sqlite.SQLiteDebug.DbStats; 31 import android.os.CancellationSignal; 32 import android.os.Looper; 33 import android.os.OperationCanceledException; 34 import android.os.SystemProperties; 35 import android.text.TextUtils; 36 import android.util.EventLog; 37 import android.util.Log; 38 import android.util.Pair; 39 import android.util.Printer; 40 41 import com.android.internal.util.Preconditions; 42 43 import dalvik.system.CloseGuard; 44 45 import java.io.File; 46 import java.io.FileFilter; 47 import java.lang.annotation.Retention; 48 import java.lang.annotation.RetentionPolicy; 49 import java.util.ArrayList; 50 import java.util.HashMap; 51 import java.util.List; 52 import java.util.Locale; 53 import java.util.Map; 54 import 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 */ 77 public 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 SQLiteDatabase(final String path, final int openFlags, CursorFactory cursorFactory, DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs)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 finalize()291 protected void finalize() throws Throwable { 292 try { 293 dispose(true); 294 } finally { 295 super.finalize(); 296 } 297 } 298 299 @Override onAllReferencesReleased()300 protected void onAllReferencesReleased() { 301 dispose(false); 302 } 303 dispose(boolean finalized)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 */ releaseMemory()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 setLockingEnabled(boolean lockingEnabled)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 */ getLabel()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 */ onCorruption()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 */ getThreadSession()387 SQLiteSession getThreadSession() { 388 return mThreadSession.get(); // initialValue() throws if database closed 389 } 390 createSession()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 */ getThreadDefaultConnectionFlags(boolean readOnly)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 isMainThread()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 */ beginTransaction()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 */ beginTransactionNonExclusive()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 */ beginTransactionWithListener(SQLiteTransactionListener transactionListener)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 */ beginTransactionWithListenerNonExclusive( SQLiteTransactionListener transactionListener)525 public void beginTransactionWithListenerNonExclusive( 526 SQLiteTransactionListener transactionListener) { 527 beginTransaction(transactionListener, false); 528 } 529 beginTransaction(SQLiteTransactionListener transactionListener, boolean exclusive)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 */ endTransaction()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 */ setTransactionSuccessful()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 */ inTransaction()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 */ isDbLockedByCurrentThread()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 isDbLockedByOtherThreads()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 yieldIfContended()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 */ yieldIfContendedSafely()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 */ yieldIfContendedSafely(long sleepAfterYieldDelay)661 public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) { 662 return yieldIfContendedHelper(true /* check yielding */, sleepAfterYieldDelay); 663 } 664 yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay)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 getSyncedTables()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 */ openDatabase(@onNull String path, @Nullable CursorFactory factory, @DatabaseOpenFlags int flags)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 */ openDatabase(@onNull File path, @NonNull OpenParams openParams)712 public static SQLiteDatabase openDatabase(@NonNull File path, 713 @NonNull OpenParams openParams) { 714 return openDatabase(path.getPath(), openParams); 715 } 716 openDatabase(@onNull String path, @NonNull OpenParams openParams)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 */ openDatabase(@onNull String path, @Nullable CursorFactory factory, @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler)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 */ openOrCreateDatabase(@onNull File file, @Nullable CursorFactory factory)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 */ openOrCreateDatabase(@onNull String path, @Nullable CursorFactory factory)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 */ openOrCreateDatabase(@onNull String path, @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler)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 */ deleteDatabase(@onNull File file)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 */ reopenReadWrite()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 open()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 openInner()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 create(@ullable CursorFactory factory)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 createInMemory(@onNull OpenParams openParams)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 */ addCustomFunction(String name, int numArgs, CustomFunction function)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 */ getVersion()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 */ setVersion(int version)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 */ getMaximumSize()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 */ setMaximumSize(long numBytes)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 */ getPageSize()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 */ setPageSize(long numBytes)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 markTableSyncable(String table, String deletedTable)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 markTableSyncable(String table, String foreignKey, String updateTable)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 */ findEditTable(String tables)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 */ compileStatement(String sql)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 */ query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)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 */ query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)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 */ queryWithFactory(CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)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 */ queryWithFactory(CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)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 */ query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)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 */ query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)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 */ rawQuery(String sql, String[] selectionArgs)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 */ rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal)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 */ rawQueryWithFactory( CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable)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 */ rawQueryWithFactory( CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable, CancellationSignal cancellationSignal)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 */ insert(String table, String nullColumnHack, ContentValues values)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 */ insertOrThrow(String table, String nullColumnHack, ContentValues values)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 */ replace(String table, String nullColumnHack, ContentValues initialValues)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 */ replaceOrThrow(String table, String nullColumnHack, ContentValues initialValues)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 */ insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm)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 */ delete(String table, String whereClause, String[] whereArgs)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 */ update(String table, ContentValues values, String whereClause, String[] whereArgs)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 */ updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm)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 */ execSQL(String sql)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 */ execSQL(String sql, Object[] bindArgs)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 /** {@hide} */ executeSql(String sql, Object[] bindArgs)1736 public int executeSql(String sql, Object[] bindArgs) throws SQLException { 1737 acquireReference(); 1738 try { 1739 if (DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_ATTACH) { 1740 boolean disableWal = false; 1741 synchronized (mLock) { 1742 if (!mHasAttachedDbsLocked) { 1743 mHasAttachedDbsLocked = true; 1744 disableWal = true; 1745 mConnectionPoolLocked.disableIdleConnectionHandler(); 1746 } 1747 } 1748 if (disableWal) { 1749 disableWriteAheadLogging(); 1750 } 1751 } 1752 1753 SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs); 1754 try { 1755 return statement.executeUpdateDelete(); 1756 } finally { 1757 statement.close(); 1758 } 1759 } finally { 1760 releaseReference(); 1761 } 1762 } 1763 1764 /** 1765 * Verifies that a SQL SELECT statement is valid by compiling it. 1766 * If the SQL statement is not valid, this method will throw a {@link SQLiteException}. 1767 * 1768 * @param sql SQL to be validated 1769 * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 1770 * If the operation is canceled, then {@link OperationCanceledException} will be thrown 1771 * when the query is executed. 1772 * @throws SQLiteException if {@code sql} is invalid 1773 */ validateSql(@onNull String sql, @Nullable CancellationSignal cancellationSignal)1774 public void validateSql(@NonNull String sql, @Nullable CancellationSignal cancellationSignal) { 1775 getThreadSession().prepare(sql, 1776 getThreadDefaultConnectionFlags(/* readOnly =*/ true), cancellationSignal, null); 1777 } 1778 1779 /** 1780 * Returns true if the database is opened as read only. 1781 * 1782 * @return True if database is opened as read only. 1783 */ isReadOnly()1784 public boolean isReadOnly() { 1785 synchronized (mLock) { 1786 return isReadOnlyLocked(); 1787 } 1788 } 1789 isReadOnlyLocked()1790 private boolean isReadOnlyLocked() { 1791 return (mConfigurationLocked.openFlags & OPEN_READ_MASK) == OPEN_READONLY; 1792 } 1793 1794 /** 1795 * Returns true if the database is in-memory db. 1796 * 1797 * @return True if the database is in-memory. 1798 * @hide 1799 */ isInMemoryDatabase()1800 public boolean isInMemoryDatabase() { 1801 synchronized (mLock) { 1802 return mConfigurationLocked.isInMemoryDb(); 1803 } 1804 } 1805 1806 /** 1807 * Returns true if the database is currently open. 1808 * 1809 * @return True if the database is currently open (has not been closed). 1810 */ isOpen()1811 public boolean isOpen() { 1812 synchronized (mLock) { 1813 return mConnectionPoolLocked != null; 1814 } 1815 } 1816 1817 /** 1818 * Returns true if the new version code is greater than the current database version. 1819 * 1820 * @param newVersion The new version code. 1821 * @return True if the new version code is greater than the current database version. 1822 */ needUpgrade(int newVersion)1823 public boolean needUpgrade(int newVersion) { 1824 return newVersion > getVersion(); 1825 } 1826 1827 /** 1828 * Gets the path to the database file. 1829 * 1830 * @return The path to the database file. 1831 */ getPath()1832 public final String getPath() { 1833 synchronized (mLock) { 1834 return mConfigurationLocked.path; 1835 } 1836 } 1837 1838 /** 1839 * Sets the locale for this database. Does nothing if this database has 1840 * the {@link #NO_LOCALIZED_COLLATORS} flag set or was opened read only. 1841 * 1842 * @param locale The new locale. 1843 * 1844 * @throws SQLException if the locale could not be set. The most common reason 1845 * for this is that there is no collator available for the locale you requested. 1846 * In this case the database remains unchanged. 1847 */ setLocale(Locale locale)1848 public void setLocale(Locale locale) { 1849 if (locale == null) { 1850 throw new IllegalArgumentException("locale must not be null."); 1851 } 1852 1853 synchronized (mLock) { 1854 throwIfNotOpenLocked(); 1855 1856 final Locale oldLocale = mConfigurationLocked.locale; 1857 mConfigurationLocked.locale = locale; 1858 try { 1859 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 1860 } catch (RuntimeException ex) { 1861 mConfigurationLocked.locale = oldLocale; 1862 throw ex; 1863 } 1864 } 1865 } 1866 1867 /** 1868 * Sets the maximum size of the prepared-statement cache for this database. 1869 * (size of the cache = number of compiled-sql-statements stored in the cache). 1870 *<p> 1871 * Maximum cache size can ONLY be increased from its current size (default = 10). 1872 * If this method is called with smaller size than the current maximum value, 1873 * then IllegalStateException is thrown. 1874 *<p> 1875 * This method is thread-safe. 1876 * 1877 * @param cacheSize the size of the cache. can be (0 to {@link #MAX_SQL_CACHE_SIZE}) 1878 * @throws IllegalStateException if input cacheSize > {@link #MAX_SQL_CACHE_SIZE}. 1879 */ setMaxSqlCacheSize(int cacheSize)1880 public void setMaxSqlCacheSize(int cacheSize) { 1881 if (cacheSize > MAX_SQL_CACHE_SIZE || cacheSize < 0) { 1882 throw new IllegalStateException( 1883 "expected value between 0 and " + MAX_SQL_CACHE_SIZE); 1884 } 1885 1886 synchronized (mLock) { 1887 throwIfNotOpenLocked(); 1888 1889 final int oldMaxSqlCacheSize = mConfigurationLocked.maxSqlCacheSize; 1890 mConfigurationLocked.maxSqlCacheSize = cacheSize; 1891 try { 1892 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 1893 } catch (RuntimeException ex) { 1894 mConfigurationLocked.maxSqlCacheSize = oldMaxSqlCacheSize; 1895 throw ex; 1896 } 1897 } 1898 } 1899 1900 /** 1901 * Sets whether foreign key constraints are enabled for the database. 1902 * <p> 1903 * By default, foreign key constraints are not enforced by the database. 1904 * This method allows an application to enable foreign key constraints. 1905 * It must be called each time the database is opened to ensure that foreign 1906 * key constraints are enabled for the session. 1907 * </p><p> 1908 * A good time to call this method is right after calling {@link #openOrCreateDatabase} 1909 * or in the {@link SQLiteOpenHelper#onConfigure} callback. 1910 * </p><p> 1911 * When foreign key constraints are disabled, the database does not check whether 1912 * changes to the database will violate foreign key constraints. Likewise, when 1913 * foreign key constraints are disabled, the database will not execute cascade 1914 * delete or update triggers. As a result, it is possible for the database 1915 * state to become inconsistent. To perform a database integrity check, 1916 * call {@link #isDatabaseIntegrityOk}. 1917 * </p><p> 1918 * This method must not be called while a transaction is in progress. 1919 * </p><p> 1920 * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a> 1921 * for more details about foreign key constraint support. 1922 * </p> 1923 * 1924 * @param enable True to enable foreign key constraints, false to disable them. 1925 * 1926 * @throws IllegalStateException if the are transactions is in progress 1927 * when this method is called. 1928 */ setForeignKeyConstraintsEnabled(boolean enable)1929 public void setForeignKeyConstraintsEnabled(boolean enable) { 1930 synchronized (mLock) { 1931 throwIfNotOpenLocked(); 1932 1933 if (mConfigurationLocked.foreignKeyConstraintsEnabled == enable) { 1934 return; 1935 } 1936 1937 mConfigurationLocked.foreignKeyConstraintsEnabled = enable; 1938 try { 1939 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 1940 } catch (RuntimeException ex) { 1941 mConfigurationLocked.foreignKeyConstraintsEnabled = !enable; 1942 throw ex; 1943 } 1944 } 1945 } 1946 1947 /** 1948 * This method enables parallel execution of queries from multiple threads on the 1949 * same database. It does this by opening multiple connections to the database 1950 * and using a different database connection for each query. The database 1951 * journal mode is also changed to enable writes to proceed concurrently with reads. 1952 * <p> 1953 * When write-ahead logging is not enabled (the default), it is not possible for 1954 * reads and writes to occur on the database at the same time. Before modifying the 1955 * database, the writer implicitly acquires an exclusive lock on the database which 1956 * prevents readers from accessing the database until the write is completed. 1957 * </p><p> 1958 * In contrast, when write-ahead logging is enabled (by calling this method), write 1959 * operations occur in a separate log file which allows reads to proceed concurrently. 1960 * While a write is in progress, readers on other threads will perceive the state 1961 * of the database as it was before the write began. When the write completes, readers 1962 * on other threads will then perceive the new state of the database. 1963 * </p><p> 1964 * It is a good idea to enable write-ahead logging whenever a database will be 1965 * concurrently accessed and modified by multiple threads at the same time. 1966 * However, write-ahead logging uses significantly more memory than ordinary 1967 * journaling because there are multiple connections to the same database. 1968 * So if a database will only be used by a single thread, or if optimizing 1969 * concurrency is not very important, then write-ahead logging should be disabled. 1970 * </p><p> 1971 * After calling this method, execution of queries in parallel is enabled as long as 1972 * the database remains open. To disable execution of queries in parallel, either 1973 * call {@link #disableWriteAheadLogging} or close the database and reopen it. 1974 * </p><p> 1975 * The maximum number of connections used to execute queries in parallel is 1976 * dependent upon the device memory and possibly other properties. 1977 * </p><p> 1978 * If a query is part of a transaction, then it is executed on the same database handle the 1979 * transaction was begun. 1980 * </p><p> 1981 * Writers should use {@link #beginTransactionNonExclusive()} or 1982 * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)} 1983 * to start a transaction. Non-exclusive mode allows database file to be in readable 1984 * by other threads executing queries. 1985 * </p><p> 1986 * If the database has any attached databases, then execution of queries in parallel is NOT 1987 * possible. Likewise, write-ahead logging is not supported for read-only databases 1988 * or memory databases. In such cases, {@link #enableWriteAheadLogging} returns false. 1989 * </p><p> 1990 * The best way to enable write-ahead logging is to pass the 1991 * {@link #ENABLE_WRITE_AHEAD_LOGGING} flag to {@link #openDatabase}. This is 1992 * more efficient than calling {@link #enableWriteAheadLogging}. 1993 * <code><pre> 1994 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory, 1995 * SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING, 1996 * myDatabaseErrorHandler); 1997 * db.enableWriteAheadLogging(); 1998 * </pre></code> 1999 * </p><p> 2000 * Another way to enable write-ahead logging is to call {@link #enableWriteAheadLogging} 2001 * after opening the database. 2002 * <code><pre> 2003 * SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory, 2004 * SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler); 2005 * db.enableWriteAheadLogging(); 2006 * </pre></code> 2007 * </p><p> 2008 * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for 2009 * more details about how write-ahead logging works. 2010 * </p> 2011 * 2012 * @return True if write-ahead logging is enabled. 2013 * 2014 * @throws IllegalStateException if there are transactions in progress at the 2015 * time this method is called. WAL mode can only be changed when there are no 2016 * transactions in progress. 2017 * 2018 * @see #ENABLE_WRITE_AHEAD_LOGGING 2019 * @see #disableWriteAheadLogging 2020 */ enableWriteAheadLogging()2021 public boolean enableWriteAheadLogging() { 2022 synchronized (mLock) { 2023 throwIfNotOpenLocked(); 2024 2025 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0) { 2026 return true; 2027 } 2028 2029 if (isReadOnlyLocked()) { 2030 // WAL doesn't make sense for readonly-databases. 2031 // TODO: True, but connection pooling does still make sense... 2032 return false; 2033 } 2034 2035 if (mConfigurationLocked.isInMemoryDb()) { 2036 Log.i(TAG, "can't enable WAL for memory databases."); 2037 return false; 2038 } 2039 2040 // make sure this database has NO attached databases because sqlite's write-ahead-logging 2041 // doesn't work for databases with attached databases 2042 if (mHasAttachedDbsLocked) { 2043 if (Log.isLoggable(TAG, Log.DEBUG)) { 2044 Log.d(TAG, "this database: " + mConfigurationLocked.label 2045 + " has attached databases. can't enable WAL."); 2046 } 2047 return false; 2048 } 2049 2050 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING; 2051 try { 2052 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 2053 } catch (RuntimeException ex) { 2054 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING; 2055 throw ex; 2056 } 2057 } 2058 return true; 2059 } 2060 2061 /** 2062 * This method disables the features enabled by {@link #enableWriteAheadLogging()}. 2063 * 2064 * @throws IllegalStateException if there are transactions in progress at the 2065 * time this method is called. WAL mode can only be changed when there are no 2066 * transactions in progress. 2067 * 2068 * @see #enableWriteAheadLogging 2069 */ disableWriteAheadLogging()2070 public void disableWriteAheadLogging() { 2071 synchronized (mLock) { 2072 throwIfNotOpenLocked(); 2073 2074 if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) { 2075 return; 2076 } 2077 2078 mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING; 2079 try { 2080 mConnectionPoolLocked.reconfigure(mConfigurationLocked); 2081 } catch (RuntimeException ex) { 2082 mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING; 2083 throw ex; 2084 } 2085 } 2086 } 2087 2088 /** 2089 * Returns true if write-ahead logging has been enabled for this database. 2090 * 2091 * @return True if write-ahead logging has been enabled for this database. 2092 * 2093 * @see #enableWriteAheadLogging 2094 * @see #ENABLE_WRITE_AHEAD_LOGGING 2095 */ isWriteAheadLoggingEnabled()2096 public boolean isWriteAheadLoggingEnabled() { 2097 synchronized (mLock) { 2098 throwIfNotOpenLocked(); 2099 2100 return (mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0; 2101 } 2102 } 2103 2104 /** 2105 * Collect statistics about all open databases in the current process. 2106 * Used by bug report. 2107 */ getDbStats()2108 static ArrayList<DbStats> getDbStats() { 2109 ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>(); 2110 for (SQLiteDatabase db : getActiveDatabases()) { 2111 db.collectDbStats(dbStatsList); 2112 } 2113 return dbStatsList; 2114 } 2115 collectDbStats(ArrayList<DbStats> dbStatsList)2116 private void collectDbStats(ArrayList<DbStats> dbStatsList) { 2117 synchronized (mLock) { 2118 if (mConnectionPoolLocked != null) { 2119 mConnectionPoolLocked.collectDbStats(dbStatsList); 2120 } 2121 } 2122 } 2123 getActiveDatabases()2124 private static ArrayList<SQLiteDatabase> getActiveDatabases() { 2125 ArrayList<SQLiteDatabase> databases = new ArrayList<SQLiteDatabase>(); 2126 synchronized (sActiveDatabases) { 2127 databases.addAll(sActiveDatabases.keySet()); 2128 } 2129 return databases; 2130 } 2131 2132 /** 2133 * Dump detailed information about all open databases in the current process. 2134 * Used by bug report. 2135 */ dumpAll(Printer printer, boolean verbose)2136 static void dumpAll(Printer printer, boolean verbose) { 2137 for (SQLiteDatabase db : getActiveDatabases()) { 2138 db.dump(printer, verbose); 2139 } 2140 } 2141 dump(Printer printer, boolean verbose)2142 private void dump(Printer printer, boolean verbose) { 2143 synchronized (mLock) { 2144 if (mConnectionPoolLocked != null) { 2145 printer.println(""); 2146 mConnectionPoolLocked.dump(printer, verbose); 2147 } 2148 } 2149 } 2150 2151 /** 2152 * Returns list of full pathnames of all attached databases including the main database 2153 * by executing 'pragma database_list' on the database. 2154 * 2155 * @return ArrayList of pairs of (database name, database file path) or null if the database 2156 * is not open. 2157 */ getAttachedDbs()2158 public List<Pair<String, String>> getAttachedDbs() { 2159 ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>(); 2160 synchronized (mLock) { 2161 if (mConnectionPoolLocked == null) { 2162 return null; // not open 2163 } 2164 2165 if (!mHasAttachedDbsLocked) { 2166 // No attached databases. 2167 // There is a small window where attached databases exist but this flag is not 2168 // set yet. This can occur when this thread is in a race condition with another 2169 // thread that is executing the SQL statement: "attach database <blah> as <foo>" 2170 // If this thread is NOT ok with such a race condition (and thus possibly not 2171 // receivethe entire list of attached databases), then the caller should ensure 2172 // that no thread is executing any SQL statements while a thread is calling this 2173 // method. Typically, this method is called when 'adb bugreport' is done or the 2174 // caller wants to collect stats on the database and all its attached databases. 2175 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path)); 2176 return attachedDbs; 2177 } 2178 2179 acquireReference(); 2180 } 2181 2182 try { 2183 // has attached databases. query sqlite to get the list of attached databases. 2184 Cursor c = null; 2185 try { 2186 c = rawQuery("pragma database_list;", null); 2187 while (c.moveToNext()) { 2188 // sqlite returns a row for each database in the returned list of databases. 2189 // in each row, 2190 // 1st column is the database name such as main, or the database 2191 // name specified on the "ATTACH" command 2192 // 2nd column is the database file path. 2193 attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2))); 2194 } 2195 } finally { 2196 if (c != null) { 2197 c.close(); 2198 } 2199 } 2200 return attachedDbs; 2201 } finally { 2202 releaseReference(); 2203 } 2204 } 2205 2206 /** 2207 * Runs 'pragma integrity_check' on the given database (and all the attached databases) 2208 * and returns true if the given database (and all its attached databases) pass integrity_check, 2209 * false otherwise. 2210 *<p> 2211 * If the result is false, then this method logs the errors reported by the integrity_check 2212 * command execution. 2213 *<p> 2214 * Note that 'pragma integrity_check' on a database can take a long time. 2215 * 2216 * @return true if the given database (and all its attached databases) pass integrity_check, 2217 * false otherwise. 2218 */ isDatabaseIntegrityOk()2219 public boolean isDatabaseIntegrityOk() { 2220 acquireReference(); 2221 try { 2222 List<Pair<String, String>> attachedDbs = null; 2223 try { 2224 attachedDbs = getAttachedDbs(); 2225 if (attachedDbs == null) { 2226 throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " + 2227 "be retrieved. probably because the database is closed"); 2228 } 2229 } catch (SQLiteException e) { 2230 // can't get attachedDb list. do integrity check on the main database 2231 attachedDbs = new ArrayList<Pair<String, String>>(); 2232 attachedDbs.add(new Pair<String, String>("main", getPath())); 2233 } 2234 2235 for (int i = 0; i < attachedDbs.size(); i++) { 2236 Pair<String, String> p = attachedDbs.get(i); 2237 SQLiteStatement prog = null; 2238 try { 2239 prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);"); 2240 String rslt = prog.simpleQueryForString(); 2241 if (!rslt.equalsIgnoreCase("ok")) { 2242 // integrity_checker failed on main or attached databases 2243 Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt); 2244 return false; 2245 } 2246 } finally { 2247 if (prog != null) prog.close(); 2248 } 2249 } 2250 } finally { 2251 releaseReference(); 2252 } 2253 return true; 2254 } 2255 2256 @Override toString()2257 public String toString() { 2258 return "SQLiteDatabase: " + getPath(); 2259 } 2260 throwIfNotOpenLocked()2261 private void throwIfNotOpenLocked() { 2262 if (mConnectionPoolLocked == null) { 2263 throw new IllegalStateException("The database '" + mConfigurationLocked.label 2264 + "' is not open."); 2265 } 2266 } 2267 2268 /** 2269 * Used to allow returning sub-classes of {@link Cursor} when calling query. 2270 */ 2271 public interface CursorFactory { 2272 /** 2273 * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}. 2274 */ newCursor(SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable, SQLiteQuery query)2275 public Cursor newCursor(SQLiteDatabase db, 2276 SQLiteCursorDriver masterQuery, String editTable, 2277 SQLiteQuery query); 2278 } 2279 2280 /** 2281 * A callback interface for a custom sqlite3 function. 2282 * This can be used to create a function that can be called from 2283 * sqlite3 database triggers. 2284 * @hide 2285 */ 2286 public interface CustomFunction { callback(String[] args)2287 public void callback(String[] args); 2288 } 2289 2290 /** 2291 * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase} 2292 */ 2293 public static final class OpenParams { 2294 private final int mOpenFlags; 2295 private final CursorFactory mCursorFactory; 2296 private final DatabaseErrorHandler mErrorHandler; 2297 private final int mLookasideSlotSize; 2298 private final int mLookasideSlotCount; 2299 private long mIdleConnectionTimeout; 2300 OpenParams(int openFlags, CursorFactory cursorFactory, DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeout)2301 private OpenParams(int openFlags, CursorFactory cursorFactory, 2302 DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount, 2303 long idleConnectionTimeout) { 2304 mOpenFlags = openFlags; 2305 mCursorFactory = cursorFactory; 2306 mErrorHandler = errorHandler; 2307 mLookasideSlotSize = lookasideSlotSize; 2308 mLookasideSlotCount = lookasideSlotCount; 2309 mIdleConnectionTimeout = idleConnectionTimeout; 2310 } 2311 2312 /** 2313 * Returns size in bytes of each lookaside slot or -1 if not set. 2314 * 2315 * @see Builder#setLookasideConfig(int, int) 2316 */ 2317 @IntRange(from = -1) getLookasideSlotSize()2318 public int getLookasideSlotSize() { 2319 return mLookasideSlotSize; 2320 } 2321 2322 /** 2323 * Returns total number of lookaside memory slots per database connection or -1 if not 2324 * set. 2325 * 2326 * @see Builder#setLookasideConfig(int, int) 2327 */ 2328 @IntRange(from = -1) getLookasideSlotCount()2329 public int getLookasideSlotCount() { 2330 return mLookasideSlotCount; 2331 } 2332 2333 /** 2334 * Returns flags to control database access mode. Default value is 0. 2335 * 2336 * @see Builder#setOpenFlags(int) 2337 */ 2338 @DatabaseOpenFlags getOpenFlags()2339 public int getOpenFlags() { 2340 return mOpenFlags; 2341 } 2342 2343 /** 2344 * Returns an optional factory class that is called to instantiate a cursor when query 2345 * is called 2346 * 2347 * @see Builder#setCursorFactory(CursorFactory) 2348 */ 2349 @Nullable getCursorFactory()2350 public CursorFactory getCursorFactory() { 2351 return mCursorFactory; 2352 } 2353 2354 /** 2355 * Returns handler for database corruption errors 2356 * 2357 * @see Builder#setErrorHandler(DatabaseErrorHandler) 2358 */ 2359 @Nullable getErrorHandler()2360 public DatabaseErrorHandler getErrorHandler() { 2361 return mErrorHandler; 2362 } 2363 2364 /** 2365 * Returns maximum number of milliseconds that SQLite connection is allowed to be idle 2366 * before it is closed and removed from the pool. 2367 * <p>If the value isn't set, the timeout defaults to the system wide timeout 2368 * 2369 * @return timeout in milliseconds or -1 if the value wasn't set. 2370 */ getIdleConnectionTimeout()2371 public long getIdleConnectionTimeout() { 2372 return mIdleConnectionTimeout; 2373 } 2374 2375 /** 2376 * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with 2377 * {@code this} parameters. 2378 * @hide 2379 */ 2380 @NonNull toBuilder()2381 public Builder toBuilder() { 2382 return new Builder(this); 2383 } 2384 2385 /** 2386 * Builder for {@link OpenParams}. 2387 */ 2388 public static final class Builder { 2389 private int mLookasideSlotSize = -1; 2390 private int mLookasideSlotCount = -1; 2391 private long mIdleConnectionTimeout = -1; 2392 private int mOpenFlags; 2393 private CursorFactory mCursorFactory; 2394 private DatabaseErrorHandler mErrorHandler; 2395 Builder()2396 public Builder() { 2397 } 2398 Builder(OpenParams params)2399 public Builder(OpenParams params) { 2400 mLookasideSlotSize = params.mLookasideSlotSize; 2401 mLookasideSlotCount = params.mLookasideSlotCount; 2402 mOpenFlags = params.mOpenFlags; 2403 mCursorFactory = params.mCursorFactory; 2404 mErrorHandler = params.mErrorHandler; 2405 } 2406 2407 /** 2408 * Configures 2409 * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a> 2410 * 2411 * <p>SQLite default settings will be used, if this method isn't called. 2412 * Use {@code setLookasideConfig(0,0)} to disable lookaside 2413 * 2414 * <p><strong>Note:</strong> Provided slotSize/slotCount configuration is just a 2415 * recommendation. The system may choose different values depending on a device, e.g. 2416 * lookaside allocations can be disabled on low-RAM devices 2417 * 2418 * @param slotSize The size in bytes of each lookaside slot. 2419 * @param slotCount The total number of lookaside memory slots per database connection. 2420 */ setLookasideConfig(@ntRangefrom = 0) final int slotSize, @IntRange(from = 0) final int slotCount)2421 public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize, 2422 @IntRange(from = 0) final int slotCount) { 2423 Preconditions.checkArgument(slotSize >= 0, 2424 "lookasideSlotCount cannot be negative"); 2425 Preconditions.checkArgument(slotCount >= 0, 2426 "lookasideSlotSize cannot be negative"); 2427 Preconditions.checkArgument( 2428 (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0), 2429 "Invalid configuration: " + slotSize + ", " + slotCount); 2430 2431 mLookasideSlotSize = slotSize; 2432 mLookasideSlotCount = slotCount; 2433 return this; 2434 } 2435 2436 /** 2437 * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set 2438 * @hide 2439 */ isWriteAheadLoggingEnabled()2440 public boolean isWriteAheadLoggingEnabled() { 2441 return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0; 2442 } 2443 2444 /** 2445 * Sets flags to control database access mode 2446 * @param openFlags The new flags to set 2447 * @see #OPEN_READWRITE 2448 * @see #OPEN_READONLY 2449 * @see #CREATE_IF_NECESSARY 2450 * @see #NO_LOCALIZED_COLLATORS 2451 * @see #ENABLE_WRITE_AHEAD_LOGGING 2452 * @return same builder instance for chaining multiple calls into a single statement 2453 */ 2454 @NonNull setOpenFlags(@atabaseOpenFlags int openFlags)2455 public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) { 2456 mOpenFlags = openFlags; 2457 return this; 2458 } 2459 2460 /** 2461 * Adds flags to control database access mode 2462 * 2463 * @param openFlags The new flags to add 2464 * @return same builder instance for chaining multiple calls into a single statement 2465 */ 2466 @NonNull addOpenFlags(@atabaseOpenFlags int openFlags)2467 public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) { 2468 mOpenFlags |= openFlags; 2469 return this; 2470 } 2471 2472 /** 2473 * Removes database access mode flags 2474 * 2475 * @param openFlags Flags to remove 2476 * @return same builder instance for chaining multiple calls into a single statement 2477 */ 2478 @NonNull removeOpenFlags(@atabaseOpenFlags int openFlags)2479 public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) { 2480 mOpenFlags &= ~openFlags; 2481 return this; 2482 } 2483 2484 /** 2485 * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true}, 2486 * unsets otherwise 2487 * @hide 2488 */ setWriteAheadLoggingEnabled(boolean enabled)2489 public void setWriteAheadLoggingEnabled(boolean enabled) { 2490 if (enabled) { 2491 addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING); 2492 } else { 2493 removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING); 2494 } 2495 } 2496 2497 /** 2498 * Set an optional factory class that is called to instantiate a cursor when query 2499 * is called. 2500 * 2501 * @param cursorFactory instance 2502 * @return same builder instance for chaining multiple calls into a single statement 2503 */ 2504 @NonNull setCursorFactory(@ullable CursorFactory cursorFactory)2505 public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) { 2506 mCursorFactory = cursorFactory; 2507 return this; 2508 } 2509 2510 2511 /** 2512 * Sets {@link DatabaseErrorHandler} object to handle db corruption errors 2513 */ 2514 @NonNull setErrorHandler(@ullable DatabaseErrorHandler errorHandler)2515 public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) { 2516 mErrorHandler = errorHandler; 2517 return this; 2518 } 2519 2520 /** 2521 * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle 2522 * before it is closed and removed from the pool. 2523 * 2524 * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE} 2525 * to allow unlimited idle connections. 2526 */ 2527 @NonNull setIdleConnectionTimeout( @ntRangefrom = 0) long idleConnectionTimeoutMs)2528 public Builder setIdleConnectionTimeout( 2529 @IntRange(from = 0) long idleConnectionTimeoutMs) { 2530 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0, 2531 "idle connection timeout cannot be negative"); 2532 mIdleConnectionTimeout = idleConnectionTimeoutMs; 2533 return this; 2534 } 2535 2536 /** 2537 * Creates an instance of {@link OpenParams} with the options that were previously set 2538 * on this builder 2539 */ 2540 @NonNull build()2541 public OpenParams build() { 2542 return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize, 2543 mLookasideSlotCount, mIdleConnectionTimeout); 2544 } 2545 } 2546 } 2547 2548 /** @hide */ 2549 @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = { 2550 OPEN_READWRITE, 2551 OPEN_READONLY, 2552 CREATE_IF_NECESSARY, 2553 NO_LOCALIZED_COLLATORS, 2554 ENABLE_WRITE_AHEAD_LOGGING 2555 }) 2556 @Retention(RetentionPolicy.SOURCE) 2557 public @interface DatabaseOpenFlags {} 2558 } 2559