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