public interface

SupportSQLiteDatabase

implements java.io.Closeable

 androidx.sqlite.db.SupportSQLiteDatabase

Gradle dependencies

compile group: 'androidx.sqlite', name: 'sqlite', version: '2.3.0-alpha02'

  • groupId: androidx.sqlite
  • artifactId: sqlite
  • version: 2.3.0-alpha02

Artifact androidx.sqlite:sqlite:2.3.0-alpha02 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.sqlite:sqlite android.arch.persistence:db

Androidx class mapping:

androidx.sqlite.db.SupportSQLiteDatabase android.arch.persistence.db.SupportSQLiteDatabase

Overview

A database abstraction which removes the framework dependency and allows swapping underlying sql versions. It mimics the behavior of android.database.sqlite.SQLiteDatabase

Summary

Methods
public voidbeginTransaction()

Begins a transaction in EXCLUSIVE mode.

public voidbeginTransactionNonExclusive()

Begins a transaction in IMMEDIATE mode.

public voidbeginTransactionWithListener(SQLiteTransactionListener transactionListener)

Begins a transaction in EXCLUSIVE mode.

public voidbeginTransactionWithListenerNonExclusive(SQLiteTransactionListener transactionListener)

Begins a transaction in IMMEDIATE mode.

public SupportSQLiteStatementcompileStatement(java.lang.String sql)

Compiles the given SQL statement.

public intdelete(java.lang.String table, java.lang.String whereClause, java.lang.Object whereArgs[])

Convenience method for deleting rows in the database.

public voiddisableWriteAheadLogging()

This method disables the features enabled by SupportSQLiteDatabase.enableWriteAheadLogging().

public booleanenableWriteAheadLogging()

This method enables parallel execution of queries from multiple threads on the same database.

public voidendTransaction()

End a transaction.

public voidexecPerConnectionSQL(java.lang.String sql, java.lang.Object bindArgs[])

Execute the given SQL statement on all connections to this database.

public voidexecSQL(java.lang.String sql)

Execute a single SQL statement that does not return any data.

public voidexecSQL(java.lang.String sql, java.lang.Object bindArgs[])

Execute a single SQL statement that does not return any data.

public java.util.List<>getAttachedDbs()

Returns list of full path names of all attached databases including the main database by executing 'pragma database_list' on the database.

public longgetMaximumSize()

Returns the maximum size the database may grow to.

public longgetPageSize()

Returns the current database page size, in bytes.

public java.lang.StringgetPath()

Gets the path to the database file.

public intgetVersion()

Gets the database version.

public longinsert(java.lang.String table, int conflictAlgorithm, ContentValues values)

Convenience method for inserting a row into the database.

public booleaninTransaction()

Returns true if the current thread has a transaction pending.

public booleanisDatabaseIntegrityOk()

Runs 'pragma integrity_check' on the given database (and all the attached databases) and returns true if the given database (and all its attached databases) pass integrity_check, false otherwise.

public booleanisDbLockedByCurrentThread()

Returns true if the current thread is holding an active connection to the database.

public booleanisExecPerConnectionSQLSupported()

Returns true if SupportSQLiteDatabase.execPerConnectionSQL(String, Object[]) is supported by the implementation.

public booleanisOpen()

Returns true if the database is currently open.

public booleanisReadOnly()

Returns true if the database is opened as read only.

public booleanisWriteAheadLoggingEnabled()

Returns true if write-ahead logging has been enabled for this database.

public booleanneedUpgrade(int newVersion)

Returns true if the new version code is greater than the current database version.

public Cursorquery(java.lang.String query)

Runs the given query on the database.

public Cursorquery(java.lang.String query, java.lang.Object bindArgs[])

Runs the given query on the database.

public Cursorquery(SupportSQLiteQuery query)

Runs the given query on the database.

public Cursorquery(SupportSQLiteQuery query, CancellationSignal cancellationSignal)

Runs the given query on the database.

public voidsetForeignKeyConstraintsEnabled(boolean enable)

Sets whether foreign key constraints are enabled for the database.

public voidsetLocale(java.util.Locale locale)

Sets the locale for this database.

public longsetMaximumSize(long numBytes)

Sets the maximum size the database will grow to.

public voidsetMaxSqlCacheSize(int cacheSize)

Sets the maximum size of the prepared-statement cache for this database.

public voidsetPageSize(long numBytes)

Sets the database page size.

public voidsetTransactionSuccessful()

Marks the current transaction as successful.

public voidsetVersion(int version)

Sets the database version.

public intupdate(java.lang.String table, int conflictAlgorithm, ContentValues values, java.lang.String whereClause, java.lang.Object whereArgs[])

Convenience method for updating rows in the database.

public booleanyieldIfContendedSafely()

Temporarily end the transaction to let other threads run.

public booleanyieldIfContendedSafely(long sleepAfterYieldDelay)

Temporarily end the transaction to let other threads run.

Methods

public SupportSQLiteStatement compileStatement(java.lang.String sql)

Compiles the given SQL statement.

Parameters:

sql: The sql query.

Returns:

Compiled statement.

public void beginTransaction()

Begins a transaction in EXCLUSIVE mode.

Transactions can be nested. When the outer transaction is ended all of the work done in that transaction and all of the nested transactions will be committed or rolled back. The changes will be rolled back if any transaction is ended without being marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.

