SQLiteStatement.java revision a006b47298539d89dc7a06b54c070cb3e986352a
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.database.sqlite; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Noriimport android.database.DatabaseUtils; 20a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringertimport android.os.ParcelFileDescriptor; 216a353876178ca2fe4bc61f128130067d2c2574d1Brad Fitzpatrickimport android.os.SystemClock; 22a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringertimport android.util.Log; 23a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert 24a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringertimport java.io.IOException; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26cfda9f3a4756c71b3aadd1387419cb3b513dd400Brad Fitzpatrickimport dalvik.system.BlockGuard; 27cfda9f3a4756c71b3aadd1387419cb3b513dd400Brad Fitzpatrick 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A pre-compiled statement against a {@link SQLiteDatabase} that can be reused. 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The statement cannot return multiple rows, but 1x1 result sets are allowed. 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't use SQLiteStatement constructor directly, please use 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SQLiteDatabase#compileStatement(String)} 33ccd954480c32e9f35357b66023ae912e7f3fa76bVasu Nori *<p> 34f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * SQLiteStatement is not internally synchronized so code using a SQLiteStatement from multiple 35f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * threads should perform its own synchronization when using the SQLiteStatement. 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 372827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori@SuppressWarnings("deprecation") 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SQLiteStatement extends SQLiteProgram 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 40a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert 41a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert private static final String TAG = "SQLiteStatement"; 42a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert 437501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private static final boolean READ = true; 447501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private static final boolean WRITE = false; 457501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 46e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori private SQLiteDatabase mOrigDb; 470732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori private int mState; 480732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori /** possible value for {@link #mState}. indicates that a transaction is started.} */ 49ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori private static final int TRANS_STARTED = 1; 500732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori /** possible value for {@link #mState}. indicates that a lock is acquired.} */ 51ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori private static final int LOCK_ACQUIRED = 2; 52e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't use SQLiteStatement constructor directly, please use 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SQLiteDatabase#compileStatement(String)} 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param db 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sql 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 590732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori /* package */ SQLiteStatement(SQLiteDatabase db, String sql, Object[] bindArgs) { 600732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori super(db, sql, bindArgs, false /* don't compile sql statement */); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 64fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example 65fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * CREATE / DROP table, view, trigger, index etc. 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.SQLException If the SQL string is invalid for 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * some reason 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void execute() { 71fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori executeUpdateDelete(); 72fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori } 73fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori 74fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori /** 75fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * Execute this SQL statement, if the the number of rows affected by exection of this SQL 76fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements. 77fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * 78fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * @return the number of rows affected by this SQL statement execution. 79fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * @throws android.database.SQLException If the SQL string is invalid for 80fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * some reason 81fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori */ 82fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori public int executeUpdateDelete() { 83e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 84e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(WRITE); 85e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 86fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori int numChanges = native_execute(); 87e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 88fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori return numChanges; 89e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 90e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 91e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 965bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * Execute this SQL statement and return the ID of the row inserted due to this call. 975bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * The SQL statement should be an INSERT for this to be a useful call. 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 995bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * @return the row ID of the last row inserted, if this insert is successful. -1 otherwise. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.SQLException If the SQL string is invalid for 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * some reason 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long executeInsert() { 105e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 106e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(WRITE); 107e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 108fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori long lastInsertedRowId = native_executeInsert(); 109e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 110fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori return lastInsertedRowId; 111e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 112e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 113e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a statement that returns a 1 by 1 table with a numeric value. 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For example, SELECT COUNT(*) FROM table; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The result of the query. 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long simpleQueryForLong() { 126e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 127e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(READ); 128e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 129e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long retValue = native_1x1_long(); 130e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 131e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori return retValue; 132e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 133e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 134e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a statement that returns a 1 by 1 table with a text value. 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For example, SELECT COUNT(*) FROM table; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The result of the query. 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String simpleQueryForString() { 147e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 148e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(READ); 149e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 150e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori String retValue = native_1x1_string(); 151e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 152e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori return retValue; 153e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 154e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 155e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 1567501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 1577501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 1587501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 1597501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori /** 160a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * Executes a statement that returns a 1 by 1 table with a blob value. 161a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * 162a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * @return A read-only file descriptor for a copy of the blob value, or {@code null} 163a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * if the value is null or could not be read for some reason. 164a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * 165a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows 166a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert */ 167a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert public ParcelFileDescriptor simpleQueryForBlobFileDescriptor() { 168a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert synchronized(this) { 169a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert long timeStart = acquireAndLock(READ); 170a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert try { 171a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert ParcelFileDescriptor retValue = native_1x1_blob_ashmem(); 172a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert mDatabase.logTimeStat(mSql, timeStart); 173a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert return retValue; 174a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert } catch (IOException ex) { 175a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert Log.e(TAG, "simpleQueryForBlobFileDescriptor() failed", ex); 176a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert return null; 177a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert } finally { 178a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert releaseAndUnlock(); 179a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert } 180a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert } 181a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert } 182a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert 183a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert /** 1847501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * Called before every method in this class before executing a SQL statement, 1857501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * this method does the following: 1867501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <ul> 1877501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>make sure the database is open</li> 188e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori * <li>get a database connection from the connection pool,if possible</li> 1897501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>notifies {@link BlockGuard} of read/write</li> 190ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * <li>if the SQL statement is an update, start transaction if not already in one. 191ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * otherwise, get lock on the database</li> 1927501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>acquire reference on this object</li> 1937501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>and then return the current time _before_ the database lock was acquired</li> 1947501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * </ul> 1957501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <p> 196ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * This method removes the duplicate code from the other public 1977501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * methods in this class. 1987501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori */ 1997501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private long acquireAndLock(boolean rwFlag) { 2000732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori mState = 0; 201e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // use pooled database connection handles for SELECT SQL statements 202e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.verifyDbIsOpen(); 203ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori SQLiteDatabase db = (mStatementType != DatabaseUtils.STATEMENT_SELECT) ? mDatabase 204e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori : mDatabase.getDbConnection(mSql); 205e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // use the database connection obtained above 206e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mOrigDb = mDatabase; 207e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase = db; 208e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori nHandle = mDatabase.mNativeHandle; 2097501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori if (rwFlag == WRITE) { 2107501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori BlockGuard.getThreadPolicy().onWriteToDisk(); 2117501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } else { 2127501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori BlockGuard.getThreadPolicy().onReadFromDisk(); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 214ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori 215ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori /* 216ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * Special case handling of SQLiteDatabase.execSQL("BEGIN transaction"). 217ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * we know it is execSQL("BEGIN transaction") from the caller IF there is no lock held. 218ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * beginTransaction() methods in SQLiteDatabase call lockForced() before 219ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * calling execSQL("BEGIN transaction"). 220ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori */ 221ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori if (mStatementType == DatabaseUtils.STATEMENT_BEGIN) { 222ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori if (!mDatabase.isDbLockedByCurrentThread()) { 223ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori // transaction is NOT started by calling beginTransaction() methods in 224ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori // SQLiteDatabase 225ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.setTransactionUsingExecSqlFlag(); 226ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 227ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } else if (mStatementType == DatabaseUtils.STATEMENT_UPDATE) { 228ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori // got update SQL statement. if there is NO pending transaction, start one 229ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori if (!mDatabase.inTransaction()) { 230ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.beginTransactionNonExclusive(); 2310732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori mState = TRANS_STARTED; 232ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 233ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 234ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori // do I have database lock? if not, grab it. 235ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori if (!mDatabase.isDbLockedByCurrentThread()) { 236ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.lock(); 2370732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori mState = LOCK_ACQUIRED; 238ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 239ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori 2407501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori acquireReference(); 241ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori long startTime = SystemClock.uptimeMillis(); 2427501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori mDatabase.closePendingStatements(); 243e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori compileAndbindAllArgs(); 2447501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori return startTime; 2457501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 2467501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 2477501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori /** 248ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * this method releases locks and references acquired in {@link #acquireAndLock(boolean)} 2497501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori */ 2507501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private void releaseAndUnlock() { 2517501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori releaseReference(); 2520732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori if (mState == TRANS_STARTED) { 253ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori try { 254ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.setTransactionSuccessful(); 255ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } finally { 256ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.endTransaction(); 257ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 2580732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori } else if (mState == LOCK_ACQUIRED) { 259ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.unlock(); 260ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 261ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori if (mStatementType == DatabaseUtils.STATEMENT_COMMIT || 262ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mStatementType == DatabaseUtils.STATEMENT_ABORT) { 263ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.resetTransactionUsingExecSqlFlag(); 264ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 2652827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori clearBindings(); 2662827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori // release the compiled sql statement so that the caller's SQLiteStatement no longer 2672827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori // has a hard reference to a database object that may get deallocated at any point. 2682827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori releaseCompiledSqlIfNotInCache(); 269e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // restore the database connection handle to the original value 270e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase = mOrigDb; 271e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori nHandle = mDatabase.mNativeHandle; 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 274fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori private final native int native_execute(); 275fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori private final native long native_executeInsert(); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final native long native_1x1_long(); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final native String native_1x1_string(); 278a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert private final native ParcelFileDescriptor native_1x1_blob_ashmem() throws IOException; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 280