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