• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.CursorWindow;
20 import android.os.SystemClock;
21 import android.util.Log;
22 
23 /**
24  * A SQLite program that represents a query that reads the resulting rows into a CursorWindow.
25  * This class is used by SQLiteCursor and isn't useful itself.
26  *
27  * SQLiteQuery is not internally synchronized so code using a SQLiteQuery from multiple
28  * threads should perform its own synchronization when using the SQLiteQuery.
29  */
30 public class SQLiteQuery extends SQLiteProgram {
31     private static final String TAG = "SQLiteQuery";
32 
nativeFillWindow(int databasePtr, int statementPtr, int windowPtr, int startPos, int offsetParam)33     private static native int nativeFillWindow(int databasePtr, int statementPtr, int windowPtr,
34             int startPos, int offsetParam);
nativeColumnCount(int statementPtr)35     private static native int nativeColumnCount(int statementPtr);
nativeColumnName(int statementPtr, int columnIndex)36     private static native String nativeColumnName(int statementPtr, int columnIndex);
37 
38     /** The index of the unbound OFFSET parameter */
39     private int mOffsetIndex = 0;
40 
41     private boolean mClosed = false;
42 
43     /**
44      * Create a persistent query object.
45      *
46      * @param db The database that this query object is associated with
47      * @param query The SQL string for this query.
48      * @param offsetIndex The 1-based index to the OFFSET parameter,
49      */
SQLiteQuery(SQLiteDatabase db, String query, int offsetIndex, String[] bindArgs)50     /* package */ SQLiteQuery(SQLiteDatabase db, String query, int offsetIndex, String[] bindArgs) {
51         super(db, query);
52         mOffsetIndex = offsetIndex;
53         bindAllArgsAsStrings(bindArgs);
54     }
55 
56     /**
57      * Constructor used to create new instance to replace a given instance of this class.
58      * This constructor is used when the current Query object is now associated with a different
59      * {@link SQLiteDatabase} object.
60      *
61      * @param db The database that this query object is associated with
62      * @param query the instance of {@link SQLiteQuery} to be replaced
63      */
SQLiteQuery(SQLiteDatabase db, SQLiteQuery query)64     /* package */ SQLiteQuery(SQLiteDatabase db, SQLiteQuery query) {
65         super(db, query.mSql);
66         this.mBindArgs = query.mBindArgs;
67         this.mOffsetIndex = query.mOffsetIndex;
68     }
69 
70     /**
71      * Reads rows into a buffer. This method acquires the database lock.
72      *
73      * @param window The window to fill into
74      * @return number of total rows in the query
75      */
fillWindow(CursorWindow window)76     /* package */ int fillWindow(CursorWindow window) {
77         mDatabase.lock(mSql);
78         long timeStart = SystemClock.uptimeMillis();
79         try {
80             acquireReference();
81             try {
82                 window.acquireReference();
83                 int numRows = nativeFillWindow(nHandle, nStatement, window.mWindowPtr,
84                         window.getStartPosition(), mOffsetIndex);
85                 mDatabase.logTimeStat(mSql, timeStart);
86                 return numRows;
87             } catch (IllegalStateException e){
88                 // simply ignore it
89                 return 0;
90             } catch (SQLiteDatabaseCorruptException e) {
91                 mDatabase.onCorruption();
92                 throw e;
93             } catch (SQLiteException e) {
94                 Log.e(TAG, "exception: " + e.getMessage() + "; query: " + mSql);
95                 throw e;
96             } finally {
97                 window.releaseReference();
98             }
99         } finally {
100             releaseReference();
101             mDatabase.unlock();
102         }
103     }
104 
105     /**
106      * Get the column count for the statement. Only valid on query based
107      * statements. The database must be locked
108      * when calling this method.
109      *
110      * @return The number of column in the statement's result set.
111      */
columnCountLocked()112     /* package */ int columnCountLocked() {
113         acquireReference();
114         try {
115             return nativeColumnCount(nStatement);
116         } finally {
117             releaseReference();
118         }
119     }
120 
121     /**
122      * Retrieves the column name for the given column index. The database must be locked
123      * when calling this method.
124      *
125      * @param columnIndex the index of the column to get the name for
126      * @return The requested column's name
127      */
columnNameLocked(int columnIndex)128     /* package */ String columnNameLocked(int columnIndex) {
129         acquireReference();
130         try {
131             return nativeColumnName(nStatement, columnIndex);
132         } finally {
133             releaseReference();
134         }
135     }
136 
137     @Override
toString()138     public String toString() {
139         return "SQLiteQuery: " + mSql;
140     }
141 
142     @Override
close()143     public void close() {
144         super.close();
145         mClosed = true;
146     }
147 
148     /**
149      * Called by SQLiteCursor when it is requeried.
150      */
requery()151     /* package */ void requery() {
152         if (mClosed) {
153             throw new IllegalStateException("requerying a closed cursor");
154         }
155         compileAndbindAllArgs();
156     }
157 }
158