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