Here is the standard idiom for transactions:

   db.beginTransaction();
   try {
     ...
     db.setTransactionSuccessful();
   } finally {
     db.endTransaction();
   }
 

public void beginTransactionNonExclusive()

Begins a transaction in IMMEDIATE mode. Transactions can be nested. When the outer transaction is ended all of the work done in that transaction and all of the nested transactions will be committed or rolled back. The changes will be rolled back if any transaction is ended without being marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.

Here is the standard idiom for transactions:

   db.beginTransactionNonExclusive();
   try {
     ...
     db.setTransactionSuccessful();
   } finally {
     db.endTransaction();
   }
 

public void beginTransactionWithListener(SQLiteTransactionListener transactionListener)

Begins a transaction in EXCLUSIVE mode.

Transactions can be nested. When the outer transaction is ended all of the work done in that transaction and all of the nested transactions will be committed or rolled back. The changes will be rolled back if any transaction is ended without being marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.

Here is the standard idiom for transactions:

   db.beginTransactionWithListener(listener);
   try {
     ...
     db.setTransactionSuccessful();
   } finally {
     db.endTransaction();
   }
 

Parameters:

transactionListener: listener that should be notified when the transaction begins, commits, or is rolled back, either explicitly or by a call to SupportSQLiteDatabase.yieldIfContendedSafely().

public void beginTransactionWithListenerNonExclusive(SQLiteTransactionListener transactionListener)

Begins a transaction in IMMEDIATE mode. Transactions can be nested. When the outer transaction is ended all of the work done in that transaction and all of the nested transactions will be committed or rolled back. The changes will be rolled back if any transaction is ended without being marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.

Here is the standard idiom for transactions:

   db.beginTransactionWithListenerNonExclusive(listener);
   try {
     ...
     db.setTransactionSuccessful();
   } finally {
     db.endTransaction();
   }
 

Parameters:

transactionListener: listener that should be notified when the transaction begins, commits, or is rolled back, either explicitly or by a call to SupportSQLiteDatabase.yieldIfContendedSafely().

public void endTransaction()

End a transaction. See beginTransaction for notes about how to use this and when transactions are committed and rolled back.

public void setTransactionSuccessful()

Marks the current transaction as successful. Do not do any more database work between calling this and calling endTransaction. Do as little non-database work as possible in that situation too. If any errors are encountered between this and endTransaction the transaction will still be committed.

public boolean inTransaction()

Returns true if the current thread has a transaction pending.

Returns:

True if the current thread is in a transaction.

public boolean isDbLockedByCurrentThread()

Returns true if the current thread is holding an active connection to the database.

The name of this method comes from a time when having an active connection to the database meant that the thread was holding an actual lock on the database. Nowadays, there is no longer a true "database lock" although threads may block if they cannot acquire a database connection to perform a particular operation.

Returns:

True if the current thread is holding an active connection to the database.

public boolean yieldIfContendedSafely()

Temporarily end the transaction to let other threads run. The transaction is assumed to be successful so far. Do not call setTransactionSuccessful before calling this. When this returns a new transaction will have been created but not marked as successful. This assumes that there are no nested transactions (beginTransaction has only been called once) and will throw an exception if that is not the case.

Returns:

true if the transaction was yielded

public boolean yieldIfContendedSafely(long sleepAfterYieldDelay)

Temporarily end the transaction to let other threads run. The transaction is assumed to be successful so far. Do not call setTransactionSuccessful before calling this. When this returns a new transaction will have been created but not marked as successful. This assumes that there are no nested transactions (beginTransaction has only been called once) and will throw an exception if that is not the case.

Parameters:

sleepAfterYieldDelay: if > 0, sleep this long before starting a new transaction if the lock was actually yielded. This will allow other background threads to make some more progress than they would if we started the transaction immediately.

Returns:

true if the transaction was yielded

public boolean isExecPerConnectionSQLSupported()

Returns true if SupportSQLiteDatabase.execPerConnectionSQL(String, Object[]) is supported by the implementation.

Returns:

true if SupportSQLiteDatabase.execPerConnectionSQL(String, Object[]) can be invoked safely, false otherwise.

public void execPerConnectionSQL(java.lang.String sql, java.lang.Object bindArgs[])

Execute the given SQL statement on all connections to this database.

This statement will be immediately executed on all existing connections, and will be automatically executed on all future connections.

Some example usages are changes like PRAGMA trusted_schema=OFF or functions like SELECT icu_load_collation(). If you execute these statements using SupportSQLiteDatabase.execSQL(String) then they will only apply to a single database connection; using this method will ensure that they are uniformly applied to all current and future connections.

An implementation of SupportSQLiteDatabase might not support this operation. Use SupportSQLiteDatabase.isExecPerConnectionSQLSupported() to check if this operation is supported before calling this method.

Parameters:

sql: The SQL statement to be executed. Multiple statements separated by semicolons are not supported.
bindArgs: The arguments that should be bound to the SQL statement.

public int getVersion()

Gets the database version.

Returns:

the database version

public void setVersion(int version)

Sets the database version.

Parameters:

version: the new database version

public long getMaximumSize()

Returns the maximum size the database may grow to.

Returns:

the new maximum database size

public long setMaximumSize(long numBytes)

Sets the maximum size the database will grow to. The maximum size cannot be set below the current size.

Parameters:

numBytes: the maximum database size, in bytes

Returns:

the new maximum database size

public long getPageSize()

