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