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
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.AbstractWindowedCursor;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.CursorWindow;
21650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brownimport android.database.DatabaseUtils;
2232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrickimport android.os.StrictMode;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A Cursor implementation that exposes results from a query on a
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SQLiteDatabase}.
31f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton *
32f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * SQLiteCursor is not internally synchronized so code using a SQLiteCursor from multiple
33f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * threads should perform its own synchronization when using the SQLiteCursor.
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SQLiteCursor extends AbstractWindowedCursor {
36071df261ed204c0c732570690921389e1c0b9bcdVasu Nori    static final String TAG = "SQLiteCursor";
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int NO_COUNT = -1;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The name of the table to edit */
4065a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    private final String mEditTable;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The names of the columns in the rows */
4365a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    private final String[] mColumns;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The query object for the cursor */
46e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    private final SQLiteQuery mQuery;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The compiled query this cursor came from */
4965a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    private final SQLiteCursorDriver mDriver;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The number of rows in the cursor */
52650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown    private int mCount = NO_COUNT;
53650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown
54650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown    /** The number of rows that can fit in the cursor window, 0 if unknown */
55650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown    private int mCursorWindowCapacity;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** A mapping of column names to column indices, to speed up lookups */
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Map<String, Integer> mColumnNameMap;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
60d606b4bf2c1a2308b40785860853cfb95a77bf58Vasu Nori    /** Used to find out where a cursor was allocated in case it never got released. */
6165a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    private final Throwable mStackTrace;
622589716964f99fd0ee29a9b295584c277e23f34fMakoto Onuki
632589716964f99fd0ee29a9b295584c277e23f34fMakoto Onuki    /**
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Execute a query and provide access to its result set through a Cursor
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * interface. For a query such as: {@code SELECT name, birth, phone FROM
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth,
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * phone) would be in the projection argument and everything from
68ebc016c01ea9d5707287cfc19ccc59b21a486c00Jeff Brown     * {@code FROM} onward would be in the params argument.
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param db a reference to a Database object that is already constructed
7165a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     *     and opened. This param is not used any longer
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param editTable the name of the table used for this query
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param query the rest of the query terms
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     cursor is finalized
7565a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * @deprecated use {@link #SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)} instead
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7765a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    @Deprecated
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SQLiteCursor(SQLiteDatabase db, SQLiteCursorDriver driver,
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String editTable, SQLiteQuery query) {
8065a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        this(driver, editTable, query);
8165a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    }
8265a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori
8365a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    /**
8465a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * Execute a query and provide access to its result set through a Cursor
8565a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * interface. For a query such as: {@code SELECT name, birth, phone FROM
8665a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth,
8765a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * phone) would be in the projection argument and everything from
88ebc016c01ea9d5707287cfc19ccc59b21a486c00Jeff Brown     * {@code FROM} onward would be in the params argument.
8965a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     *
9065a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * @param editTable the name of the table used for this query
9165a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * @param query the {@link SQLiteQuery} object associated with this cursor object.
9265a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     */
9365a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    public SQLiteCursor(SQLiteCursorDriver driver, String editTable, SQLiteQuery query) {
9465a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        if (query == null) {
9565a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori            throw new IllegalArgumentException("query object cannot be null");
9665a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        }
977978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey        if (StrictMode.vmSqliteObjectLeaksEnabled()) {
987978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey            mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
997978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey        } else {
1007978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey            mStackTrace = null;
1017978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey        }
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDriver = driver;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEditTable = editTable;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mColumnNameMap = null;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQuery = query;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
107e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        mColumns = query.getColumnNames();
108fb5a4964b8d402b39754f406dd2255035ff2148dJeff Brown        mRowIdColumnIndex = DatabaseUtils.findRowIdColumnIndex(mColumns);
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
112e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown     * Get the database that this cursor is associated with.
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the SQLiteDatabase that this cursor is associated with.
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SQLiteDatabase getDatabase() {
116e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        return mQuery.getDatabase();
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onMove(int oldPosition, int newPosition) {
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Make sure the row at newPosition is present in the window
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mWindow == null || newPosition < mWindow.getStartPosition() ||
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillWindow(newPosition);
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getCount() {
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCount == NO_COUNT) {
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillWindow(0);
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCount;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
138650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown    private void fillWindow(int requiredPos) {
1395e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brown        clearOrCreateWindow(getDatabase().getPath());
140650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown
141c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown        try {
142c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            if (mCount == NO_COUNT) {
143c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos, 0);
144c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                mCount = mQuery.fillWindow(mWindow, startPos, requiredPos, true);
145c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                mCursorWindowCapacity = mWindow.getNumRows();
146c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                if (Log.isLoggable(TAG, Log.DEBUG)) {
147c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                    Log.d(TAG, "received count(*) from native_fill_window: " + mCount);
148c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                }
149c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            } else {
150c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos,
151c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                        mCursorWindowCapacity);
152c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                mQuery.fillWindow(mWindow, startPos, requiredPos, false);
153b18f27dbf43ee9028a11cafbca23d3fa318e278bVasu Nori            }
154c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown        } catch (RuntimeException ex) {
155c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            // Close the cursor window if the query failed and therefore will
156c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            // not produce any results.  This helps to avoid accidentally leaking
157c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            // the cursor window if the client does not correctly handle exceptions
158c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            // and fails to close the cursor.
159c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            closeWindow();
160c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            throw ex;
161b18f27dbf43ee9028a11cafbca23d3fa318e278bVasu Nori        }
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getColumnIndex(String columnName) {
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Create mColumnNameMap on demand
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mColumnNameMap == null) {
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String[] columns = mColumns;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int columnCount = columns.length;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HashMap<String, Integer> map = new HashMap<String, Integer>(columnCount, 1);
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < columnCount; i++) {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                map.put(columns[i], i);
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mColumnNameMap = map;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Hack according to bug 903852
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int periodIndex = columnName.lastIndexOf('.');
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (periodIndex != -1) {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Exception e = new Exception();
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "requesting column name with table name -- " + columnName, e);
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            columnName = columnName.substring(periodIndex + 1);
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Integer i = mColumnNameMap.get(columnName);
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i != null) {
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return i.intValue();
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] getColumnNames() {
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mColumns;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void deactivate() {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.deactivate();
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDriver.cursorDeactivated();
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void close() {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.close();
20765a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        synchronized (this) {
20865a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori            mQuery.close();
20965a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori            mDriver.cursorClosed();
21065a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requery() {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isClosed()) {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21865a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori
21965a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        synchronized (this) {
220e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            if (!mQuery.getDatabase().isOpen()) {
221e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                return false;
222e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            }
223e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mWindow != null) {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mWindow.clear();
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPos = -1;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCount = NO_COUNT;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
230e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            mDriver.cursorRequeried(this);
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
233ca74897b24e24681e05ed35d13cf7a68bc924673Vasu Nori        try {
234e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            return super.requery();
235ca74897b24e24681e05ed35d13cf7a68bc924673Vasu Nori        } catch (IllegalStateException e) {
236ca74897b24e24681e05ed35d13cf7a68bc924673Vasu Nori            // for backwards compatibility, just return false
237324dbe508e7afdae201fe378f1aca4227baf6c06Vasu Nori            Log.w(TAG, "requery() failed " + e.getMessage(), e);
238e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            return false;
239ca74897b24e24681e05ed35d13cf7a68bc924673Vasu Nori        }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2437ce745248d4de0e6543a559c93423df899832100Jeff Brown    public void setWindow(CursorWindow window) {
2447ce745248d4de0e6543a559c93423df899832100Jeff Brown        super.setWindow(window);
2457ce745248d4de0e6543a559c93423df899832100Jeff Brown        mCount = NO_COUNT;
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Changes the selection arguments. The new values take effect after a call to requery().
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setSelectionArguments(String[] selectionArgs) {
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDriver.setBindArguments(selectionArgs);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Release the native resources, if they haven't been released yet.
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() {
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
26142960e8ddf443f81ceadb9f9390707768d68ab7fVasu Nori            // if the cursor hasn't been closed yet, close it first
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mWindow != null) {
2637978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey                if (mStackTrace != null) {
264e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                    String sql = mQuery.getSql();
265e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                    int len = sql.length();
26632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick                    StrictMode.onSqliteObjectLeaked(
26732e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick                        "Finalizing a Cursor that has not been deactivated or closed. " +
268e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                        "database = " + mQuery.getDatabase().getLabel() +
269e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                        ", table = " + mEditTable +
270e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                        ", query = " + sql.substring(0, (len > 1000) ? 1000 : len),
2712cc1df04381cb13c7d66aa8de0cc32312482d045Vasu Nori                        mStackTrace);
27232e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick                }
2732cc1df04381cb13c7d66aa8de0cc32312482d045Vasu Nori                close();
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super.finalize();
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
280