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