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