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