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