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