SQLiteQuery.java revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
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;
20
21/**
22 * A SQLite program that represents a query that reads the resulting rows into a CursorWindow.
23 * This class is used by SQLiteCursor and isn't useful itself.
24 */
25public class SQLiteQuery extends SQLiteProgram {
26    //private static final String TAG = "Cursor";
27
28    /** The index of the unbound OFFSET parameter */
29    private int mOffsetIndex;
30
31    /** The SQL used to create this query */
32    private String mQuery;
33
34    /** Args to bind on requery */
35    private String[] mBindArgs;
36
37    private boolean mClosed = false;
38
39    /**
40     * Create a persistent query object.
41     *
42     * @param db The database that this query object is associated with
43     * @param query The SQL string for this query. It must include "INDEX -1
44     *            OFFSET ?" at the end
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     * @param startPos The position to start reading rows from
60     * @return number of total rows in the query
61     */
62    /* package */ int fillWindow(CursorWindow window, int startPos) {
63        if (startPos < 0) {
64            throw new IllegalArgumentException("startPos should > 0");
65        }
66        window.setStartPosition(startPos);
67        mDatabase.lock();
68        try {
69            acquireReference();
70            window.acquireReference();
71            return native_fill_window(window, startPos, mOffsetIndex);
72        } catch (IllegalStateException e){
73            // simply ignore it
74            return 0;
75        } catch (SQLiteDatabaseCorruptException e) {
76            mDatabase.onCorruption();
77            throw e;
78        } finally {
79            window.releaseReference();
80            releaseReference();
81            mDatabase.unlock();
82        }
83    }
84
85    /**
86     * Get the column count for the statement. Only valid on query based
87     * statements. The database must be locked
88     * when calling this method.
89     *
90     * @return The number of column in the statement's result set.
91     */
92    /* package */ int columnCountLocked() {
93        acquireReference();
94        try {
95            return native_column_count();
96        } finally {
97            releaseReference();
98        }
99    }
100
101    /**
102     * Retrieves the column name for the given column index. The database must be locked
103     * when calling this method.
104     *
105     * @param columnIndex the index of the column to get the name for
106     * @return The requested column's name
107     */
108    /* package */ String columnNameLocked(int columnIndex) {
109        acquireReference();
110        try {
111            return native_column_name(columnIndex);
112        } finally {
113            releaseReference();
114        }
115    }
116
117    @Override
118    public void close() {
119        super.close();
120        mClosed = true;
121    }
122
123    /**
124     * Called by SQLiteCursor when it is requeried.
125     */
126    /* package */ void requery() {
127        boolean oldMClosed = mClosed;
128        if (mClosed) {
129            mClosed = false;
130            compile(mQuery, false);
131        }
132        if (mBindArgs != null) {
133            int len = mBindArgs.length;
134            try {
135                for (int i = 0; i < len; i++) {
136                    super.bindString(i + 1, mBindArgs[i]);
137                }
138            } catch (SQLiteMisuseException e) {
139                StringBuilder errMsg = new StringBuilder
140                    ("old mClosed " + oldMClosed + " mQuery " + mQuery);
141                for (int i = 0; i < len; i++) {
142                    errMsg.append(" ");
143                    errMsg.append(mBindArgs[i]);
144                }
145                errMsg.append(" ");
146                IllegalStateException leakProgram = new IllegalStateException(
147                        errMsg.toString(), e);
148                throw leakProgram;
149            }
150        }
151    }
152
153    @Override
154    public void bindNull(int index) {
155        mBindArgs[index - 1] = null;
156        if (!mClosed) super.bindNull(index);
157    }
158
159    @Override
160    public void bindLong(int index, long value) {
161        mBindArgs[index - 1] = Long.toString(value);
162        if (!mClosed) super.bindLong(index, value);
163    }
164
165    @Override
166    public void bindDouble(int index, double value) {
167        mBindArgs[index - 1] = Double.toString(value);
168        if (!mClosed) super.bindDouble(index, value);
169    }
170
171    @Override
172    public void bindString(int index, String value) {
173        mBindArgs[index - 1] = value;
174        if (!mClosed) super.bindString(index, value);
175    }
176
177    private final native int native_fill_window(CursorWindow window, int startPos, int offsetParam);
178
179    private final native int native_column_count();
180
181    private final native String native_column_name(int columnIndex);
182}
183