SQLiteStatement.java revision fb16cbd9b2e86d6878d4bff820422bc09c8938de
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 196a353876178ca2fe4bc61f128130067d2c2574d1Brad Fitzpatrickimport android.os.SystemClock; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21cfda9f3a4756c71b3aadd1387419cb3b513dd400Brad Fitzpatrickimport dalvik.system.BlockGuard; 22cfda9f3a4756c71b3aadd1387419cb3b513dd400Brad Fitzpatrick 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A pre-compiled statement against a {@link SQLiteDatabase} that can be reused. 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The statement cannot return multiple rows, but 1x1 result sets are allowed. 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't use SQLiteStatement constructor directly, please use 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SQLiteDatabase#compileStatement(String)} 28ccd954480c32e9f35357b66023ae912e7f3fa76bVasu Nori *<p> 29f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * SQLiteStatement is not internally synchronized so code using a SQLiteStatement from multiple 30f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * threads should perform its own synchronization when using the SQLiteStatement. 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 322827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori@SuppressWarnings("deprecation") 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SQLiteStatement extends SQLiteProgram 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 357501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private static final boolean READ = true; 367501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private static final boolean WRITE = false; 377501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 38e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori private SQLiteDatabase mOrigDb; 39e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't use SQLiteStatement constructor directly, please use 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SQLiteDatabase#compileStatement(String)} 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param db 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sql 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* package */ SQLiteStatement(SQLiteDatabase db, String sql) { 472827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori super(db, sql, false /* don't compile sql statement */); 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 51fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example 52fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * CREATE / DROP table, view, trigger, index etc. 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.SQLException If the SQL string is invalid for 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * some reason 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void execute() { 58fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori executeUpdateDelete(); 59fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori } 60fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori 61fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori /** 62fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * Execute this SQL statement, if the the number of rows affected by exection of this SQL 63fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements. 64fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * 65fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * @return the number of rows affected by this SQL statement execution. 66fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * @throws android.database.SQLException If the SQL string is invalid for 67fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori * some reason 68fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori */ 69fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori public int executeUpdateDelete() { 70e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 71e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(WRITE); 72e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 73fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori int numChanges = native_execute(); 74e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 75fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori return numChanges; 76e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 77e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 78e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 835bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * Execute this SQL statement and return the ID of the row inserted due to this call. 845bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * The SQL statement should be an INSERT for this to be a useful call. 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 865bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * @return the row ID of the last row inserted, if this insert is successful. -1 otherwise. 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.SQLException If the SQL string is invalid for 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * some reason 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long executeInsert() { 92e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 93e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(WRITE); 94e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 95fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori long lastInsertedRowId = native_executeInsert(); 96e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 97fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori return lastInsertedRowId; 98e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 99e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 100e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a statement that returns a 1 by 1 table with a numeric value. 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For example, SELECT COUNT(*) FROM table; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The result of the query. 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long simpleQueryForLong() { 113e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 114e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(READ); 115e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 116e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long retValue = native_1x1_long(); 117e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 118e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori return retValue; 119e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 120e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 121e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a statement that returns a 1 by 1 table with a text value. 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For example, SELECT COUNT(*) FROM table; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The result of the query. 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String simpleQueryForString() { 134e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 135e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(READ); 136e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 137e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori String retValue = native_1x1_string(); 138e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 139e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori return retValue; 140e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 141e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 142e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 1437501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 1447501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 1457501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 1467501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori /** 1477501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * Called before every method in this class before executing a SQL statement, 1487501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * this method does the following: 1497501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <ul> 1507501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>make sure the database is open</li> 151e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori * <li>get a database connection from the connection pool,if possible</li> 1527501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>notifies {@link BlockGuard} of read/write</li> 1537501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>get lock on the database</li> 1547501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>acquire reference on this object</li> 1557501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>and then return the current time _before_ the database lock was acquired</li> 1567501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * </ul> 1577501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <p> 1587501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * This method removes the duplcate code from the other public 1597501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * methods in this class. 1607501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori */ 1617501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private long acquireAndLock(boolean rwFlag) { 162e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // use pooled database connection handles for SELECT SQL statements 163e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.verifyDbIsOpen(); 164e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori SQLiteDatabase db = (getSqlStatementType(mSql) != SELECT_STMT) ? mDatabase 165e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori : mDatabase.getDbConnection(mSql); 166e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // use the database connection obtained above 167e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mOrigDb = mDatabase; 168e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase = db; 169e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori nHandle = mDatabase.mNativeHandle; 1707501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori if (rwFlag == WRITE) { 1717501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori BlockGuard.getThreadPolicy().onWriteToDisk(); 1727501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } else { 1737501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori BlockGuard.getThreadPolicy().onReadFromDisk(); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1757501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori long startTime = SystemClock.uptimeMillis(); 1767501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori mDatabase.lock(); 1777501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori acquireReference(); 1787501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori mDatabase.closePendingStatements(); 179e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori compileAndbindAllArgs(); 1807501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori return startTime; 1817501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 1827501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 1837501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori /** 1847501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * this method releases locks and references acquired in {@link #acquireAndLock(boolean)}. 1857501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori */ 1867501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private void releaseAndUnlock() { 1877501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori releaseReference(); 1887501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori mDatabase.unlock(); 1892827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori clearBindings(); 1902827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori // release the compiled sql statement so that the caller's SQLiteStatement no longer 1912827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori // has a hard reference to a database object that may get deallocated at any point. 1922827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori releaseCompiledSqlIfNotInCache(); 193e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // restore the database connection handle to the original value 194e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase = mOrigDb; 195e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori nHandle = mDatabase.mNativeHandle; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 198fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori private final native int native_execute(); 199fb16cbd9b2e86d6878d4bff820422bc09c8938deVasu Nori private final native long native_executeInsert(); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final native long native_1x1_long(); 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final native String native_1x1_string(); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 203