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; 20a7771df3696954f0e279407e8894a916a7cb26ccJeff Brownimport android.os.CancellationSignal; 21e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori 22e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownimport java.util.Arrays; 233695709457c66354261502b8bf23d59604a59ce4Vasu Nori 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A base class for compiled SQLite programs. 26e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * <p> 27e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * This class is not thread-safe. 28e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * </p> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class SQLiteProgram extends SQLiteClosable { 31e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private static final String[] EMPTY_STRING_ARRAY = new String[0]; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final SQLiteDatabase mDatabase; 34e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final String mSql; 35e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final boolean mReadOnly; 36e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final String[] mColumnNames; 37e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final int mNumParameters; 38e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private final Object[] mBindArgs; 393695709457c66354261502b8bf23d59604a59ce4Vasu Nori 4075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown SQLiteProgram(SQLiteDatabase db, String sql, Object[] bindArgs, 414c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown CancellationSignal cancellationSignalForPrepare) { 42e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mDatabase = db; 43d606b4bf2c1a2308b40785860853cfb95a77bf58Vasu Nori mSql = sql.trim(); 44e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 454e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori int n = DatabaseUtils.getSqlStatementType(mSql); 464e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori switch (n) { 474e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori case DatabaseUtils.STATEMENT_BEGIN: 484e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori case DatabaseUtils.STATEMENT_COMMIT: 494e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori case DatabaseUtils.STATEMENT_ABORT: 50e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mReadOnly = false; 51e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mColumnNames = EMPTY_STRING_ARRAY; 52e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mNumParameters = 0; 534e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori break; 54e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 554e874edf69ce9900eb847629dc4d3616972a3468Vasu Nori default: 56e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown boolean assumeReadOnly = (n == DatabaseUtils.STATEMENT_SELECT); 57e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown SQLiteStatementInfo info = new SQLiteStatementInfo(); 58e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown db.getThreadSession().prepare(mSql, 5975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown db.getThreadDefaultConnectionFlags(assumeReadOnly), 604c1241df8f8b7fd5ec3dff6c7e0f66271248e76eJeff Brown cancellationSignalForPrepare, info); 61e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mReadOnly = info.readOnly; 62e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mColumnNames = info.columnNames; 63e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mNumParameters = info.numParameters; 64e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown break; 652827d6d974beabb12344040a002dcb52dd7106b5Vasu Nori } 667501010b71d57264a06f82937f5fb29cb9f4b509Vasu Nori 67b2679481b57d87945df02983f95ff8e6c9ba5928Jeff Brown if (bindArgs != null && bindArgs.length > mNumParameters) { 68b2679481b57d87945df02983f95ff8e6c9ba5928Jeff Brown throw new IllegalArgumentException("Too many bind arguments. " 69b2679481b57d87945df02983f95ff8e6c9ba5928Jeff Brown + bindArgs.length + " arguments were provided but the statement needs " 70b2679481b57d87945df02983f95ff8e6c9ba5928Jeff Brown + mNumParameters + " arguments."); 71b2679481b57d87945df02983f95ff8e6c9ba5928Jeff Brown } 72b2679481b57d87945df02983f95ff8e6c9ba5928Jeff Brown 73e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mNumParameters != 0) { 74e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mBindArgs = new Object[mNumParameters]; 75b2679481b57d87945df02983f95ff8e6c9ba5928Jeff Brown if (bindArgs != null) { 76b2679481b57d87945df02983f95ff8e6c9ba5928Jeff Brown System.arraycopy(bindArgs, 0, mBindArgs, 0, bindArgs.length); 77b2679481b57d87945df02983f95ff8e6c9ba5928Jeff Brown } 78e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } else { 79e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mBindArgs = null; 80b729dcc8a94bc2c2a1ecda47d791be0d6f1d160aVasu Nori } 81b729dcc8a94bc2c2a1ecda47d791be0d6f1d160aVasu Nori } 82b729dcc8a94bc2c2a1ecda47d791be0d6f1d160aVasu Nori 83e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final SQLiteDatabase getDatabase() { 84e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return mDatabase; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 865a03f36ef845f73eb4473193dbb0f93dd12a51afVasu Nori 87e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final String getSql() { 88e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return mSql; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 91e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final Object[] getBindArgs() { 92e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return mBindArgs; 93e495d1f74af13aec8d5d825e93e4cfe1e4fe7468Vasu Nori } 94e495d1f74af13aec8d5d825e93e4cfe1e4fe7468Vasu Nori 95e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown final String[] getColumnNames() { 96e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return mColumnNames; 9759d60420ba9246eee152852b6a597a0aba7f704dVasu Nori } 9859d60420ba9246eee152852b6a597a0aba7f704dVasu Nori 99e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** @hide */ 100e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown protected final SQLiteSession getSession() { 101e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return mDatabase.getThreadSession(); 1025a03f36ef845f73eb4473193dbb0f93dd12a51afVasu Nori } 1035a03f36ef845f73eb4473193dbb0f93dd12a51afVasu Nori 104e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** @hide */ 105e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown protected final int getConnectionFlags() { 106e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return mDatabase.getThreadDefaultConnectionFlags(mReadOnly); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 109e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** @hide */ 110e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown protected final void onCorruption() { 111e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mDatabase.onCorruption(); 112e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 113e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown 114e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown /** 115e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Unimplemented. 116e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @deprecated This method is deprecated and must not be used. 117e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */ 118e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown @Deprecated 119e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown public final int getUniqueId() { 120e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown return -1; 1210732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori } 1220732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bind a NULL value to this statement. The value remains bound until 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #clearBindings} is called. 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index The 1-based index to the parameter to bind null to 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void bindNull(int index) { 130e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown bind(index, null); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bind a long value to this statement. The value remains bound until 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #clearBindings} is called. 1360732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori *addToBindArgs 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index The 1-based index to the parameter to bind 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The value to bind 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void bindLong(int index, long value) { 141e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown bind(index, value); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bind a double value to this statement. The value remains bound until 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #clearBindings} is called. 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index The 1-based index to the parameter to bind 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value The value to bind 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void bindDouble(int index, double value) { 152e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown bind(index, value); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bind a String value to this statement. The value remains bound until 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #clearBindings} is called. 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index The 1-based index to the parameter to bind 160e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param value The value to bind, must not be null 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void bindString(int index, String value) { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value == null) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("the bind value at index " + index + " is null"); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 166e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown bind(index, value); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Bind a byte array value to this statement. The value remains bound until 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #clearBindings} is called. 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index The 1-based index to the parameter to bind 174e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param value The value to bind, must not be null 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void bindBlob(int index, byte[] value) { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value == null) { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("the bind value at index " + index + " is null"); 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 180e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown bind(index, value); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Clears all existing bindings. Unset bindings are treated as NULL. 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearBindings() { 187e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (mBindArgs != null) { 188e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown Arrays.fill(mBindArgs, null); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1930732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori * Given an array of String bindArgs, this method binds all of them in one single call. 1940732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori * 195e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * @param bindArgs the String array of bind args, none of which must be null. 1960732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori */ 1970732f7912ccec9a1cc379b535ac0b56ae50972b3Vasu Nori public void bindAllArgsAsStrings(String[] bindArgs) { 198e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (bindArgs != null) { 199e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown for (int i = bindArgs.length; i != 0; i--) { 200e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown bindString(i, bindArgs[i - 1]); 201e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 202e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 203e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori } 204e25539fdfdf884eee55107efbcc893f44e82e00eVasu Nori 205e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown @Override 206e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown protected void onAllReferencesReleased() { 207e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown clearBindings(); 208196663234ab1b67fdd88060701e8211f67fd7854Vasu Nori } 209196663234ab1b67fdd88060701e8211f67fd7854Vasu Nori 210e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown private void bind(int index, Object value) { 211e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown if (index < 1 || index > mNumParameters) { 212e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown throw new IllegalArgumentException("Cannot bind argument at index " 213e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + index + " because the index is out of range. " 214e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown + "The statement has " + mNumParameters + " parameters."); 215e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 216e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown mBindArgs[index - 1] = value; 217e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown } 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 219