Returns the current database page size, in bytes.

Returns:

the database page size, in bytes

public void setPageSize(long numBytes)

Sets the database page size. The page size must be a power of two. This method does not work if any data has been written to the database file, and must be called right after the database has been created.

Parameters:

numBytes: the database page size, in bytes

public Cursor query(java.lang.String query)

Runs the given query on the database. If you would like to have typed bind arguments, use SupportSQLiteDatabase.query(SupportSQLiteQuery).

Parameters:

query: The SQL query that includes the query and can bind into a given compiled program.

Returns:

A object, which is positioned before the first entry. Note that s are not synchronized, see the documentation for more details.

See also: SupportSQLiteDatabase.query(SupportSQLiteQuery)

public Cursor query(java.lang.String query, java.lang.Object bindArgs[])

Runs the given query on the database. If you would like to have bind arguments, use SupportSQLiteDatabase.query(SupportSQLiteQuery).

Parameters:

query: The SQL query that includes the query and can bind into a given compiled program.
bindArgs: The query arguments to bind.

Returns:

A object, which is positioned before the first entry. Note that s are not synchronized, see the documentation for more details.

See also: SupportSQLiteDatabase.query(SupportSQLiteQuery)

public Cursor query(SupportSQLiteQuery query)

Runs the given query on the database.

This class allows using type safe sql program bindings while running queries.

Parameters:

query: The SQL query that includes the query and can bind into a given compiled program.

Returns:

A object, which is positioned before the first entry. Note that s are not synchronized, see the documentation for more details.

See also: SimpleSQLiteQuery

public Cursor query(SupportSQLiteQuery query, CancellationSignal cancellationSignal)

Runs the given query on the database.

This class allows using type safe sql program bindings while running queries.

Parameters:

query: The SQL query that includes the query and can bind into a given compiled program.
cancellationSignal: A signal to cancel the operation in progress, or null if none. If the operation is canceled, then will be thrown when the query is executed.

Returns:

A object, which is positioned before the first entry. Note that s are not synchronized, see the documentation for more details.

public long insert(java.lang.String table, int conflictAlgorithm, ContentValues values)

Convenience method for inserting a row into the database.

Parameters:

table: the table to insert the row into
values: this map contains the initial column values for the row. The keys should be the column names and the values the column values
conflictAlgorithm: for insert conflict resolver. One of SQLiteDatabase, SQLiteDatabase, SQLiteDatabase, SQLiteDatabase, SQLiteDatabase, SQLiteDatabase.

Returns:

the row ID of the newly inserted row, or -1 if an error occurred

public int delete(java.lang.String table, java.lang.String whereClause, java.lang.Object whereArgs[])

Convenience method for deleting rows in the database.

Parameters:

table: the table to delete from
whereClause: the optional WHERE clause to apply when deleting. Passing null will delete all rows.
whereArgs: You may include ?s in the where clause, which will be replaced by the values from whereArgs. The values will be bound as Strings.

Returns:

the number of rows affected if a whereClause is passed in, 0 otherwise. To remove all rows and get a count pass "1" as the whereClause.

public int update(java.lang.String table, int conflictAlgorithm, ContentValues values, java.lang.String whereClause, java.lang.Object whereArgs[])

Convenience method for updating rows in the database.

Parameters:

table: the table to update in
conflictAlgorithm: for update conflict resolver. One of SQLiteDatabase, SQLiteDatabase, SQLiteDatabase, SQLiteDatabase, SQLiteDatabase, SQLiteDatabase.
values: a map from column names to new column values. null is a valid value that will be translated to NULL.
whereClause: the optional WHERE clause to apply when updating. Passing null will update all rows.
whereArgs: You may include ?s in the where clause, which will be replaced by the values from whereArgs. The values will be bound as Strings.

Returns:

the number of rows affected

public void execSQL(java.lang.String sql)

Execute a single SQL statement that does not return any data.

When using SupportSQLiteDatabase.enableWriteAheadLogging(), journal_mode is automatically managed by this class. So, do not set journal_mode using "PRAGMA journal_mode'" statement if your app is using SupportSQLiteDatabase.enableWriteAheadLogging()

Parameters:

sql: the SQL statement to be executed. Multiple statements separated by semicolons are not supported.

See also: SupportSQLiteDatabase.query(SupportSQLiteQuery)

public void execSQL(java.lang.String sql, java.lang.Object bindArgs[])

Execute a single SQL statement that does not return any data.

When using SupportSQLiteDatabase.enableWriteAheadLogging(), journal_mode is automatically managed by this class. So, do not set journal_mode using "PRAGMA journal_mode'" statement if your app is using SupportSQLiteDatabase.enableWriteAheadLogging()

Parameters:

sql: the SQL statement to be executed. Multiple statements separated by semicolons are not supported.
bindArgs: only byte[], String, Long and Double are supported in selectionArgs.

See also: SupportSQLiteDatabase.query(SupportSQLiteQuery)

public boolean isReadOnly()

Returns true if the database is opened as read only.

Returns:

True if database is opened as read only.

public boolean isOpen()

Returns true if the database is currently open.

Returns:

True if the database is currently open (has not been closed).

public boolean needUpgrade(int newVersion)

Returns true if the new version code is greater than the current database version.

Parameters:

newVersion: The new version code.

Returns:

True if the new version code is greater than the current database version.

public java.lang.String getPath()

