The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 | |
| 17 | package android.database.sqlite; |
| 18 | |
| 19 | import android.database.AbstractWindowedCursor; |
| 20 | import android.database.CursorWindow; |
Jeff Brown | 650de3d | 2011-10-27 14:52:28 -0700 | [diff] [blame] | 21 | import android.database.DatabaseUtils; |
Brad Fitzpatrick | 32e60c7 | 2010-09-30 16:22:36 -0700 | [diff] [blame] | 22 | import android.os.StrictMode; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 23 | import android.util.Log; |
| 24 | |
| 25 | import java.util.HashMap; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 26 | import java.util.Map; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 27 | |
| 28 | /** |
| 29 | * A Cursor implementation that exposes results from a query on a |
| 30 | * {@link SQLiteDatabase}. |
Jeff Hamilton | f3ca9a5 | 2010-05-12 15:04:33 -0700 | [diff] [blame] | 31 | * |
| 32 | * SQLiteCursor is not internally synchronized so code using a SQLiteCursor from multiple |
| 33 | * threads should perform its own synchronization when using the SQLiteCursor. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 34 | */ |
| 35 | public class SQLiteCursor extends AbstractWindowedCursor { |
Vasu Nori | 071df26 | 2010-09-14 16:02:02 -0700 | [diff] [blame] | 36 | static final String TAG = "SQLiteCursor"; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 37 | static final int NO_COUNT = -1; |
| 38 | |
| 39 | /** The name of the table to edit */ |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 40 | private final String mEditTable; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 41 | |
| 42 | /** The names of the columns in the rows */ |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 43 | private final String[] mColumns; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 44 | |
| 45 | /** The query object for the cursor */ |
| 46 | private SQLiteQuery mQuery; |
| 47 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 48 | /** The compiled query this cursor came from */ |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 49 | private final SQLiteCursorDriver mDriver; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 50 | |
| 51 | /** The number of rows in the cursor */ |
Jeff Brown | 650de3d | 2011-10-27 14:52:28 -0700 | [diff] [blame] | 52 | private int mCount = NO_COUNT; |
| 53 | |
| 54 | /** The number of rows that can fit in the cursor window, 0 if unknown */ |
| 55 | private int mCursorWindowCapacity; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 56 | |
| 57 | /** A mapping of column names to column indices, to speed up lookups */ |
| 58 | private Map<String, Integer> mColumnNameMap; |
| 59 | |
Vasu Nori | d606b4b | 2010-02-24 12:54:20 -0800 | [diff] [blame] | 60 | /** Used to find out where a cursor was allocated in case it never got released. */ |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 61 | private final Throwable mStackTrace; |
Makoto Onuki | 2589716 | 2010-04-29 11:26:20 -0700 | [diff] [blame] | 62 | |
| 63 | /** |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 64 | * Execute a query and provide access to its result set through a Cursor |
| 65 | * interface. For a query such as: {@code SELECT name, birth, phone FROM |
| 66 | * myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth, |
| 67 | * phone) would be in the projection argument and everything from |
| 68 | * {@code FROM} onward would be in the params argument. This constructor |
| 69 | * has package scope. |
| 70 | * |
| 71 | * @param db a reference to a Database object that is already constructed |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 72 | * and opened. This param is not used any longer |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 73 | * @param editTable the name of the table used for this query |
| 74 | * @param query the rest of the query terms |
| 75 | * cursor is finalized |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 76 | * @deprecated use {@link #SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)} instead |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 77 | */ |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 78 | @Deprecated |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 79 | public SQLiteCursor(SQLiteDatabase db, SQLiteCursorDriver driver, |
| 80 | String editTable, SQLiteQuery query) { |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 81 | this(driver, editTable, query); |
| 82 | } |
| 83 | |
| 84 | /** |
| 85 | * Execute a query and provide access to its result set through a Cursor |
| 86 | * interface. For a query such as: {@code SELECT name, birth, phone FROM |
| 87 | * myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth, |
| 88 | * phone) would be in the projection argument and everything from |
| 89 | * {@code FROM} onward would be in the params argument. This constructor |
| 90 | * has package scope. |
| 91 | * |
| 92 | * @param editTable the name of the table used for this query |
| 93 | * @param query the {@link SQLiteQuery} object associated with this cursor object. |
| 94 | */ |
| 95 | public SQLiteCursor(SQLiteCursorDriver driver, String editTable, SQLiteQuery query) { |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 96 | if (query == null) { |
| 97 | throw new IllegalArgumentException("query object cannot be null"); |
| 98 | } |
| 99 | if (query.mDatabase == null) { |
| 100 | throw new IllegalArgumentException("query.mDatabase cannot be null"); |
| 101 | } |
Jeff Sharkey | 7978a41 | 2011-10-25 17:09:09 -0700 | [diff] [blame] | 102 | if (StrictMode.vmSqliteObjectLeaksEnabled()) { |
| 103 | mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace(); |
| 104 | } else { |
| 105 | mStackTrace = null; |
| 106 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 107 | mDriver = driver; |
| 108 | mEditTable = editTable; |
| 109 | mColumnNameMap = null; |
| 110 | mQuery = query; |
| 111 | |
Vasu Nori | 16057fa | 2011-03-18 11:40:37 -0700 | [diff] [blame] | 112 | query.mDatabase.lock(query.mSql); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 113 | try { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 114 | // Setup the list of columns |
| 115 | int columnCount = mQuery.columnCountLocked(); |
| 116 | mColumns = new String[columnCount]; |
| 117 | |
| 118 | // Read in all column names |
| 119 | for (int i = 0; i < columnCount; i++) { |
| 120 | String columnName = mQuery.columnNameLocked(i); |
| 121 | mColumns[i] = columnName; |
Joe Onorato | 43a1765 | 2011-04-06 19:22:23 -0700 | [diff] [blame] | 122 | if (false) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 123 | Log.v("DatabaseWindow", "mColumns[" + i + "] is " |
| 124 | + mColumns[i]); |
| 125 | } |
| 126 | |
| 127 | // Make note of the row ID column index for quick access to it |
| 128 | if ("_id".equals(columnName)) { |
| 129 | mRowIdColumnIndex = i; |
| 130 | } |
| 131 | } |
| 132 | } finally { |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 133 | query.mDatabase.unlock(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 134 | } |
| 135 | } |
| 136 | |
| 137 | /** |
| 138 | * @return the SQLiteDatabase that this cursor is associated with. |
| 139 | */ |
| 140 | public SQLiteDatabase getDatabase() { |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 141 | synchronized (this) { |
| 142 | return mQuery.mDatabase; |
| 143 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 144 | } |
| 145 | |
| 146 | @Override |
| 147 | public boolean onMove(int oldPosition, int newPosition) { |
| 148 | // Make sure the row at newPosition is present in the window |
| 149 | if (mWindow == null || newPosition < mWindow.getStartPosition() || |
| 150 | newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) { |
| 151 | fillWindow(newPosition); |
| 152 | } |
| 153 | |
| 154 | return true; |
| 155 | } |
| 156 | |
| 157 | @Override |
| 158 | public int getCount() { |
| 159 | if (mCount == NO_COUNT) { |
| 160 | fillWindow(0); |
| 161 | } |
| 162 | return mCount; |
| 163 | } |
| 164 | |
Jeff Brown | 650de3d | 2011-10-27 14:52:28 -0700 | [diff] [blame] | 165 | private void fillWindow(int requiredPos) { |
Jeff Brown | 5e5d6d8 | 2011-10-12 15:41:34 -0700 | [diff] [blame] | 166 | clearOrCreateWindow(getDatabase().getPath()); |
Jeff Brown | 650de3d | 2011-10-27 14:52:28 -0700 | [diff] [blame] | 167 | |
| 168 | if (mCount == NO_COUNT) { |
| 169 | int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos, 0); |
| 170 | mCount = getQuery().fillWindow(mWindow, startPos, requiredPos, true); |
| 171 | mCursorWindowCapacity = mWindow.getNumRows(); |
Vasu Nori | b18f27d | 2010-08-12 18:16:35 -0700 | [diff] [blame] | 172 | if (Log.isLoggable(TAG, Log.DEBUG)) { |
Jeff Brown | 650de3d | 2011-10-27 14:52:28 -0700 | [diff] [blame] | 173 | Log.d(TAG, "received count(*) from native_fill_window: " + mCount); |
Vasu Nori | b18f27d | 2010-08-12 18:16:35 -0700 | [diff] [blame] | 174 | } |
Jeff Brown | 650de3d | 2011-10-27 14:52:28 -0700 | [diff] [blame] | 175 | } else { |
| 176 | int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos, |
| 177 | mCursorWindowCapacity); |
| 178 | getQuery().fillWindow(mWindow, startPos, requiredPos, false); |
Vasu Nori | b18f27d | 2010-08-12 18:16:35 -0700 | [diff] [blame] | 179 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 180 | } |
| 181 | |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 182 | private synchronized SQLiteQuery getQuery() { |
| 183 | return mQuery; |
| 184 | } |
| 185 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 186 | @Override |
| 187 | public int getColumnIndex(String columnName) { |
| 188 | // Create mColumnNameMap on demand |
| 189 | if (mColumnNameMap == null) { |
| 190 | String[] columns = mColumns; |
| 191 | int columnCount = columns.length; |
| 192 | HashMap<String, Integer> map = new HashMap<String, Integer>(columnCount, 1); |
| 193 | for (int i = 0; i < columnCount; i++) { |
| 194 | map.put(columns[i], i); |
| 195 | } |
| 196 | mColumnNameMap = map; |
| 197 | } |
| 198 | |
| 199 | // Hack according to bug 903852 |
| 200 | final int periodIndex = columnName.lastIndexOf('.'); |
| 201 | if (periodIndex != -1) { |
| 202 | Exception e = new Exception(); |
| 203 | Log.e(TAG, "requesting column name with table name -- " + columnName, e); |
| 204 | columnName = columnName.substring(periodIndex + 1); |
| 205 | } |
| 206 | |
| 207 | Integer i = mColumnNameMap.get(columnName); |
| 208 | if (i != null) { |
| 209 | return i.intValue(); |
| 210 | } else { |
| 211 | return -1; |
| 212 | } |
| 213 | } |
| 214 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 215 | @Override |
| 216 | public String[] getColumnNames() { |
| 217 | return mColumns; |
| 218 | } |
| 219 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 220 | @Override |
| 221 | public void deactivate() { |
| 222 | super.deactivate(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 223 | mDriver.cursorDeactivated(); |
| 224 | } |
| 225 | |
| 226 | @Override |
| 227 | public void close() { |
| 228 | super.close(); |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 229 | synchronized (this) { |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 230 | mQuery.close(); |
| 231 | mDriver.cursorClosed(); |
| 232 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 233 | } |
| 234 | |
| 235 | @Override |
| 236 | public boolean requery() { |
| 237 | if (isClosed()) { |
| 238 | return false; |
| 239 | } |
| 240 | long timeStart = 0; |
Joe Onorato | 43a1765 | 2011-04-06 19:22:23 -0700 | [diff] [blame] | 241 | if (false) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 242 | timeStart = System.currentTimeMillis(); |
| 243 | } |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 244 | |
| 245 | synchronized (this) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 246 | if (mWindow != null) { |
| 247 | mWindow.clear(); |
| 248 | } |
| 249 | mPos = -1; |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 250 | SQLiteDatabase db = null; |
| 251 | try { |
| 252 | db = mQuery.mDatabase.getDatabaseHandle(mQuery.mSql); |
| 253 | } catch (IllegalStateException e) { |
| 254 | // for backwards compatibility, just return false |
Vasu Nori | 324dbe5 | 2011-01-06 17:45:32 -0800 | [diff] [blame] | 255 | Log.w(TAG, "requery() failed " + e.getMessage(), e); |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 256 | return false; |
| 257 | } |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 258 | if (!db.equals(mQuery.mDatabase)) { |
| 259 | // since we need to use a different database connection handle, |
| 260 | // re-compile the query |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 261 | try { |
Vasu Nori | 16057fa | 2011-03-18 11:40:37 -0700 | [diff] [blame] | 262 | db.lock(mQuery.mSql); |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 263 | } catch (IllegalStateException e) { |
| 264 | // for backwards compatibility, just return false |
Vasu Nori | 324dbe5 | 2011-01-06 17:45:32 -0800 | [diff] [blame] | 265 | Log.w(TAG, "requery() failed " + e.getMessage(), e); |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 266 | return false; |
| 267 | } |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 268 | try { |
| 269 | // close the old mQuery object and open a new one |
| 270 | mQuery.close(); |
| 271 | mQuery = new SQLiteQuery(db, mQuery); |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 272 | } catch (IllegalStateException e) { |
| 273 | // for backwards compatibility, just return false |
Vasu Nori | 324dbe5 | 2011-01-06 17:45:32 -0800 | [diff] [blame] | 274 | Log.w(TAG, "requery() failed " + e.getMessage(), e); |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 275 | return false; |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 276 | } finally { |
| 277 | db.unlock(); |
| 278 | } |
| 279 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 280 | // This one will recreate the temp table, and get its count |
| 281 | mDriver.cursorRequeried(this); |
| 282 | mCount = NO_COUNT; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 283 | try { |
| 284 | mQuery.requery(); |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 285 | } catch (IllegalStateException e) { |
| 286 | // for backwards compatibility, just return false |
Vasu Nori | 324dbe5 | 2011-01-06 17:45:32 -0800 | [diff] [blame] | 287 | Log.w(TAG, "requery() failed " + e.getMessage(), e); |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 288 | return false; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 289 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 290 | } |
| 291 | |
Joe Onorato | 43a1765 | 2011-04-06 19:22:23 -0700 | [diff] [blame] | 292 | if (false) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 293 | Log.v("DatabaseWindow", "closing window in requery()"); |
| 294 | Log.v(TAG, "--- Requery()ed cursor " + this + ": " + mQuery); |
| 295 | } |
| 296 | |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 297 | boolean result = false; |
| 298 | try { |
| 299 | result = super.requery(); |
| 300 | } catch (IllegalStateException e) { |
| 301 | // for backwards compatibility, just return false |
Vasu Nori | 324dbe5 | 2011-01-06 17:45:32 -0800 | [diff] [blame] | 302 | Log.w(TAG, "requery() failed " + e.getMessage(), e); |
Vasu Nori | ca74897 | 2011-01-06 16:35:37 -0800 | [diff] [blame] | 303 | } |
Joe Onorato | 43a1765 | 2011-04-06 19:22:23 -0700 | [diff] [blame] | 304 | if (false) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 305 | long timeEnd = System.currentTimeMillis(); |
| 306 | Log.v(TAG, "requery (" + (timeEnd - timeStart) + " ms): " + mDriver.toString()); |
| 307 | } |
| 308 | return result; |
| 309 | } |
| 310 | |
| 311 | @Override |
Jeff Brown | 7ce7452 | 2011-10-07 13:29:37 -0700 | [diff] [blame] | 312 | public void setWindow(CursorWindow window) { |
| 313 | super.setWindow(window); |
| 314 | mCount = NO_COUNT; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 315 | } |
| 316 | |
| 317 | /** |
| 318 | * Changes the selection arguments. The new values take effect after a call to requery(). |
| 319 | */ |
| 320 | public void setSelectionArguments(String[] selectionArgs) { |
| 321 | mDriver.setBindArguments(selectionArgs); |
| 322 | } |
| 323 | |
| 324 | /** |
| 325 | * Release the native resources, if they haven't been released yet. |
| 326 | */ |
| 327 | @Override |
| 328 | protected void finalize() { |
| 329 | try { |
Vasu Nori | 42960e8 | 2010-01-06 23:12:02 -0800 | [diff] [blame] | 330 | // if the cursor hasn't been closed yet, close it first |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 331 | if (mWindow != null) { |
Jeff Sharkey | 7978a41 | 2011-10-25 17:09:09 -0700 | [diff] [blame] | 332 | if (mStackTrace != null) { |
Brad Fitzpatrick | 32e60c7 | 2010-09-30 16:22:36 -0700 | [diff] [blame] | 333 | int len = mQuery.mSql.length(); |
| 334 | StrictMode.onSqliteObjectLeaked( |
| 335 | "Finalizing a Cursor that has not been deactivated or closed. " + |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 336 | "database = " + mQuery.mDatabase.getPath() + ", table = " + mEditTable + |
Vasu Nori | b73cf1c | 2010-10-25 11:55:56 -0700 | [diff] [blame] | 337 | ", query = " + mQuery.mSql.substring(0, (len > 1000) ? 1000 : len), |
Vasu Nori | 2cc1df0 | 2010-03-23 10:17:48 -0700 | [diff] [blame] | 338 | mStackTrace); |
Brad Fitzpatrick | 32e60c7 | 2010-09-30 16:22:36 -0700 | [diff] [blame] | 339 | } |
Vasu Nori | 2cc1df0 | 2010-03-23 10:17:48 -0700 | [diff] [blame] | 340 | close(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 341 | SQLiteDebug.notifyActiveCursorFinalized(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 342 | } else { |
Joe Onorato | 43a1765 | 2011-04-06 19:22:23 -0700 | [diff] [blame] | 343 | if (false) { |
Vasu Nori | 65a8883 | 2010-07-16 15:14:08 -0700 | [diff] [blame] | 344 | Log.v(TAG, "Finalizing cursor on database = " + mQuery.mDatabase.getPath() + |
Vasu Nori | 42960e8 | 2010-01-06 23:12:02 -0800 | [diff] [blame] | 345 | ", table = " + mEditTable + ", query = " + mQuery.mSql); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 346 | } |
| 347 | } |
| 348 | } finally { |
| 349 | super.finalize(); |
| 350 | } |
| 351 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 352 | } |