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