Gets the path to the database file.

Returns:

The path to the database file.

public void setLocale(java.util.Locale locale)

Sets the locale for this database. Does nothing if this database has the SQLiteDatabase flag set or was opened read only.

Parameters:

locale: The new locale.

public void setMaxSqlCacheSize(int cacheSize)

Sets the maximum size of the prepared-statement cache for this database. (size of the cache = number of compiled-sql-statements stored in the cache).

Maximum cache size can ONLY be increased from its current size (default = 10). If this method is called with smaller size than the current maximum value, then IllegalStateException is thrown.

This method is thread-safe.

Parameters:

cacheSize: the size of the cache. can be (0 to SQLiteDatabase)

public void setForeignKeyConstraintsEnabled(boolean enable)

Sets whether foreign key constraints are enabled for the database.

By default, foreign key constraints are not enforced by the database. This method allows an application to enable foreign key constraints. It must be called each time the database is opened to ensure that foreign key constraints are enabled for the session.

A good time to call this method is right after calling #openOrCreateDatabase or in the SupportSQLiteOpenHelper.Callback.onConfigure(SupportSQLiteDatabase) callback.

When foreign key constraints are disabled, the database does not check whether changes to the database will violate foreign key constraints. Likewise, when foreign key constraints are disabled, the database will not execute cascade delete or update triggers. As a result, it is possible for the database state to become inconsistent. To perform a database integrity check, call SupportSQLiteDatabase.isDatabaseIntegrityOk().

This method must not be called while a transaction is in progress.

See also SQLite Foreign Key Constraints for more details about foreign key constraint support.

Parameters:

enable: True to enable foreign key constraints, false to disable them.

public boolean enableWriteAheadLogging()

This method enables parallel execution of queries from multiple threads on the same database. It does this by opening multiple connections to the database and using a different database connection for each query. The database journal mode is also changed to enable writes to proceed concurrently with reads.

When write-ahead logging is not enabled (the default), it is not possible for reads and writes to occur on the database at the same time. Before modifying the database, the writer implicitly acquires an exclusive lock on the database which prevents readers from accessing the database until the write is completed.

In contrast, when write-ahead logging is enabled (by calling this method), write operations occur in a separate log file which allows reads to proceed concurrently. While a write is in progress, readers on other threads will perceive the state of the database as it was before the write began. When the write completes, readers on other threads will then perceive the new state of the database.

It is a good idea to enable write-ahead logging whenever a database will be concurrently accessed and modified by multiple threads at the same time. However, write-ahead logging uses significantly more memory than ordinary journaling because there are multiple connections to the same database. So if a database will only be used by a single thread, or if optimizing concurrency is not very important, then write-ahead logging should be disabled.

After calling this method, execution of queries in parallel is enabled as long as the database remains open. To disable execution of queries in parallel, either call SupportSQLiteDatabase.disableWriteAheadLogging() or close the database and reopen it.

The maximum number of connections used to execute queries in parallel is dependent upon the device memory and possibly other properties.

If a query is part of a transaction, then it is executed on the same database handle the transaction was begun.

Writers should use SupportSQLiteDatabase.beginTransactionNonExclusive() or SupportSQLiteDatabase.beginTransactionWithListenerNonExclusive(SQLiteTransactionListener) to start a transaction. Non-exclusive mode allows database file to be in readable by other threads executing queries.

If the database has any attached databases, then execution of queries in parallel is NOT possible. Likewise, write-ahead logging is not supported for read-only databases or memory databases. In such cases, enableWriteAheadLogging returns false.

The best way to enable write-ahead logging is to pass the SQLiteDatabase flag to SQLiteDatabase. This is more efficient than calling

     SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
             SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
             myDatabaseErrorHandler);
     db.enableWriteAheadLogging();
 

Another way to enable write-ahead logging is to call enableWriteAheadLogging after opening the database.

     SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
             SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
     db.enableWriteAheadLogging();
 

See also SQLite Write-Ahead Logging for more details about how write-ahead logging works.

Returns:

True if write-ahead logging is enabled.

See also: SQLiteDatabase, SupportSQLiteDatabase.disableWriteAheadLogging()

public void disableWriteAheadLogging()

This method disables the features enabled by SupportSQLiteDatabase.enableWriteAheadLogging().

See also: SupportSQLiteDatabase.enableWriteAheadLogging()

public boolean isWriteAheadLoggingEnabled()

Returns true if write-ahead logging has been enabled for this database.

Returns:

True if write-ahead logging has been enabled for this database.

See also: SupportSQLiteDatabase.enableWriteAheadLogging(), SQLiteDatabase

public java.util.List<> getAttachedDbs()

Returns list of full path names of all attached databases including the main database by executing 'pragma database_list' on the database.

Returns:

ArrayList of pairs of (database name, database file path) or null if the database is not open.

public boolean isDatabaseIntegrityOk()

Runs 'pragma integrity_check' on the given database (and all the attached databases) and returns true if the given database (and all its attached databases) pass integrity_check, false otherwise.

If the result is false, then this method logs the errors reported by the integrity_check command execution.

Note that 'pragma integrity_check' on a database can take a long time.

Returns:

true if the given database (and all its attached databases) pass integrity_check, false otherwise.

Source

/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.sqlite.db;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteTransactionListener;
import android.os.Build;
import android.os.CancellationSignal;
import android.os.OperationCanceledException;
import android.util.Pair;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import java.io.Closeable;
import java.util.List;
import java.util.Locale;

