SQLiteStatement.java revision e25539fdfdf884eee55107efbcc893f44e82e00e
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 /** 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute this SQL statement, if it is not a query. For example, 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CREATE TABLE, DELTE, INSERT, 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() { 58e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 59e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(WRITE); 60e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 61e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori native_execute(); 62e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 63e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 64e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 65e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 705bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * Execute this SQL statement and return the ID of the row inserted due to this call. 715bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * The SQL statement should be an INSERT for this to be a useful call. 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 735bf67247d2e299f0586de65b2d024f1f835657e0Vasu Nori * @return the row ID of the last row inserted, if this insert is successful. -1 otherwise. 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.SQLException If the SQL string is invalid for 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * some reason 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long executeInsert() { 79e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 80e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(WRITE); 81e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 82e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori native_execute(); 83e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 84e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori return (mDatabase.lastChangeCount() > 0) ? mDatabase.lastInsertRow() : -1; 85e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 86e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 87e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a statement that returns a 1 by 1 table with a numeric value. 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For example, SELECT COUNT(*) FROM table; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The result of the query. 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long simpleQueryForLong() { 100e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 101e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(READ); 102e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 103e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long retValue = native_1x1_long(); 104e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 105e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori return retValue; 106e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 107e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 108e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Execute a statement that returns a 1 by 1 table with a text value. 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For example, SELECT COUNT(*) FROM table; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The result of the query. 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String simpleQueryForString() { 121e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori synchronized(this) { 122e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori long timeStart = acquireAndLock(READ); 123e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori try { 124e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori String retValue = native_1x1_string(); 125e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.logTimeStat(mSql, timeStart); 126e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori return retValue; 127e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } finally { 128e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori releaseAndUnlock(); 129e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 1307501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 1317501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 1327501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 1337501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori /** 1347501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * Called before every method in this class before executing a SQL statement, 1357501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * this method does the following: 1367501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <ul> 1377501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>make sure the database is open</li> 138e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori * <li>get a database connection from the connection pool,if possible</li> 1397501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>notifies {@link BlockGuard} of read/write</li> 1407501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>get lock on the database</li> 1417501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>acquire reference on this object</li> 1427501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <li>and then return the current time _before_ the database lock was acquired</li> 1437501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * </ul> 1447501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * <p> 1457501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * This method removes the duplcate code from the other public 1467501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * methods in this class. 1477501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori */ 1487501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private long acquireAndLock(boolean rwFlag) { 149e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // use pooled database connection handles for SELECT SQL statements 150e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase.verifyDbIsOpen(); 151e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori SQLiteDatabase db = (getSqlStatementType(mSql) != SELECT_STMT) ? mDatabase 152e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori : mDatabase.getDbConnection(mSql); 153e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // use the database connection obtained above 154e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mOrigDb = mDatabase; 155e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase = db; 156e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori nHandle = mDatabase.mNativeHandle; 1577501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori if (rwFlag == WRITE) { 1587501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori BlockGuard.getThreadPolicy().onWriteToDisk(); 1597501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } else { 1607501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori BlockGuard.getThreadPolicy().onReadFromDisk(); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1627501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori long startTime = SystemClock.uptimeMillis(); 1637501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori mDatabase.lock(); 1647501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori acquireReference(); 1657501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori mDatabase.closePendingStatements(); 166e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori compileAndbindAllArgs(); 1677501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori return startTime; 1687501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori } 1697501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 1707501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori /** 1717501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori * this method releases locks and references acquired in {@link #acquireAndLock(boolean)}. 1727501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori */ 1737501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori private void releaseAndUnlock() { 1747501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori releaseReference(); 1757501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori mDatabase.unlock(); 1762827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori clearBindings(); 1772827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori // release the compiled sql statement so that the caller's SQLiteStatement no longer 1782827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori // has a hard reference to a database object that may get deallocated at any point. 1792827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori releaseCompiledSqlIfNotInCache(); 180e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori // restore the database connection handle to the original value 181e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori mDatabase = mOrigDb; 182e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori nHandle = mDatabase.mNativeHandle; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final native void native_execute(); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final native long native_1x1_long(); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final native String native_1x1_string(); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 189