1e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/* 2e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Copyright (C) 2011 The Android Open Source Project 3e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 4e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * you may not use this file except in compliance with the License. 6e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * You may obtain a copy of the License at 7e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 8e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 10e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Unless required by applicable law or agreed to in writing, software 11e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * See the License for the specific language governing permissions and 14e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * limitations under the License. 15e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 16e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 17e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownpackage android.database.sqlite; 18e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 19e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport android.database.CursorWindow; 20e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport android.database.DatabaseUtils; 21a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.CancellationSignal; 22a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.OperationCanceledException; 23e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport android.os.ParcelFileDescriptor; 24e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 25e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/** 26e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Provides a single client the ability to use a database. 27e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 28e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <h2>About database sessions</h2> 29e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 30e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Database access is always performed using a session. The session 31e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * manages the lifecycle of transactions and database connections. 32e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 33e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Sessions can be used to perform both read-only and read-write operations. 34e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * There is some advantage to knowing when a session is being used for 35e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * read-only purposes because the connection pool can optimize the use 36e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * of the available connections to permit multiple read-only operations 37e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * to execute in parallel whereas read-write operations may need to be serialized. 38e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 39e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * When <em>Write Ahead Logging (WAL)</em> is enabled, the database can 40e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * execute simultaneous read-only and read-write transactions, provided that 41e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * at most one read-write transaction is performed at a time. When WAL is not 42e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * enabled, read-only transactions can execute in parallel but read-write 43e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * transactions are mutually exclusive. 44e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 45e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 46e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <h2>Ownership and concurrency guarantees</h2> 47e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 48e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Session objects are not thread-safe. In fact, session objects are thread-bound. 49e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * The {@link SQLiteDatabase} uses a thread-local variable to associate a session 50e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * with each thread for the use of that thread alone. Consequently, each thread 51e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * has its own session object and therefore its own transaction state independent 52e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * of other threads. 53e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 54e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * A thread has at most one session per database. This constraint ensures that 55e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * a thread can never use more than one database connection at a time for a 56e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * given database. As the number of available database connections is limited, 57e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * if a single thread tried to acquire multiple connections for the same database 58e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * at the same time, it might deadlock. Therefore we allow there to be only 59e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * one session (so, at most one connection) per thread per database. 60e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 61e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 62e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <h2>Transactions</h2> 63e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 64e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * There are two kinds of transaction: implicit transactions and explicit 65e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * transactions. 66e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 67e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * An implicit transaction is created whenever a database operation is requested 68e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * and there is no explicit transaction currently in progress. An implicit transaction 69e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * only lasts for the duration of the database operation in question and then it 70e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * is ended. If the database operation was successful, then its changes are committed. 71e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 72e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * An explicit transaction is started by calling {@link #beginTransaction} and 73e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * specifying the desired transaction mode. Once an explicit transaction has begun, 74e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * all subsequent database operations will be performed as part of that transaction. 75e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * To end an explicit transaction, first call {@link #setTransactionSuccessful} if the 76e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * transaction was successful, then call {@link #end}. If the transaction was 77e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * marked successful, its changes will be committed, otherwise they will be rolled back. 78e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 79e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Explicit transactions can also be nested. A nested explicit transaction is 80e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * started with {@link #beginTransaction}, marked successful with 81e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * {@link #setTransactionSuccessful}and ended with {@link #endTransaction}. 82e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * If any nested transaction is not marked successful, then the entire transaction 83e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * including all of its nested transactions will be rolled back 84e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * when the outermost transaction is ended. 85e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 86e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * To improve concurrency, an explicit transaction can be yielded by calling 87e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * {@link #yieldTransaction}. If there is contention for use of the database, 88e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * then yielding ends the current transaction, commits its changes, releases the 89e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * database connection for use by another session for a little while, and starts a 90e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * new transaction with the same properties as the original one. 91e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Changes committed by {@link #yieldTransaction} cannot be rolled back. 92e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 93e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * When a transaction is started, the client can provide a {@link SQLiteTransactionListener} 94e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * to listen for notifications of transaction-related events. 95e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 96e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Recommended usage: 97e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <code><pre> 98e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * // First, begin the transaction. 99e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * session.beginTransaction(SQLiteSession.TRANSACTION_MODE_DEFERRED, 0); 100e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * try { 101e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * // Then do stuff... 102e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * session.execute("INSERT INTO ...", null, 0); 103e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 104e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * // As the very last step before ending the transaction, mark it successful. 105e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * session.setTransactionSuccessful(); 106e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * } finally { 107e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * // Finally, end the transaction. 108e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * // This statement will commit the transaction if it was marked successful or 109e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * // roll it back otherwise. 110e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * session.endTransaction(); 111e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * } 112e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </pre></code> 113e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 114e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 115e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <h2>Database connections</h2> 116e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 117e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * A {@link SQLiteDatabase} can have multiple active sessions at the same 118e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * time. Each session acquires and releases connections to the database 119e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * as needed to perform each requested database transaction. If all connections 120e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * are in use, then database transactions on some sessions will block until a 121e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * connection becomes available. 122e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 123e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * The session acquires a single database connection only for the duration 124e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * of a single (implicit or explicit) database transaction, then releases it. 125e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This characteristic allows a small pool of database connections to be shared 126e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * efficiently by multiple sessions as long as they are not all trying to perform 127e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * database transactions at the same time. 128e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 129e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 130e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <h2>Responsiveness</h2> 131e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 132e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Because there are a limited number of database connections and the session holds 133e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * a database connection for the entire duration of a database transaction, 134e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * it is important to keep transactions short. This is especially important 135e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * for read-write transactions since they may block other transactions 136e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * from executing. Consider calling {@link #yieldTransaction} periodically 137e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * during long-running transactions. 138e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 139e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Another important consideration is that transactions that take too long to 140e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * run may cause the application UI to become unresponsive. Even if the transaction 141e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * is executed in a background thread, the user will get bored and 142e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * frustrated if the application shows no data for several seconds while 143e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * a transaction runs. 144e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 145e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Guidelines: 146e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <ul> 147e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <li>Do not perform database transactions on the UI thread.</li> 148e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <li>Keep database transactions as short as possible.</li> 149e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <li>Simple queries often run faster than complex queries.</li> 150e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <li>Measure the performance of your database transactions.</li> 151e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <li>Consider what will happen when the size of the data set grows. 152e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * A query that works well on 100 rows may struggle with 10,000.</li> 153e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </ul> 154e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 155a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown * <h2>Reentrance</h2> 156a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown * <p> 157a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown * This class must tolerate reentrant execution of SQLite operations because 158a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown * triggers may call custom SQLite functions that perform additional queries. 159a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown * </p> 160a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown * 161e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @hide 162e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 163e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownpublic final class SQLiteSession { 164e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final SQLiteConnectionPool mConnectionPool; 165e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 166e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private SQLiteConnection mConnection; 167e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private int mConnectionFlags; 168a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown private int mConnectionUseCount; 169e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private Transaction mTransactionPool; 170e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private Transaction mTransactionStack; 171e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 172e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 173e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Transaction mode: Deferred. 174e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 175e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * In a deferred transaction, no locks are acquired on the database 176e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * until the first operation is performed. If the first operation is 177e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * read-only, then a <code>SHARED</code> lock is acquired, otherwise 178e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * a <code>RESERVED</code> lock is acquired. 179e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 180e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * While holding a <code>SHARED</code> lock, this session is only allowed to 181e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * read but other sessions are allowed to read or write. 182e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * While holding a <code>RESERVED</code> lock, this session is allowed to read 183e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or write but other sessions are only allowed to read. 184e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 185e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Because the lock is only acquired when needed in a deferred transaction, 186e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * it is possible for another session to write to the database first before 187e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * this session has a chance to do anything. 188e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 189e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Corresponds to the SQLite <code>BEGIN DEFERRED</code> transaction mode. 190e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 191e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 192e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public static final int TRANSACTION_MODE_DEFERRED = 0; 193e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 194e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 195e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Transaction mode: Immediate. 196e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 197e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * When an immediate transaction begins, the session acquires a 198e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <code>RESERVED</code> lock. 199e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 200e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * While holding a <code>RESERVED</code> lock, this session is allowed to read 201e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or write but other sessions are only allowed to read. 202e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 203e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Corresponds to the SQLite <code>BEGIN IMMEDIATE</code> transaction mode. 204e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 205e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 206e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public static final int TRANSACTION_MODE_IMMEDIATE = 1; 207e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 208e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 209e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Transaction mode: Exclusive. 210e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 211e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * When an exclusive transaction begins, the session acquires an 212e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <code>EXCLUSIVE</code> lock. 213e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 214e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * While holding an <code>EXCLUSIVE</code> lock, this session is allowed to read 215e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or write but no other sessions are allowed to access the database. 216e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 217e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Corresponds to the SQLite <code>BEGIN EXCLUSIVE</code> transaction mode. 218e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 219e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 220e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public static final int TRANSACTION_MODE_EXCLUSIVE = 2; 221e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 222e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 223e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Creates a session bound to the specified connection pool. 224e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 225e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionPool The connection pool. 226e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 227e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public SQLiteSession(SQLiteConnectionPool connectionPool) { 228e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (connectionPool == null) { 229e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("connectionPool must not be null"); 230e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 231e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 232e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConnectionPool = connectionPool; 233e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 234e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 235e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 236e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Returns true if the session has a transaction in progress. 237e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 238e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return True if the session has a transaction in progress. 239e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 240e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public boolean hasTransaction() { 241e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return mTransactionStack != null; 242e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 243e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 244e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 245e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Returns true if the session has a nested transaction in progress. 246e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 247e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return True if the session has a nested transaction in progress. 248e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 249e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public boolean hasNestedTransaction() { 250e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return mTransactionStack != null && mTransactionStack.mParent != null; 251e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 252e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 253e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 254e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Returns true if the session has an active database connection. 255e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 256e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return True if the session has an active database connection. 257e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 258e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public boolean hasConnection() { 259e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return mConnection != null; 260e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 261e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 262e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 263e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Begins a transaction. 264e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 265e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Transactions may nest. If the transaction is not in progress, 266e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * then a database connection is obtained and a new transaction is started. 267e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Otherwise, a nested transaction is started. 268e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 269e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Each call to {@link #beginTransaction} must be matched exactly by a call 270e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * to {@link #endTransaction}. To mark a transaction as successful, 271e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * call {@link #setTransactionSuccessful} before calling {@link #endTransaction}. 272e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * If the transaction is not successful, or if any of its nested 273e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * transactions were not successful, then the entire transaction will 274e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * be rolled back when the outermost transaction is ended. 275e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 276e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 277e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param transactionMode The transaction mode. One of: {@link #TRANSACTION_MODE_DEFERRED}, 278e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * {@link #TRANSACTION_MODE_IMMEDIATE}, or {@link #TRANSACTION_MODE_EXCLUSIVE}. 279e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Ignored when creating a nested transaction. 280e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param transactionListener The transaction listener, or null if none. 281e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection flags to use if a connection must be 282e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by this operation. Refer to {@link SQLiteConnectionPool}. 2834c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 284e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 285e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws IllegalStateException if {@link #setTransactionSuccessful} has already been 286e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * called for the current transaction. 28775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws SQLiteException if an error occurs. 28875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 289e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 290e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @see #setTransactionSuccessful 291e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @see #yieldTransaction 292e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @see #endTransaction 293e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 294e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public void beginTransaction(int transactionMode, 29575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown SQLiteTransactionListener transactionListener, int connectionFlags, 2964c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 297e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throwIfTransactionMarkedSuccessful(); 29875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown beginTransactionUnchecked(transactionMode, transactionListener, connectionFlags, 2994c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); 300e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 301e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 302e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void beginTransactionUnchecked(int transactionMode, 30375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown SQLiteTransactionListener transactionListener, int connectionFlags, 3044c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 3054c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (cancellationSignal != null) { 3064c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal.throwIfCanceled(); 30775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 30875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 309a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown if (mTransactionStack == null) { 3104c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown acquireConnection(null, connectionFlags, cancellationSignal); // might throw 311a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown } 312e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 313e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Set up the transaction such that we can back out safely 314e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // in case we fail part way. 315e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mTransactionStack == null) { 316e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Execute SQL might throw a runtime exception. 317e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown switch (transactionMode) { 318e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown case TRANSACTION_MODE_IMMEDIATE: 31975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown mConnection.execute("BEGIN IMMEDIATE;", null, 3204c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); // might throw 321e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 322e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown case TRANSACTION_MODE_EXCLUSIVE: 32375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown mConnection.execute("BEGIN EXCLUSIVE;", null, 3244c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); // might throw 325e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 326e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown default: 3274c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown mConnection.execute("BEGIN;", null, cancellationSignal); // might throw 328e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 329e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 330e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 331e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 332e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Listener might throw a runtime exception. 333e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (transactionListener != null) { 334e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 335e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown transactionListener.onBegin(); // might throw 336e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } catch (RuntimeException ex) { 337e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mTransactionStack == null) { 3384c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown mConnection.execute("ROLLBACK;", null, cancellationSignal); // might throw 339e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 340e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw ex; 341e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 342e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 343e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 344e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // Bookkeeping can't throw, except an OOM, which is just too bad... 345e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Transaction transaction = obtainTransaction(transactionMode, transactionListener); 346e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown transaction.mParent = mTransactionStack; 347e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mTransactionStack = transaction; 348e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 349a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown if (mTransactionStack == null) { 350a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown releaseConnection(); // might throw 351a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown } 352e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 353e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 354e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 355e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 356e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Marks the current transaction as having completed successfully. 357e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 358e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This method can be called at most once between {@link #beginTransaction} and 359e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * {@link #endTransaction} to indicate that the changes made by the transaction should be 360e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * committed. If this method is not called, the changes will be rolled back 361e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * when the transaction is ended. 362e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 363e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 364e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws IllegalStateException if there is no current transaction, or if 365e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * {@link #setTransactionSuccessful} has already been called for the current transaction. 366e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 367e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @see #beginTransaction 368e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @see #endTransaction 369e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 370e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public void setTransactionSuccessful() { 371e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throwIfNoTransaction(); 372e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throwIfTransactionMarkedSuccessful(); 373e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 374e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mTransactionStack.mMarkedSuccessful = true; 375e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 376e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 377e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 378e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Ends the current transaction and commits or rolls back changes. 379e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 380e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * If this is the outermost transaction (not nested within any other 381e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * transaction), then the changes are committed if {@link #setTransactionSuccessful} 382e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * was called or rolled back otherwise. 383e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 384e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This method must be called exactly once for each call to {@link #beginTransaction}. 385e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 386e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 3874c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 38875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * 389e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws IllegalStateException if there is no current transaction. 39075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws SQLiteException if an error occurs. 39175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 392e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 393e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @see #beginTransaction 394e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @see #setTransactionSuccessful 395e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @see #yieldTransaction 396e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 3974c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown public void endTransaction(CancellationSignal cancellationSignal) { 398e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throwIfNoTransaction(); 399e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown assert mConnection != null; 400e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 401d19ff5f95dc9ea684edb5097ce97e7bf78c2e628Jeff Brown endTransactionUnchecked(cancellationSignal, false); 402e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 403e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 404d19ff5f95dc9ea684edb5097ce97e7bf78c2e628Jeff Brown private void endTransactionUnchecked(CancellationSignal cancellationSignal, boolean yielding) { 4054c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (cancellationSignal != null) { 4064c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal.throwIfCanceled(); 40775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 40875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 409e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final Transaction top = mTransactionStack; 410d19ff5f95dc9ea684edb5097ce97e7bf78c2e628Jeff Brown boolean successful = (top.mMarkedSuccessful || yielding) && !top.mChildFailed; 411e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 412e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown RuntimeException listenerException = null; 413e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final SQLiteTransactionListener listener = top.mListener; 414e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (listener != null) { 415e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 416e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (successful) { 417e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown listener.onCommit(); // might throw 418e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 419e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown listener.onRollback(); // might throw 420e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 421e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } catch (RuntimeException ex) { 422e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown listenerException = ex; 423e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown successful = false; 424e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 425e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 426e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 427e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mTransactionStack = top.mParent; 428e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown recycleTransaction(top); 429e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 430e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mTransactionStack != null) { 431e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!successful) { 432e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mTransactionStack.mChildFailed = true; 433e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 434e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 435e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 436e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (successful) { 4374c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown mConnection.execute("COMMIT;", null, cancellationSignal); // might throw 438e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 4394c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown mConnection.execute("ROLLBACK;", null, cancellationSignal); // might throw 440e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 441e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 442a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown releaseConnection(); // might throw 443e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 444e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 445e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 446e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (listenerException != null) { 447e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw listenerException; 448e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 449e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 450e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 451e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 452e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Temporarily ends a transaction to let other threads have use of 453e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * the database. Begins a new transaction after a specified delay. 454e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 455e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * If there are other threads waiting to acquire connections, 456e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * then the current transaction is committed and the database 457e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * connection is released. After a short delay, a new transaction 458e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * is started. 459e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 460e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * The transaction is assumed to be successful so far. Do not call 461e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * {@link #setTransactionSuccessful()} before calling this method. 462e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This method will fail if the transaction has already been marked 463e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * successful. 464e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 465e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * The changes that were committed by a yield cannot be rolled back later. 466e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 467e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Before this method was called, there must already have been 468e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * a transaction in progress. When this method returns, there will 469e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * still be a transaction in progress, either the same one as before 470e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or a new one if the transaction was actually yielded. 471e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 472e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This method should not be called when there is a nested transaction 473e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * in progress because it is not possible to yield a nested transaction. 474e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * If <code>throwIfNested</code> is true, then attempting to yield 475e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * a nested transaction will throw {@link IllegalStateException}, otherwise 476e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * the method will return <code>false</code> in that case. 477e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 478e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * If there is no nested transaction in progress but a previous nested 479e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * transaction failed, then the transaction is not yielded (because it 480e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * must be rolled back) and this method returns <code>false</code>. 481e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 482e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 483e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sleepAfterYieldDelayMillis A delay time to wait after yielding 484e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * the database connection to allow other threads some time to run. 485e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * If the value is less than or equal to zero, there will be no additional 486e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * delay beyond the time it will take to begin a new transaction. 487e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param throwIfUnsafe If true, then instead of returning false when no 488e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * transaction is in progress, a nested transaction is in progress, or when 489e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * the transaction has already been marked successful, throws {@link IllegalStateException}. 4904c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 491e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return True if the transaction was actually yielded. 492e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 493e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws IllegalStateException if <code>throwIfNested</code> is true and 494e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * there is no current transaction, there is a nested transaction in progress or 495e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * if {@link #setTransactionSuccessful} has already been called for the current transaction. 49675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws SQLiteException if an error occurs. 49775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 498e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 499e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @see #beginTransaction 500e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @see #endTransaction 501e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 50275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public boolean yieldTransaction(long sleepAfterYieldDelayMillis, boolean throwIfUnsafe, 5034c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 504e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (throwIfUnsafe) { 505e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throwIfNoTransaction(); 506e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throwIfTransactionMarkedSuccessful(); 507e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throwIfNestedTransaction(); 508e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 509e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mTransactionStack == null || mTransactionStack.mMarkedSuccessful 510e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown || mTransactionStack.mParent != null) { 511e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return false; 512e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 513e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 514e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown assert mConnection != null; 515e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 516e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mTransactionStack.mChildFailed) { 517e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return false; 518e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 519e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 52075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return yieldTransactionUnchecked(sleepAfterYieldDelayMillis, 5214c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); // might throw 522e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 523e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 52475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown private boolean yieldTransactionUnchecked(long sleepAfterYieldDelayMillis, 5254c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 5264c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (cancellationSignal != null) { 5274c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal.throwIfCanceled(); 52875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 52975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 530e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (!mConnectionPool.shouldYieldConnection(mConnection, mConnectionFlags)) { 531e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return false; 532e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 533e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 534e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final int transactionMode = mTransactionStack.mMode; 535e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final SQLiteTransactionListener listener = mTransactionStack.mListener; 536e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final int connectionFlags = mConnectionFlags; 537d19ff5f95dc9ea684edb5097ce97e7bf78c2e628Jeff Brown endTransactionUnchecked(cancellationSignal, true); // might throw 538e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 539e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (sleepAfterYieldDelayMillis > 0) { 540e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 541e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Thread.sleep(sleepAfterYieldDelayMillis); 542e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } catch (InterruptedException ex) { 543e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown // we have been interrupted, that's all we need to do 544e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 545e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 546e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 54775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown beginTransactionUnchecked(transactionMode, listener, connectionFlags, 5484c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); // might throw 549e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return true; 550e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 551e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 552e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 553e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Prepares a statement for execution but does not bind its parameters or execute it. 554e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 555e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This method can be used to check for syntax errors during compilation 556e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * prior to execution of the statement. If the {@code outStatementInfo} argument 557e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * is not null, the provided {@link SQLiteStatementInfo} object is populated 558e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * with information about the statement. 559e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p><p> 560e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * A prepared statement makes no reference to the arguments that may eventually 561e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * be bound to it, consequently it it possible to cache certain prepared statements 562e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * such as SELECT or INSERT/UPDATE statements. If the statement is cacheable, 563e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * then it will be stored in the cache for later and reused if possible. 564e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 565e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 566e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sql The SQL statement to prepare. 567e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection flags to use if a connection must be 568e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by this operation. Refer to {@link SQLiteConnectionPool}. 5694c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 570e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param outStatementInfo The {@link SQLiteStatementInfo} object to populate 571e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * with information about the statement, or null if none. 572e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 573e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if an error occurs, such as a syntax error. 57475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 575e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 5764c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown public void prepare(String sql, int connectionFlags, CancellationSignal cancellationSignal, 57775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown SQLiteStatementInfo outStatementInfo) { 578e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (sql == null) { 579e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("sql must not be null."); 580e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 581e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 5824c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (cancellationSignal != null) { 5834c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal.throwIfCanceled(); 58475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 58575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 5864c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown acquireConnection(sql, connectionFlags, cancellationSignal); // might throw 587e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 588e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConnection.prepare(sql, outStatementInfo); // might throw 589e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 590a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown releaseConnection(); // might throw 591e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 592e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 593e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 594e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 595e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Executes a statement that does not return a result. 596e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 597e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sql The SQL statement to execute. 598e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param bindArgs The arguments to bind, or null if none. 599e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection flags to use if a connection must be 600e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by this operation. Refer to {@link SQLiteConnectionPool}. 6014c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 602e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 603e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if an error occurs, such as a syntax error 604e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or invalid number of bind arguments. 60575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 606e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 60775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public void execute(String sql, Object[] bindArgs, int connectionFlags, 6084c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 609e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (sql == null) { 610e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("sql must not be null."); 611e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 612e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 6134c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) { 614e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return; 615e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 616e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 6174c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown acquireConnection(sql, connectionFlags, cancellationSignal); // might throw 618e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 6194c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown mConnection.execute(sql, bindArgs, cancellationSignal); // might throw 620e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 621a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown releaseConnection(); // might throw 622e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 623e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 624e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 625e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 626e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Executes a statement that returns a single <code>long</code> result. 627e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 628e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sql The SQL statement to execute. 629e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param bindArgs The arguments to bind, or null if none. 630e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection flags to use if a connection must be 631e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by this operation. Refer to {@link SQLiteConnectionPool}. 6324c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 633e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return The value of the first column in the first row of the result set 634e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * as a <code>long</code>, or zero if none. 635e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 636e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if an error occurs, such as a syntax error 637e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or invalid number of bind arguments. 63875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 639e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 64075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public long executeForLong(String sql, Object[] bindArgs, int connectionFlags, 6414c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 642e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (sql == null) { 643e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("sql must not be null."); 644e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 645e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 6464c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) { 647e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return 0; 648e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 649e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 6504c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown acquireConnection(sql, connectionFlags, cancellationSignal); // might throw 651e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 6524c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown return mConnection.executeForLong(sql, bindArgs, cancellationSignal); // might throw 653e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 654a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown releaseConnection(); // might throw 655e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 656e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 657e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 658e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 659e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Executes a statement that returns a single {@link String} result. 660e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 661e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sql The SQL statement to execute. 662e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param bindArgs The arguments to bind, or null if none. 663e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection flags to use if a connection must be 664e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by this operation. Refer to {@link SQLiteConnectionPool}. 6654c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 666e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return The value of the first column in the first row of the result set 667e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * as a <code>String</code>, or null if none. 668e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 669e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if an error occurs, such as a syntax error 670e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or invalid number of bind arguments. 67175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 672e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 67375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public String executeForString(String sql, Object[] bindArgs, int connectionFlags, 6744c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 675e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (sql == null) { 676e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("sql must not be null."); 677e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 678e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 6794c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) { 680e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return null; 681e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 682e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 6834c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown acquireConnection(sql, connectionFlags, cancellationSignal); // might throw 684e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 6854c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown return mConnection.executeForString(sql, bindArgs, cancellationSignal); // might throw 686e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 687a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown releaseConnection(); // might throw 688e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 689e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 690e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 691e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 692e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Executes a statement that returns a single BLOB result as a 693e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * file descriptor to a shared memory region. 694e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 695e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sql The SQL statement to execute. 696e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param bindArgs The arguments to bind, or null if none. 697e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection flags to use if a connection must be 698e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by this operation. Refer to {@link SQLiteConnectionPool}. 6994c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 700e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return The file descriptor for a shared memory region that contains 701e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * the value of the first column in the first row of the result set as a BLOB, 702e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or null if none. 703e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 704e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if an error occurs, such as a syntax error 705e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or invalid number of bind arguments. 70675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 707e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 708e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public ParcelFileDescriptor executeForBlobFileDescriptor(String sql, Object[] bindArgs, 7094c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown int connectionFlags, CancellationSignal cancellationSignal) { 710e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (sql == null) { 711e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("sql must not be null."); 712e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 713e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 7144c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) { 715e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return null; 716e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 717e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 7184c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown acquireConnection(sql, connectionFlags, cancellationSignal); // might throw 719e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 72075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return mConnection.executeForBlobFileDescriptor(sql, bindArgs, 7214c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); // might throw 722e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 723a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown releaseConnection(); // might throw 724e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 725e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 726e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 727e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 728e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Executes a statement that returns a count of the number of rows 729e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * that were changed. Use for UPDATE or DELETE SQL statements. 730e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 731e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sql The SQL statement to execute. 732e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param bindArgs The arguments to bind, or null if none. 733e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection flags to use if a connection must be 734e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by this operation. Refer to {@link SQLiteConnectionPool}. 7354c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 736e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return The number of rows that were changed. 737e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 738e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if an error occurs, such as a syntax error 739e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or invalid number of bind arguments. 74075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 741e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 74275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public int executeForChangedRowCount(String sql, Object[] bindArgs, int connectionFlags, 7434c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 744e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (sql == null) { 745e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("sql must not be null."); 746e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 747e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 7484c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) { 749e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return 0; 750e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 751e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 7524c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown acquireConnection(sql, connectionFlags, cancellationSignal); // might throw 753e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 75475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return mConnection.executeForChangedRowCount(sql, bindArgs, 7554c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); // might throw 756e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 757a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown releaseConnection(); // might throw 758e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 759e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 760e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 761e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 762e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Executes a statement that returns the row id of the last row inserted 763e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * by the statement. Use for INSERT SQL statements. 764e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 765e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sql The SQL statement to execute. 766e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param bindArgs The arguments to bind, or null if none. 767e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection flags to use if a connection must be 768e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by this operation. Refer to {@link SQLiteConnectionPool}. 7694c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 770e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return The row id of the last row that was inserted, or 0 if none. 771e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 772e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if an error occurs, such as a syntax error 773e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or invalid number of bind arguments. 77475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 775e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 77675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown public long executeForLastInsertedRowId(String sql, Object[] bindArgs, int connectionFlags, 7774c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 778e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (sql == null) { 779e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("sql must not be null."); 780e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 781e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 7824c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) { 783e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return 0; 784e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 785e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 7864c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown acquireConnection(sql, connectionFlags, cancellationSignal); // might throw 787e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 78875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown return mConnection.executeForLastInsertedRowId(sql, bindArgs, 7894c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); // might throw 790e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 791a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown releaseConnection(); // might throw 792e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 793e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 794e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 795e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 796e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Executes a statement and populates the specified {@link CursorWindow} 797e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * with a range of results. Returns the number of rows that were counted 798e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * during query execution. 799e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 800e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sql The SQL statement to execute. 801e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param bindArgs The arguments to bind, or null if none. 802e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param window The cursor window to clear and fill. 803e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param startPos The start position for filling the window. 804e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param requiredPos The position of a row that MUST be in the window. 805e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * If it won't fit, then the query should discard part of what it filled 806e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * so that it does. Must be greater than or equal to <code>startPos</code>. 807e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param countAllRows True to count all rows that the query would return 808e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * regagless of whether they fit in the window. 809e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection flags to use if a connection must be 810e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by this operation. Refer to {@link SQLiteConnectionPool}. 8114c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 812e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return The number of rows that were counted during query execution. Might 813e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * not be all rows in the result set unless <code>countAllRows</code> is true. 814e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 815e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if an error occurs, such as a syntax error 816e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or invalid number of bind arguments. 81775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 818e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 819e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public int executeForCursorWindow(String sql, Object[] bindArgs, 820e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown CursorWindow window, int startPos, int requiredPos, boolean countAllRows, 8214c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown int connectionFlags, CancellationSignal cancellationSignal) { 822e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (sql == null) { 823e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("sql must not be null."); 824e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 825e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (window == null) { 826e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("window must not be null."); 827e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 828e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 8294c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (executeSpecial(sql, bindArgs, connectionFlags, cancellationSignal)) { 830e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown window.clear(); 831e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return 0; 832e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 833e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 8344c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown acquireConnection(sql, connectionFlags, cancellationSignal); // might throw 835e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 836e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return mConnection.executeForCursorWindow(sql, bindArgs, 83775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown window, startPos, requiredPos, countAllRows, 8384c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); // might throw 839e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 840a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown releaseConnection(); // might throw 841e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 842e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 843e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 844e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 845e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Performs special reinterpretation of certain SQL statements such as "BEGIN", 846e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * "COMMIT" and "ROLLBACK" to ensure that transaction state invariants are 847e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * maintained. 848e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 849e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This function is mainly used to support legacy apps that perform their 850e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * own transactions by executing raw SQL rather than calling {@link #beginTransaction} 851e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * and the like. 852e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 853e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param sql The SQL statement to execute. 854e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param bindArgs The arguments to bind, or null if none. 855e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param connectionFlags The connection flags to use if a connection must be 856e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * acquired by this operation. Refer to {@link SQLiteConnectionPool}. 8574c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown * @param cancellationSignal A signal to cancel the operation in progress, or null if none. 858e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @return True if the statement was of a special form that was handled here, 859e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * false otherwise. 860e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * 861e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @throws SQLiteException if an error occurs, such as a syntax error 862e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * or invalid number of bind arguments. 86375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown * @throws OperationCanceledException if the operation was canceled. 864e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 86575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown private boolean executeSpecial(String sql, Object[] bindArgs, int connectionFlags, 8664c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 8674c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown if (cancellationSignal != null) { 8684c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal.throwIfCanceled(); 86975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown } 87075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown 871e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final int type = DatabaseUtils.getSqlStatementType(sql); 872e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown switch (type) { 873e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown case DatabaseUtils.STATEMENT_BEGIN: 87475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown beginTransaction(TRANSACTION_MODE_EXCLUSIVE, null, connectionFlags, 8754c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); 876e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return true; 877e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 878e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown case DatabaseUtils.STATEMENT_COMMIT: 879e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown setTransactionSuccessful(); 8804c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown endTransaction(cancellationSignal); 881e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return true; 882e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 883e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown case DatabaseUtils.STATEMENT_ABORT: 8844c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown endTransaction(cancellationSignal); 885e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return true; 886e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 887e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return false; 888e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 889e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 89075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown private void acquireConnection(String sql, int connectionFlags, 8914c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignal) { 892a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown if (mConnection == null) { 893a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown assert mConnectionUseCount == 0; 89475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown mConnection = mConnectionPool.acquireConnection(sql, connectionFlags, 8954c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignal); // might throw 896e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConnectionFlags = connectionFlags; 897e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 898a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown mConnectionUseCount += 1; 899e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 900e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 901a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown private void releaseConnection() { 902a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown assert mConnection != null; 903a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown assert mConnectionUseCount > 0; 904a9be4154e8dac0de3db5ee42e878beb0639e70e6Jeff Brown if (--mConnectionUseCount == 0) { 905e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown try { 906e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConnectionPool.releaseConnection(mConnection); // might throw 907e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } finally { 908e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mConnection = null; 909e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 910e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 911e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 912e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 913e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void throwIfNoTransaction() { 914e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mTransactionStack == null) { 915e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalStateException("Cannot perform this operation because " 916e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "there is no current transaction."); 917e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 918e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 919e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 920e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void throwIfTransactionMarkedSuccessful() { 921e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mTransactionStack != null && mTransactionStack.mMarkedSuccessful) { 922e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalStateException("Cannot perform this operation because " 923e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "the transaction has already been marked successful. The only " 924e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "thing you can do now is call endTransaction()."); 925e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 926e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 927e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 928e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void throwIfNestedTransaction() { 929e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mTransactionStack == null && mTransactionStack.mParent != null) { 930e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalStateException("Cannot perform this operation because " 931e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "a nested transaction is in progress."); 932e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 933e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 934e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 935e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private Transaction obtainTransaction(int mode, SQLiteTransactionListener listener) { 936e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Transaction transaction = mTransactionPool; 937e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (transaction != null) { 938e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mTransactionPool = transaction.mParent; 939e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown transaction.mParent = null; 940e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown transaction.mMarkedSuccessful = false; 941e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown transaction.mChildFailed = false; 942e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 943e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown transaction = new Transaction(); 944e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 945e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown transaction.mMode = mode; 946e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown transaction.mListener = listener; 947e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return transaction; 948e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 949e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 950e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void recycleTransaction(Transaction transaction) { 951e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown transaction.mParent = mTransactionPool; 952e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown transaction.mListener = null; 953e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mTransactionPool = transaction; 954e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 955e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 956e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private static final class Transaction { 957e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public Transaction mParent; 958e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public int mMode; 959e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public SQLiteTransactionListener mListener; 960e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public boolean mMarkedSuccessful; 961e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public boolean mChildFailed; 962e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 963e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} 964