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