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