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
2541cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolovimport com.android.internal.util.Preconditions;
2641cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A Cursor implementation that exposes results from a query on a
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SQLiteDatabase}.
33f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton *
34f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * SQLiteCursor is not internally synchronized so code using a SQLiteCursor from multiple
35f3ca9a5c7e87319c934b5815566054d2e5c2085fJeff Hamilton * threads should perform its own synchronization when using the SQLiteCursor.
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SQLiteCursor extends AbstractWindowedCursor {
38071df261ed204c0c732570690921389e1c0b9bcdVasu Nori    static final String TAG = "SQLiteCursor";
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int NO_COUNT = -1;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The name of the table to edit */
4265a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    private final String mEditTable;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The names of the columns in the rows */
4565a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    private final String[] mColumns;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The query object for the cursor */
48e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    private final SQLiteQuery mQuery;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The compiled query this cursor came from */
5165a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    private final SQLiteCursorDriver mDriver;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The number of rows in the cursor */
54650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown    private int mCount = NO_COUNT;
55650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown
56650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown    /** The number of rows that can fit in the cursor window, 0 if unknown */
57650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown    private int mCursorWindowCapacity;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** A mapping of column names to column indices, to speed up lookups */
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Map<String, Integer> mColumnNameMap;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
62d606b4bf2c1a2308b40785860853cfb95a77bf58Vasu Nori    /** Used to find out where a cursor was allocated in case it never got released. */
6365a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    private final Throwable mStackTrace;
642589716964f99fd0ee29a9b295584c277e23f34fMakoto Onuki
6541cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov    /** Controls fetching of rows relative to requested position **/
6641cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov    private boolean mFillWindowForwardOnly;
6741cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov
682589716964f99fd0ee29a9b295584c277e23f34fMakoto Onuki    /**
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Execute a query and provide access to its result set through a Cursor
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * interface. For a query such as: {@code SELECT name, birth, phone FROM
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth,
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * phone) would be in the projection argument and everything from
73ebc016c01ea9d5707287cfc19ccc59b21a486c00Jeff Brown     * {@code FROM} onward would be in the params argument.
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param db a reference to a Database object that is already constructed
7665a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     *     and opened. This param is not used any longer
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param editTable the name of the table used for this query
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param query the rest of the query terms
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     cursor is finalized
8065a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * @deprecated use {@link #SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)} instead
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8265a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    @Deprecated
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SQLiteCursor(SQLiteDatabase db, SQLiteCursorDriver driver,
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String editTable, SQLiteQuery query) {
8565a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        this(driver, editTable, query);
8665a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    }
8765a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori
8865a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    /**
8965a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * Execute a query and provide access to its result set through a Cursor
9065a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * interface. For a query such as: {@code SELECT name, birth, phone FROM
9165a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth,
9265a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * phone) would be in the projection argument and everything from
93ebc016c01ea9d5707287cfc19ccc59b21a486c00Jeff Brown     * {@code FROM} onward would be in the params argument.
9465a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     *
9565a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * @param editTable the name of the table used for this query
9665a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     * @param query the {@link SQLiteQuery} object associated with this cursor object.
9765a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori     */
9865a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori    public SQLiteCursor(SQLiteCursorDriver driver, String editTable, SQLiteQuery query) {
9965a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        if (query == null) {
10065a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori            throw new IllegalArgumentException("query object cannot be null");
10165a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        }
1027978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey        if (StrictMode.vmSqliteObjectLeaksEnabled()) {
1037978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey            mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
1047978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey        } else {
1057978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey            mStackTrace = null;
1067978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey        }
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDriver = driver;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEditTable = editTable;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mColumnNameMap = null;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQuery = query;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
112e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        mColumns = query.getColumnNames();
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
116e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown     * Get the database that this cursor is associated with.
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the SQLiteDatabase that this cursor is associated with.
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SQLiteDatabase getDatabase() {
120e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        return mQuery.getDatabase();
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onMove(int oldPosition, int newPosition) {
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Make sure the row at newPosition is present in the window
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mWindow == null || newPosition < mWindow.getStartPosition() ||
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillWindow(newPosition);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getCount() {
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCount == NO_COUNT) {
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillWindow(0);
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCount;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
142650de3dcfcbc7635da3c070410ef1dc4027ae464Jeff Brown    private void fillWindow(int requiredPos) {
1435e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brown        clearOrCreateWindow(getDatabase().getPath());
144c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown        try {
14541cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov            Preconditions.checkArgumentNonnegative(requiredPos,
14641cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov                    "requiredPos cannot be negative, but was " + requiredPos);
14741cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov
148c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            if (mCount == NO_COUNT) {
14941cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov                mCount = mQuery.fillWindow(mWindow, requiredPos, requiredPos, true);
150c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                mCursorWindowCapacity = mWindow.getNumRows();
151c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                if (Log.isLoggable(TAG, Log.DEBUG)) {
152c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                    Log.d(TAG, "received count(*) from native_fill_window: " + mCount);
153c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                }
154c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            } else {
15541cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov                int startPos = mFillWindowForwardOnly ? requiredPos : DatabaseUtils
15641cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov                        .cursorPickFillWindowStartPosition(requiredPos, mCursorWindowCapacity);
157c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown                mQuery.fillWindow(mWindow, startPos, requiredPos, false);
158b18f27dbf43ee9028a11cafbca23d3fa318e278bVasu Nori            }
159c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown        } catch (RuntimeException ex) {
160c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            // Close the cursor window if the query failed and therefore will
161c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            // not produce any results.  This helps to avoid accidentally leaking
162c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            // the cursor window if the client does not correctly handle exceptions
163c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            // and fails to close the cursor.
164c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            closeWindow();
165c21b5a019c1da00b6d861cd2859e3c349a44b3a7Jeff Brown            throw ex;
166b18f27dbf43ee9028a11cafbca23d3fa318e278bVasu Nori        }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getColumnIndex(String columnName) {
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Create mColumnNameMap on demand
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mColumnNameMap == null) {
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String[] columns = mColumns;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int columnCount = columns.length;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HashMap<String, Integer> map = new HashMap<String, Integer>(columnCount, 1);
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < columnCount; i++) {
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                map.put(columns[i], i);
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mColumnNameMap = map;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Hack according to bug 903852
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int periodIndex = columnName.lastIndexOf('.');
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (periodIndex != -1) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Exception e = new Exception();
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "requesting column name with table name -- " + columnName, e);
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            columnName = columnName.substring(periodIndex + 1);
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Integer i = mColumnNameMap.get(columnName);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (i != null) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return i.intValue();
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String[] getColumnNames() {
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mColumns;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void deactivate() {
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.deactivate();
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDriver.cursorDeactivated();
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void close() {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.close();
21265a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        synchronized (this) {
21365a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori            mQuery.close();
21465a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori            mDriver.cursorClosed();
21565a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        }
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requery() {
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isClosed()) {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22365a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori
22465a8883f0e605bb8a73a692987b47ce5da632e72Vasu Nori        synchronized (this) {
225e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            if (!mQuery.getDatabase().isOpen()) {
226e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                return false;
227e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            }
228e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mWindow != null) {
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mWindow.clear();
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPos = -1;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCount = NO_COUNT;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
235e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            mDriver.cursorRequeried(this);
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
238ca74897b24e24681e05ed35d13cf7a68bc924673Vasu Nori        try {
239e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            return super.requery();
240ca74897b24e24681e05ed35d13cf7a68bc924673Vasu Nori        } catch (IllegalStateException e) {
241ca74897b24e24681e05ed35d13cf7a68bc924673Vasu Nori            // for backwards compatibility, just return false
242324dbe508e7afdae201fe378f1aca4227baf6c06Vasu Nori            Log.w(TAG, "requery() failed " + e.getMessage(), e);
243e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            return false;
244ca74897b24e24681e05ed35d13cf7a68bc924673Vasu Nori        }
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2487ce745248d4de0e6543a559c93423df899832100Jeff Brown    public void setWindow(CursorWindow window) {
2497ce745248d4de0e6543a559c93423df899832100Jeff Brown        super.setWindow(window);
2507ce745248d4de0e6543a559c93423df899832100Jeff Brown        mCount = NO_COUNT;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Changes the selection arguments. The new values take effect after a call to requery().
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setSelectionArguments(String[] selectionArgs) {
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDriver.setBindArguments(selectionArgs);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
26141cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov     * Controls fetching of rows relative to requested position.
26241cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov     *
26341cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov     * <p>Calling this method defines how rows will be loaded, but it doesn't affect rows that
26441cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov     * are already in the window. This setting is preserved if a new window is
26541cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov     * {@link #setWindow(CursorWindow) set}
26641cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov     *
26741cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov     * @param fillWindowForwardOnly if true, rows will be fetched starting from requested position
26841cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov     * up to the window's capacity. Default value is false.
26941cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov     */
27041cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov    public void setFillWindowForwardOnly(boolean fillWindowForwardOnly) {
27141cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov        mFillWindowForwardOnly = fillWindowForwardOnly;
27241cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov    }
27341cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov
27441cadb7d31c974c259044e1fcfeb2601c6ad60afFyodor Kupolov    /**
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Release the native resources, if they haven't been released yet.
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() {
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
28042960e8ddf443f81ceadb9f9390707768d68ab7fVasu Nori            // if the cursor hasn't been closed yet, close it first
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mWindow != null) {
2827978a414bbbc737bfb342db8840c29376e33a34dJeff Sharkey                if (mStackTrace != null) {
283e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                    String sql = mQuery.getSql();
284e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                    int len = sql.length();
28532e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick                    StrictMode.onSqliteObjectLeaked(
28632e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick                        "Finalizing a Cursor that has not been deactivated or closed. " +
287e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                        "database = " + mQuery.getDatabase().getLabel() +
288e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                        ", table = " + mEditTable +
289e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                        ", query = " + sql.substring(0, (len > 1000) ? 1000 : len),
2902cc1df04381cb13c7d66aa8de0cc32312482d045Vasu Nori                        mStackTrace);
29132e60c7942eeba920ec5c27b372ec0899fd75a20Brad Fitzpatrick                }
2922cc1df04381cb13c7d66aa8de0cc32312482d045Vasu Nori                close();
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super.finalize();
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
299