/**
 * A database abstraction which removes the framework dependency and allows swapping underlying
 * sql versions. It mimics the behavior of {@link android.database.sqlite.SQLiteDatabase}
 */
@SuppressWarnings("unused")
public interface SupportSQLiteDatabase extends Closeable {
    /**
     * Compiles the given SQL statement.
     *
     * @param sql The sql query.
     * @return Compiled statement.
     */
    SupportSQLiteStatement compileStatement(String sql);

    /**
     * Begins a transaction in EXCLUSIVE mode.
     * <p>
     * Transactions can be nested.
     * When the outer transaction is ended all of
     * the work done in that transaction and all of the nested transactions will be committed or
     * rolled back. The changes will be rolled back if any transaction is ended without being
     * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
     * </p>
     * <p>Here is the standard idiom for transactions:
     *
     * <pre>
     *   db.beginTransaction();
     *   try {
     *     ...
     *     db.setTransactionSuccessful();
     *   } finally {
     *     db.endTransaction();
     *   }
     * </pre>
     */
    void beginTransaction();

    /**
     * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
     * the outer transaction is ended all of the work done in that transaction
     * and all of the nested transactions will be committed or rolled back. The
     * changes will be rolled back if any transaction is ended without being
     * marked as clean (by calling setTransactionSuccessful). Otherwise they
     * will be committed.
     * <p>
     * Here is the standard idiom for transactions:
     *
     * <pre>
     *   db.beginTransactionNonExclusive();
     *   try {
     *     ...
     *     db.setTransactionSuccessful();
     *   } finally {
     *     db.endTransaction();
     *   }
     * </pre>
     */
    void beginTransactionNonExclusive();

    /**
     * Begins a transaction in EXCLUSIVE mode.
     * <p>
     * Transactions can be nested.
     * When the outer transaction is ended all of
     * the work done in that transaction and all of the nested transactions will be committed or
     * rolled back. The changes will be rolled back if any transaction is ended without being
     * marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
     * </p>
     * <p>Here is the standard idiom for transactions:
     *
     * <pre>
     *   db.beginTransactionWithListener(listener);
     *   try {
     *     ...
     *     db.setTransactionSuccessful();
     *   } finally {
     *     db.endTransaction();
     *   }
     * </pre>
     *
     * @param transactionListener listener that should be notified when the transaction begins,
     *                            commits, or is rolled back, either explicitly or by a call to
     *                            {@link #yieldIfContendedSafely}.
     */
    void beginTransactionWithListener(SQLiteTransactionListener transactionListener);

    /**
     * Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
     * the outer transaction is ended all of the work done in that transaction
     * and all of the nested transactions will be committed or rolled back. The
     * changes will be rolled back if any transaction is ended without being
     * marked as clean (by calling setTransactionSuccessful). Otherwise they
     * will be committed.
     * <p>
     * Here is the standard idiom for transactions:
     *
     * <pre>
     *   db.beginTransactionWithListenerNonExclusive(listener);
     *   try {
     *     ...
     *     db.setTransactionSuccessful();
     *   } finally {
     *     db.endTransaction();
     *   }
     * </pre>
     *
     * @param transactionListener listener that should be notified when the
     *                            transaction begins, commits, or is rolled back, either
     *                            explicitly or by a call to {@link #yieldIfContendedSafely}.
     */
    void beginTransactionWithListenerNonExclusive(SQLiteTransactionListener transactionListener);

    /**
     * End a transaction. See beginTransaction for notes about how to use this and when transactions
     * are committed and rolled back.
     */
    void endTransaction();

    /**
     * Marks the current transaction as successful. Do not do any more database work between
     * calling this and calling endTransaction. Do as little non-database work as possible in that
     * situation too. If any errors are encountered between this and endTransaction the transaction
     * will still be committed.
     *
     * @throws IllegalStateException if the current thread is not in a transaction or the
     *                               transaction is already marked as successful.
     */
    void setTransactionSuccessful();

    /**
     * Returns true if the current thread has a transaction pending.
     *
     * @return True if the current thread is in a transaction.
     */
    boolean inTransaction();

    /**
     * Returns true if the current thread is holding an active connection to the database.
     * <p>
     * The name of this method comes from a time when having an active connection
     * to the database meant that the thread was holding an actual lock on the
     * database.  Nowadays, there is no longer a true "database lock" although threads
     * may block if they cannot acquire a database connection to perform a
     * particular operation.
     * </p>
     *
     * @return True if the current thread is holding an active connection to the database.
     */
    boolean isDbLockedByCurrentThread();

    /**
     * Temporarily end the transaction to let other threads run. The transaction is assumed to be
     * successful so far. Do not call setTransactionSuccessful before calling this. When this
     * returns a new transaction will have been created but not marked as successful. This assumes
     * that there are no nested transactions (beginTransaction has only been called once) and will
     * throw an exception if that is not the case.
     *
     * @return true if the transaction was yielded
     */
    boolean yieldIfContendedSafely();

    /**
     * Temporarily end the transaction to let other threads run. The transaction is assumed to be
     * successful so far. Do not call setTransactionSuccessful before calling this. When this
     * returns a new transaction will have been created but not marked as successful. This assumes
     * that there are no nested transactions (beginTransaction has only been called once) and will
     * throw an exception if that is not the case.
     *
     * @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
     *                             the lock was actually yielded. This will allow other background
     *                             threads to make some
     *                             more progress than they would if we started the transaction
     *                             immediately.
     * @return true if the transaction was yielded
     */
    boolean yieldIfContendedSafely(long sleepAfterYieldDelay);

