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