SQLiteQuery.java revision d24b8183b93e781080b2c16c487e60d51c12da31
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.database.sqlite; 18 19import android.database.CursorWindow; 20import android.os.SystemClock; 21 22/** 23 * A SQLite program that represents a query that reads the resulting rows into a CursorWindow. 24 * This class is used by SQLiteCursor and isn't useful itself. 25 */ 26public class SQLiteQuery extends SQLiteProgram { 27 //private static final String TAG = "Cursor"; 28 29 /** The index of the unbound OFFSET parameter */ 30 private int mOffsetIndex; 31 32 /** The SQL used to create this query */ 33 private String mQuery; 34 35 /** Args to bind on requery */ 36 private String[] mBindArgs; 37 38 private boolean mClosed = false; 39 40 /** 41 * Create a persistent query object. 42 * 43 * @param db The database that this query object is associated with 44 * @param query The SQL string for this query. 45 * @param offsetIndex The 1-based index to the OFFSET parameter, 46 */ 47 /* package */ SQLiteQuery(SQLiteDatabase db, String query, int offsetIndex, String[] bindArgs) { 48 super(db, query); 49 50 mOffsetIndex = offsetIndex; 51 mQuery = query; 52 mBindArgs = bindArgs; 53 } 54 55 /** 56 * Reads rows into a buffer. This method acquires the database lock. 57 * 58 * @param window The window to fill into 59 * @return number of total rows in the query 60 */ 61 /* package */ int fillWindow(CursorWindow window, 62 int maxRead, int lastPos) { 63 mDatabase.lock(); 64 65 boolean logStats = mDatabase.mLogStats; 66 long startTime = logStats ? SystemClock.elapsedRealtime() : 0; 67 try { 68 acquireReference(); 69 try { 70 window.acquireReference(); 71 // if the start pos is not equal to 0, then most likely window is 72 // too small for the data set, loading by another thread 73 // is not safe in this situation. the native code will ignore maxRead 74 int numRows = native_fill_window(window, window.getStartPosition(), mOffsetIndex, 75 maxRead, lastPos); 76 if (logStats) { 77 mDatabase.logTimeStat(true /* read */, startTime, 78 SystemClock.elapsedRealtime()); 79 } 80 return numRows; 81 } catch (IllegalStateException e){ 82 // simply ignore it 83 return 0; 84 } catch (SQLiteDatabaseCorruptException e) { 85 mDatabase.onCorruption(); 86 throw e; 87 } finally { 88 window.releaseReference(); 89 } 90 } finally { 91 releaseReference(); 92 mDatabase.unlock(); 93 } 94 } 95 96 /** 97 * Get the column count for the statement. Only valid on query based 98 * statements. The database must be locked 99 * when calling this method. 100 * 101 * @return The number of column in the statement's result set. 102 */ 103 /* package */ int columnCountLocked() { 104 acquireReference(); 105 try { 106 return native_column_count(); 107 } finally { 108 releaseReference(); 109 } 110 } 111 112 /** 113 * Retrieves the column name for the given column index. The database must be locked 114 * when calling this method. 115 * 116 * @param columnIndex the index of the column to get the name for 117 * @return The requested column's name 118 */ 119 /* package */ String columnNameLocked(int columnIndex) { 120 acquireReference(); 121 try { 122 return native_column_name(columnIndex); 123 } finally { 124 releaseReference(); 125 } 126 } 127 128 /** {@hide pending API Council approval} */ 129 @Override 130 public String toString() { 131 return "SQLiteQuery: " + mQuery; 132 } 133 134 @Override 135 public void close() { 136 super.close(); 137 mClosed = true; 138 } 139 140 /** 141 * Called by SQLiteCursor when it is requeried. 142 */ 143 /* package */ void requery() { 144 if (mBindArgs != null) { 145 int len = mBindArgs.length; 146 try { 147 for (int i = 0; i < len; i++) { 148 super.bindString(i + 1, mBindArgs[i]); 149 } 150 } catch (SQLiteMisuseException e) { 151 StringBuilder errMsg = new StringBuilder("mQuery " + mQuery); 152 for (int i = 0; i < len; i++) { 153 errMsg.append(" "); 154 errMsg.append(mBindArgs[i]); 155 } 156 errMsg.append(" "); 157 IllegalStateException leakProgram = new IllegalStateException( 158 errMsg.toString(), e); 159 throw leakProgram; 160 } 161 } 162 } 163 164 @Override 165 public void bindNull(int index) { 166 mBindArgs[index - 1] = null; 167 if (!mClosed) super.bindNull(index); 168 } 169 170 @Override 171 public void bindLong(int index, long value) { 172 mBindArgs[index - 1] = Long.toString(value); 173 if (!mClosed) super.bindLong(index, value); 174 } 175 176 @Override 177 public void bindDouble(int index, double value) { 178 mBindArgs[index - 1] = Double.toString(value); 179 if (!mClosed) super.bindDouble(index, value); 180 } 181 182 @Override 183 public void bindString(int index, String value) { 184 mBindArgs[index - 1] = value; 185 if (!mClosed) super.bindString(index, value); 186 } 187 188 private final native int native_fill_window(CursorWindow window, 189 int startPos, int offsetParam, int maxRead, int lastPos); 190 191 private final native int native_column_count(); 192 193 private final native String native_column_name(int columnIndex); 194} 195