    /**
     * Returns true if {@link #execPerConnectionSQL(String, Object[])} is supported by the
     * implementation.
     *
     * @return true if {@link #execPerConnectionSQL(String, Object[])} can be invoked safely,
     * false otherwise.
     */
    @SuppressWarnings("AcronymName") // To keep consistency with framework method name.
    default boolean isExecPerConnectionSQLSupported() {
        return false;
    }

    /**
     * Execute the given SQL statement on all connections to this database.
     * <p>
     * This statement will be immediately executed on all existing connections,
     * and will be automatically executed on all future connections.
     * <p>
     * Some example usages are changes like {@code PRAGMA trusted_schema=OFF} or
     * functions like {@code SELECT icu_load_collation()}. If you execute these
     * statements using {@link #execSQL} then they will only apply to a single
     * database connection; using this method will ensure that they are
     * uniformly applied to all current and future connections.
     * <p>
     * An implementation of {@link SupportSQLiteDatabase} might not support this operation. Use
     * {@link #isExecPerConnectionSQLSupported()} to check if this operation is supported before
     * calling this method.
     *
     * @param sql The SQL statement to be executed. Multiple statements
     *            separated by semicolons are not supported.
     * @param bindArgs The arguments that should be bound to the SQL statement.
     * @throws UnsupportedOperationException if this operation is not supported. To check if it
     * supported use {@link #isExecPerConnectionSQLSupported()}
     */
    @SuppressWarnings("AcronymName") // To keep consistency with framework method name.
    default void execPerConnectionSQL(@NonNull String sql,
            @SuppressLint("ArrayReturn") @Nullable Object[] bindArgs) {
        throw new UnsupportedOperationException();
    }

    /**
     * Gets the database version.
     *
     * @return the database version
     */
    int getVersion();

    /**
     * Sets the database version.
     *
     * @param version the new database version
     */
    void setVersion(int version);

    /**
     * Returns the maximum size the database may grow to.
     *
     * @return the new maximum database size
     */
    long getMaximumSize();

    /**
     * Sets the maximum size the database will grow to. The maximum size cannot
     * be set below the current size.
     *
     * @param numBytes the maximum database size, in bytes
     * @return the new maximum database size
     */
    long setMaximumSize(long numBytes);

    /**
     * Returns the current database page size, in bytes.
     *
     * @return the database page size, in bytes
     */
    long getPageSize();

    /**
     * Sets the database page size. The page size must be a power of two. This
     * method does not work if any data has been written to the database file,
     * and must be called right after the database has been created.
     *
     * @param numBytes the database page size, in bytes
     */
    void setPageSize(long numBytes);

    /**
     * Runs the given query on the database. If you would like to have typed bind arguments,
     * use {@link #query(SupportSQLiteQuery)}.
     *
     * @param query The SQL query that includes the query and can bind into a given compiled
     *              program.
     * @return A {@link Cursor} object, which is positioned before the first entry. Note that
     * {@link Cursor}s are not synchronized, see the documentation for more details.
     * @see #query(SupportSQLiteQuery)
     */
    Cursor query(String query);

    /**
     * Runs the given query on the database. If you would like to have bind arguments,
     * use {@link #query(SupportSQLiteQuery)}.
     *
     * @param query The SQL query that includes the query and can bind into a given compiled
     *              program.
     * @param bindArgs The query arguments to bind.
     * @return A {@link Cursor} object, which is positioned before the first entry. Note that
     * {@link Cursor}s are not synchronized, see the documentation for more details.
     * @see #query(SupportSQLiteQuery)
     */
    Cursor query(String query, Object[] bindArgs);

    /**
     * Runs the given query on the database.
     * <p>
     * This class allows using type safe sql program bindings while running queries.
     *
     * @param query The SQL query that includes the query and can bind into a given compiled
     *              program.
     * @return A {@link Cursor} object, which is positioned before the first entry. Note that
     * {@link Cursor}s are not synchronized, see the documentation for more details.
     * @see SimpleSQLiteQuery
     */
    Cursor query(SupportSQLiteQuery query);

    /**
     * Runs the given query on the database.
     * <p>
     * This class allows using type safe sql program bindings while running queries.
     *
     * @param query The SQL query that includes the query and can bind into a given compiled
     *              program.
     * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
     * If the operation is canceled, then {@link OperationCanceledException} will be thrown
     * when the query is executed.
     * @return A {@link Cursor} object, which is positioned before the first entry. Note that
     * {@link Cursor}s are not synchronized, see the documentation for more details.
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    Cursor query(SupportSQLiteQuery query, CancellationSignal cancellationSignal);

    /**
     * Convenience method for inserting a row into the database.
     *
     * @param table          the table to insert the row into
     * @param values         this map contains the initial column values for the
     *                       row. The keys should be the column names and the values the
     *                       column values
     * @param conflictAlgorithm for insert conflict resolver. One of
     * {@link SQLiteDatabase#CONFLICT_NONE}, {@link SQLiteDatabase#CONFLICT_ROLLBACK},
     * {@link SQLiteDatabase#CONFLICT_ABORT}, {@link SQLiteDatabase#CONFLICT_FAIL},
     * {@link SQLiteDatabase#CONFLICT_IGNORE}, {@link SQLiteDatabase#CONFLICT_REPLACE}.
     * @return the row ID of the newly inserted row, or -1 if an error occurred
     * @throws SQLException If the insert fails
     */
    long insert(String table, int conflictAlgorithm, ContentValues values) throws SQLException;

