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