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