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