    /**
     * Convenience method for deleting rows in the database.
     *
     * @param table       the table to delete from
     * @param whereClause the optional WHERE clause to apply when deleting.
     *                    Passing null will delete all rows.
     * @param whereArgs   You may include ?s in the where clause, which
     *                    will be replaced by the values from whereArgs. The values
     *                    will be bound as Strings.
     * @return the number of rows affected if a whereClause is passed in, 0
     * otherwise. To remove all rows and get a count pass "1" as the
     * whereClause.
     */
    int delete(String table, String whereClause, Object[] whereArgs);

    /**
     * Convenience method for updating rows in the database.
     *
     * @param table       the table to update in
     * @param conflictAlgorithm for update conflict resolver. One of
     * {@link SQLiteDatabase#CONFLICT_NONE}, {@link SQLiteDatabase#CONFLICT_ROLLBACK},
     * {@link SQLiteDatabase#CONFLICT_ABORT}, {@link SQLiteDatabase#CONFLICT_FAIL},
     * {@link SQLiteDatabase#CONFLICT_IGNORE}, {@link SQLiteDatabase#CONFLICT_REPLACE}.
     * @param values      a map from column names to new column values. null is a
     *                    valid value that will be translated to NULL.
     * @param whereClause the optional WHERE clause to apply when updating.
     *                    Passing null will update all rows.
     * @param whereArgs   You may include ?s in the where clause, which
     *                    will be replaced by the values from whereArgs. The values
     *                    will be bound as Strings.
     * @return the number of rows affected
     */
    int update(String table, int conflictAlgorithm,
            ContentValues values, String whereClause, Object[] whereArgs);

    /**
     * Execute a single SQL statement that does not return any data.
     * <p>
     * When using {@link #enableWriteAheadLogging()}, journal_mode is
     * automatically managed by this class. So, do not set journal_mode
     * using "PRAGMA journal_mode'<value>" statement if your app is using
     * {@link #enableWriteAheadLogging()}
     * </p>
     *
     * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
     *            not supported.
     * @throws SQLException if the SQL string is invalid
     * @see #query(SupportSQLiteQuery)
     */
    void execSQL(String sql) throws SQLException;

    /**
     * Execute a single SQL statement that does not return any data.
     * <p>
     * When using {@link #enableWriteAheadLogging()}, journal_mode is
     * automatically managed by this class. So, do not set journal_mode
     * using "PRAGMA journal_mode'<value>" statement if your app is using
     * {@link #enableWriteAheadLogging()}
     * </p>
     *
     * @param sql      the SQL statement to be executed. Multiple statements separated by semicolons
     *                 are
     *                 not supported.
     * @param bindArgs only byte[], String, Long and Double are supported in selectionArgs.
     * @throws SQLException if the SQL string is invalid
     * @see #query(SupportSQLiteQuery)
     */
    void execSQL(String sql, Object[] bindArgs) throws SQLException;

    /**
     * Returns true if the database is opened as read only.
     *
     * @return True if database is opened as read only.
     */
    boolean isReadOnly();

    /**
     * Returns true if the database is currently open.
     *
     * @return True if the database is currently open (has not been closed).
     */
    boolean isOpen();

    /**
     * Returns true if the new version code is greater than the current database version.
     *
     * @param newVersion The new version code.
     * @return True if the new version code is greater than the current database version.
     */
    boolean needUpgrade(int newVersion);

    /**
     * Gets the path to the database file.
     *
     * @return The path to the database file.
     */
    String getPath();

    /**
     * Sets the locale for this database.  Does nothing if this database has
     * the {@link SQLiteDatabase#NO_LOCALIZED_COLLATORS} flag set or was opened read only.
     *
     * @param locale The new locale.
     * @throws SQLException if the locale could not be set.  The most common reason
     *                      for this is that there is no collator available for the locale you
     *                      requested.
     *                      In this case the database remains unchanged.
     */
    void setLocale(Locale locale);

    /**
     * Sets the maximum size of the prepared-statement cache for this database.
     * (size of the cache = number of compiled-sql-statements stored in the cache).
     * <p>
     * Maximum cache size can ONLY be increased from its current size (default = 10).
     * If this method is called with smaller size than the current maximum value,
     * then IllegalStateException is thrown.
     * <p>
     * This method is thread-safe.
     *
     * @param cacheSize the size of the cache. can be (0 to
     *                  {@link SQLiteDatabase#MAX_SQL_CACHE_SIZE})
     * @throws IllegalStateException if input cacheSize gt;
     *                               {@link SQLiteDatabase#MAX_SQL_CACHE_SIZE}.
     */
    void setMaxSqlCacheSize(int cacheSize);

