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