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