    /**
     * Sets whether foreign key constraints are enabled for the database.
     * <p>
     * By default, foreign key constraints are not enforced by the database.
     * This method allows an application to enable foreign key constraints.
     * It must be called each time the database is opened to ensure that foreign
     * key constraints are enabled for the session.
     * </p><p>
     * A good time to call this method is right after calling {@code #openOrCreateDatabase}
     * or in the {@link SupportSQLiteOpenHelper.Callback#onConfigure} callback.
     * </p><p>
     * When foreign key constraints are disabled, the database does not check whether
     * changes to the database will violate foreign key constraints.  Likewise, when
     * foreign key constraints are disabled, the database will not execute cascade
     * delete or update triggers.  As a result, it is possible for the database
     * state to become inconsistent.  To perform a database integrity check,
     * call {@link #isDatabaseIntegrityOk}.
     * </p><p>
     * This method must not be called while a transaction is in progress.
     * </p><p>
     * See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
     * for more details about foreign key constraint support.
     * </p>
     *
     * @param enable True to enable foreign key constraints, false to disable them.
     * @throws IllegalStateException if the are transactions is in progress
     *                               when this method is called.
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    void setForeignKeyConstraintsEnabled(boolean enable);

    /**
     * This method enables parallel execution of queries from multiple threads on the
     * same database.  It does this by opening multiple connections to the database
     * and using a different database connection for each query.  The database
     * journal mode is also changed to enable writes to proceed concurrently with reads.
     * <p>
     * When write-ahead logging is not enabled (the default), it is not possible for
     * reads and writes to occur on the database at the same time.  Before modifying the
     * database, the writer implicitly acquires an exclusive lock on the database which
     * prevents readers from accessing the database until the write is completed.
     * </p><p>
     * In contrast, when write-ahead logging is enabled (by calling this method), write
     * operations occur in a separate log file which allows reads to proceed concurrently.
     * While a write is in progress, readers on other threads will perceive the state
     * of the database as it was before the write began.  When the write completes, readers
     * on other threads will then perceive the new state of the database.
     * </p><p>
     * It is a good idea to enable write-ahead logging whenever a database will be
     * concurrently accessed and modified by multiple threads at the same time.
     * However, write-ahead logging uses significantly more memory than ordinary
     * journaling because there are multiple connections to the same database.
     * So if a database will only be used by a single thread, or if optimizing
     * concurrency is not very important, then write-ahead logging should be disabled.
     * </p><p>
     * After calling this method, execution of queries in parallel is enabled as long as
     * the database remains open.  To disable execution of queries in parallel, either
     * call {@link #disableWriteAheadLogging} or close the database and reopen it.
     * </p><p>
     * The maximum number of connections used to execute queries in parallel is
     * dependent upon the device memory and possibly other properties.
     * </p><p>
     * If a query is part of a transaction, then it is executed on the same database handle the
     * transaction was begun.
     * </p><p>
     * Writers should use {@link #beginTransactionNonExclusive()} or
     * {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
     * to start a transaction.  Non-exclusive mode allows database file to be in readable
     * by other threads executing queries.
     * </p><p>
     * If the database has any attached databases, then execution of queries in parallel is NOT
     * possible.  Likewise, write-ahead logging is not supported for read-only databases
     * or memory databases.  In such cases, {@code enableWriteAheadLogging} returns false.
     * </p><p>
     * The best way to enable write-ahead logging is to pass the
     * {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag to
     * {@link SQLiteDatabase#openDatabase}.  This is more efficient than calling
     * <code><pre>
     *     SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
     *             SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
     *             myDatabaseErrorHandler);
     *     db.enableWriteAheadLogging();
     * </pre></code>
     * </p><p>
     * Another way to enable write-ahead logging is to call {@code enableWriteAheadLogging}
     * after opening the database.
     * <code><pre>
     *     SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
     *             SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
     *     db.enableWriteAheadLogging();
     * </pre></code>
     * </p><p>
     * See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
     * more details about how write-ahead logging works.
     * </p>
     *
     * @return True if write-ahead logging is enabled.
     * @throws IllegalStateException if there are transactions in progress at the
     *                               time this method is called.  WAL mode can only be changed when
     *                               there are no
     *                               transactions in progress.
     * @see SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING
     * @see #disableWriteAheadLogging
     */
    boolean enableWriteAheadLogging();

    /**
     * This method disables the features enabled by {@link #enableWriteAheadLogging()}.
     *
     * @throws IllegalStateException if there are transactions in progress at the
     *                               time this method is called.  WAL mode can only be changed when
     *                               there are no
     *                               transactions in progress.
     * @see #enableWriteAheadLogging
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    void disableWriteAheadLogging();

    /**
     * Returns true if write-ahead logging has been enabled for this database.
     *
     * @return True if write-ahead logging has been enabled for this database.
     * @see #enableWriteAheadLogging
     * @see SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    boolean isWriteAheadLoggingEnabled();

    /**
     * Returns list of full path names of all attached databases including the main database
     * by executing 'pragma database_list' on the database.
     *
     * @return ArrayList of pairs of (database name, database file path) or null if the database
     * is not open.
     */
    List<Pair<String, String>> getAttachedDbs();

    /**
     * Runs 'pragma integrity_check' on the given database (and all the attached databases)
     * and returns true if the given database (and all its attached databases) pass integrity_check,
     * false otherwise.
     * <p>
     * If the result is false, then this method logs the errors reported by the integrity_check
     * command execution.
     * <p>
     * Note that 'pragma integrity_check' on a database can take a long time.
     *
     * @return true if the given database (and all its attached databases) pass integrity_check,
     * false otherwise.
     */
    boolean isDatabaseIntegrityOk();
}