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> 342467561ac2c7de870417e0405a138c857c9d5629Vasu Nori * 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 private static final String TAG = "SQLiteStatement"; 41a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert 427501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private static final boolean READ = true; 437501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private static final boolean WRITE = false; 447501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 45e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori private SQLiteDatabase mOrigDb; 460732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori private int mState; 47d31211fd46e342cc1b762d2009149e12f48e4153Vasu Nori /** possible value for {@link #mState}. indicates that a transaction is started. */ 48ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori private static final int TRANS_STARTED = 1; 49d31211fd46e342cc1b762d2009149e12f48e4153Vasu Nori /** possible value for {@link #mState}. indicates that a lock is acquired. */ 50ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori private static final int LOCK_ACQUIRED = 2; 51e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't use SQLiteStatement constructor directly, please use 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SQLiteDatabase#compileStatement(String)} 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param db 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sql 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 580732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori /* package */ SQLiteStatement(SQLiteDatabase db, String sql, Object[] bindArgs) { 590732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori super(db, sql, bindArgs, false /* don't compile sql statement */); 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 63fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example 64fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * CREATE / DROP table, view, trigger, index etc. 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.SQLException If the SQL string is invalid for 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * some reason 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void execute() { 70fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori executeUpdateDelete(); 71fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori } 72fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori 73fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori /** 744e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori * Execute this SQL statement, if the the number of rows affected by execution of this SQL 75fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements. 76fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * 77fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * @return the number of rows affected by this SQL statement execution. 78fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * @throws android.database.SQLException If the SQL string is invalid for 79fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * some reason 80fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori */ 81fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori public int executeUpdateDelete() { 822467561ac2c7de870417e0405a138c857c9d5629Vasu Nori try { 8316057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori saveSqlAsLastSqlStatement(); 8416057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori acquireAndLock(WRITE); 852467561ac2c7de870417e0405a138c857c9d5629Vasu Nori int numChanges = 0; 862467561ac2c7de870417e0405a138c857c9d5629Vasu Nori if ((mStatementType & STATEMENT_DONT_PREPARE) > 0) { 872467561ac2c7de870417e0405a138c857c9d5629Vasu Nori // since the statement doesn't have to be prepared, 882467561ac2c7de870417e0405a138c857c9d5629Vasu Nori // call the following native method which will not prepare 892467561ac2c7de870417e0405a138c857c9d5629Vasu Nori // the query plan 902467561ac2c7de870417e0405a138c857c9d5629Vasu Nori native_executeSql(mSql); 912467561ac2c7de870417e0405a138c857c9d5629Vasu Nori } else { 922467561ac2c7de870417e0405a138c857c9d5629Vasu Nori numChanges = native_execute(); 93e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 942467561ac2c7de870417e0405a138c857c9d5629Vasu Nori return numChanges; 952467561ac2c7de870417e0405a138c857c9d5629Vasu Nori } finally { 962467561ac2c7de870417e0405a138c857c9d5629Vasu Nori releaseAndUnlock(); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1015bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * Execute this SQL statement and return the ID of the row inserted due to this call. 1025bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * The SQL statement should be an INSERT for this to be a useful call. 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1045bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * @return the row ID of the last row inserted, if this insert is successful. -1 otherwise. 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.SQLException If the SQL string is invalid for 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * some reason 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long executeInsert() { 1102467561ac2c7de870417e0405a138c857c9d5629Vasu Nori try { 11116057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori saveSqlAsLastSqlStatement(); 11216057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori acquireAndLock(WRITE); 11316057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori return native_executeInsert(); 1142467561ac2c7de870417e0405a138c857c9d5629Vasu Nori } finally { 1152467561ac2c7de870417e0405a138c857c9d5629Vasu Nori releaseAndUnlock(); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11916057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori private void saveSqlAsLastSqlStatement() { 12016057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori if (((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == 12116057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori DatabaseUtils.STATEMENT_UPDATE) || 12216057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori (mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == 12316057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori DatabaseUtils.STATEMENT_BEGIN) { 12416057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori mDatabase.setLastSqlStatement(mSql); 12516057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori } 12616057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a statement that returns a 1 by 1 table with a numeric value. 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For example, SELECT COUNT(*) FROM table; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The result of the query. 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long simpleQueryForLong() { 1362467561ac2c7de870417e0405a138c857c9d5629Vasu Nori try { 1372467561ac2c7de870417e0405a138c857c9d5629Vasu Nori long timeStart = acquireAndLock(READ); 1382467561ac2c7de870417e0405a138c857c9d5629Vasu Nori long retValue = native_1x1_long(); 1392467561ac2c7de870417e0405a138c857c9d5629Vasu Nori mDatabase.logTimeStat(mSql, timeStart); 1402467561ac2c7de870417e0405a138c857c9d5629Vasu Nori return retValue; 1413045bbaf58574ad3168466b198b835b29d174c18Vasu Nori } catch (SQLiteDoneException e) { 1423045bbaf58574ad3168466b198b835b29d174c18Vasu Nori throw new SQLiteDoneException( 1433045bbaf58574ad3168466b198b835b29d174c18Vasu Nori "expected 1 row from this query but query returned no data. check the query: " + 1443045bbaf58574ad3168466b198b835b29d174c18Vasu Nori mSql); 1452467561ac2c7de870417e0405a138c857c9d5629Vasu Nori } finally { 1462467561ac2c7de870417e0405a138c857c9d5629Vasu Nori releaseAndUnlock(); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a statement that returns a 1 by 1 table with a text value. 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For example, SELECT COUNT(*) FROM table; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The result of the query. 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String simpleQueryForString() { 1592467561ac2c7de870417e0405a138c857c9d5629Vasu Nori try { 1602467561ac2c7de870417e0405a138c857c9d5629Vasu Nori long timeStart = acquireAndLock(READ); 1612467561ac2c7de870417e0405a138c857c9d5629Vasu Nori String retValue = native_1x1_string(); 1622467561ac2c7de870417e0405a138c857c9d5629Vasu Nori mDatabase.logTimeStat(mSql, timeStart); 1632467561ac2c7de870417e0405a138c857c9d5629Vasu Nori return retValue; 1643045bbaf58574ad3168466b198b835b29d174c18Vasu Nori } catch (SQLiteDoneException e) { 1653045bbaf58574ad3168466b198b835b29d174c18Vasu Nori throw new SQLiteDoneException( 1663045bbaf58574ad3168466b198b835b29d174c18Vasu Nori "expected 1 row from this query but query returned no data. check the query: " + 1673045bbaf58574ad3168466b198b835b29d174c18Vasu Nori mSql); 1682467561ac2c7de870417e0405a138c857c9d5629Vasu Nori } finally { 1692467561ac2c7de870417e0405a138c857c9d5629Vasu Nori releaseAndUnlock(); 1707501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 1717501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 1727501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 1737501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori /** 174a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * Executes a statement that returns a 1 by 1 table with a blob value. 175a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * 176a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * @return A read-only file descriptor for a copy of the blob value, or {@code null} 177a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * if the value is null or could not be read for some reason. 178a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * 179a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows 180a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert */ 181a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert public ParcelFileDescriptor simpleQueryForBlobFileDescriptor() { 1822467561ac2c7de870417e0405a138c857c9d5629Vasu Nori try { 1832467561ac2c7de870417e0405a138c857c9d5629Vasu Nori long timeStart = acquireAndLock(READ); 1842467561ac2c7de870417e0405a138c857c9d5629Vasu Nori ParcelFileDescriptor retValue = native_1x1_blob_ashmem(); 1852467561ac2c7de870417e0405a138c857c9d5629Vasu Nori mDatabase.logTimeStat(mSql, timeStart); 1862467561ac2c7de870417e0405a138c857c9d5629Vasu Nori return retValue; 1872467561ac2c7de870417e0405a138c857c9d5629Vasu Nori } catch (IOException ex) { 1882467561ac2c7de870417e0405a138c857c9d5629Vasu Nori Log.e(TAG, "simpleQueryForBlobFileDescriptor() failed", ex); 1892467561ac2c7de870417e0405a138c857c9d5629Vasu Nori return null; 1903045bbaf58574ad3168466b198b835b29d174c18Vasu Nori } catch (SQLiteDoneException e) { 1913045bbaf58574ad3168466b198b835b29d174c18Vasu Nori throw new SQLiteDoneException( 1923045bbaf58574ad3168466b198b835b29d174c18Vasu Nori "expected 1 row from this query but query returned no data. check the query: " + 1933045bbaf58574ad3168466b198b835b29d174c18Vasu Nori mSql); 1942467561ac2c7de870417e0405a138c857c9d5629Vasu Nori } finally { 1952467561ac2c7de870417e0405a138c857c9d5629Vasu Nori releaseAndUnlock(); 196a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert } 197a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert } 198a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert 199a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert /** 2007501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * Called before every method in this class before executing a SQL statement, 2017501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * this method does the following: 2027501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <ul> 2037501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>make sure the database is open</li> 204e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori * <li>get a database connection from the connection pool,if possible</li> 2057501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>notifies {@link BlockGuard} of read/write</li> 206ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * <li>if the SQL statement is an update, start transaction if not already in one. 207ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * otherwise, get lock on the database</li> 2087501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>acquire reference on this object</li> 20916057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori * <li>and then return the current time _after_ the database lock was acquired</li> 2107501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * </ul> 2117501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <p> 212ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * This method removes the duplicate code from the other public 2137501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * methods in this class. 2147501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori */ 2157501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private long acquireAndLock(boolean rwFlag) { 2160732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori mState = 0; 217e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // use pooled database connection handles for SELECT SQL statements 218e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.verifyDbIsOpen(); 2194e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori SQLiteDatabase db = ((mStatementType & SQLiteProgram.STATEMENT_USE_POOLED_CONN) > 0) 2204e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori ? mDatabase.getDbConnection(mSql) : mDatabase; 221e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // use the database connection obtained above 222e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mOrigDb = mDatabase; 223e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase = db; 224196663234ab1b67fdd88060701e8211f67fd7854Vasu Nori setNativeHandle(mDatabase.mNativeHandle); 2257501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori if (rwFlag == WRITE) { 2267501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori BlockGuard.getThreadPolicy().onWriteToDisk(); 2277501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } else { 2287501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori BlockGuard.getThreadPolicy().onReadFromDisk(); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 230ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori 231ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori /* 232ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * Special case handling of SQLiteDatabase.execSQL("BEGIN transaction"). 233ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * we know it is execSQL("BEGIN transaction") from the caller IF there is no lock held. 234ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * beginTransaction() methods in SQLiteDatabase call lockForced() before 235ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * calling execSQL("BEGIN transaction"). 236ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori */ 2374e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori if ((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == DatabaseUtils.STATEMENT_BEGIN) { 238ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori if (!mDatabase.isDbLockedByCurrentThread()) { 239ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori // transaction is NOT started by calling beginTransaction() methods in 240ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori // SQLiteDatabase 241ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.setTransactionUsingExecSqlFlag(); 242ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 2434e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori } else if ((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == 2444e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori DatabaseUtils.STATEMENT_UPDATE) { 245ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori // got update SQL statement. if there is NO pending transaction, start one 246ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori if (!mDatabase.inTransaction()) { 247ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.beginTransactionNonExclusive(); 2480732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori mState = TRANS_STARTED; 249ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 250ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 251ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori // do I have database lock? if not, grab it. 252ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori if (!mDatabase.isDbLockedByCurrentThread()) { 25316057fad00d47e920fc20721b70c7cafb765f7f8Vasu Nori mDatabase.lock(mSql); 2540732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori mState = LOCK_ACQUIRED; 255ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 256ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori 2577501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori acquireReference(); 258ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori long startTime = SystemClock.uptimeMillis(); 2597501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori mDatabase.closePendingStatements(); 260e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori compileAndbindAllArgs(); 2617501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori return startTime; 2627501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 2637501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 2647501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori /** 265ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori * this method releases locks and references acquired in {@link #acquireAndLock(boolean)} 2667501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori */ 2677501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private void releaseAndUnlock() { 2687501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori releaseReference(); 2690732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori if (mState == TRANS_STARTED) { 270ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori try { 271ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.setTransactionSuccessful(); 272ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } finally { 273ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.endTransaction(); 274ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 2750732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori } else if (mState == LOCK_ACQUIRED) { 276ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.unlock(); 277ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 2784e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori if ((mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == 2794e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori DatabaseUtils.STATEMENT_COMMIT || 2804e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori (mStatementType & SQLiteProgram.STATEMENT_TYPE_MASK) == 2814e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori DatabaseUtils.STATEMENT_ABORT) { 282ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori mDatabase.resetTransactionUsingExecSqlFlag(); 283ce38b98feb1e7c9c1799eb270c40798d833aa9aeVasu Nori } 2842827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori clearBindings(); 2852827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori // release the compiled sql statement so that the caller's SQLiteStatement no longer 2862827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori // has a hard reference to a database object that may get deallocated at any point. 287cc6f54910d2431e31af176163f61b34d50a33647Vasu Nori release(); 288e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // restore the database connection handle to the original value 289e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase = mOrigDb; 290196663234ab1b67fdd88060701e8211f67fd7854Vasu Nori setNativeHandle(mDatabase.mNativeHandle); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 293fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori private final native int native_execute(); 294fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori private final native long native_executeInsert(); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final native long native_1x1_long(); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final native String native_1x1_string(); 297a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert private final native ParcelFileDescriptor native_1x1_blob_ashmem() throws IOException; 2984e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori private final native void native_executeSql(String sql); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 300