SQLiteCursorpublic class SQLiteCursor extends android.database.AbstractWindowedCursor A Cursor implementation that exposes results from a query on a
{@link SQLiteDatabase}.
SQLiteCursor is not internally synchronized so code using a SQLiteCursor from multiple
threads should perform its own synchronization when using the SQLiteCursor. |
Fields Summary |
---|
static final String | TAG | static final int | NO_COUNT | private final String | mEditTableThe name of the table to edit | private final String[] | mColumnsThe names of the columns in the rows | private final SQLiteQuery | mQueryThe query object for the cursor | private final SQLiteCursorDriver | mDriverThe compiled query this cursor came from | private int | mCountThe number of rows in the cursor | private int | mCursorWindowCapacityThe number of rows that can fit in the cursor window, 0 if unknown | private Map | mColumnNameMapA mapping of column names to column indices, to speed up lookups | private final Throwable | mStackTraceUsed to find out where a cursor was allocated in case it never got released. |
Constructors Summary |
---|
public SQLiteCursor(SQLiteDatabase db, SQLiteCursorDriver driver, String editTable, SQLiteQuery query)Execute a query and provide access to its result set through a Cursor
interface. For a query such as: {@code SELECT name, birth, phone FROM
myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth,
phone) would be in the projection argument and everything from
{@code FROM} onward would be in the params argument.
this(driver, editTable, query);
| public SQLiteCursor(SQLiteCursorDriver driver, String editTable, SQLiteQuery query)Execute a query and provide access to its result set through a Cursor
interface. For a query such as: {@code SELECT name, birth, phone FROM
myTable WHERE ... LIMIT 1,20 ORDER BY...} the column names (name, birth,
phone) would be in the projection argument and everything from
{@code FROM} onward would be in the params argument.
if (query == null) {
throw new IllegalArgumentException("query object cannot be null");
}
if (StrictMode.vmSqliteObjectLeaksEnabled()) {
mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
} else {
mStackTrace = null;
}
mDriver = driver;
mEditTable = editTable;
mColumnNameMap = null;
mQuery = query;
mColumns = query.getColumnNames();
mRowIdColumnIndex = DatabaseUtils.findRowIdColumnIndex(mColumns);
|
Methods Summary |
---|
public void | close()
super.close();
synchronized (this) {
mQuery.close();
mDriver.cursorClosed();
}
| public void | deactivate()
super.deactivate();
mDriver.cursorDeactivated();
| private void | fillWindow(int requiredPos)
clearOrCreateWindow(getDatabase().getPath());
try {
if (mCount == NO_COUNT) {
int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos, 0);
mCount = mQuery.fillWindow(mWindow, startPos, requiredPos, true);
mCursorWindowCapacity = mWindow.getNumRows();
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "received count(*) from native_fill_window: " + mCount);
}
} else {
int startPos = DatabaseUtils.cursorPickFillWindowStartPosition(requiredPos,
mCursorWindowCapacity);
mQuery.fillWindow(mWindow, startPos, requiredPos, false);
}
} catch (RuntimeException ex) {
// Close the cursor window if the query failed and therefore will
// not produce any results. This helps to avoid accidentally leaking
// the cursor window if the client does not correctly handle exceptions
// and fails to close the cursor.
closeWindow();
throw ex;
}
| protected void | finalize()Release the native resources, if they haven't been released yet.
try {
// if the cursor hasn't been closed yet, close it first
if (mWindow != null) {
if (mStackTrace != null) {
String sql = mQuery.getSql();
int len = sql.length();
StrictMode.onSqliteObjectLeaked(
"Finalizing a Cursor that has not been deactivated or closed. " +
"database = " + mQuery.getDatabase().getLabel() +
", table = " + mEditTable +
", query = " + sql.substring(0, (len > 1000) ? 1000 : len),
mStackTrace);
}
close();
}
} finally {
super.finalize();
}
| public int | getColumnIndex(java.lang.String columnName)
// Create mColumnNameMap on demand
if (mColumnNameMap == null) {
String[] columns = mColumns;
int columnCount = columns.length;
HashMap<String, Integer> map = new HashMap<String, Integer>(columnCount, 1);
for (int i = 0; i < columnCount; i++) {
map.put(columns[i], i);
}
mColumnNameMap = map;
}
// Hack according to bug 903852
final int periodIndex = columnName.lastIndexOf('.");
if (periodIndex != -1) {
Exception e = new Exception();
Log.e(TAG, "requesting column name with table name -- " + columnName, e);
columnName = columnName.substring(periodIndex + 1);
}
Integer i = mColumnNameMap.get(columnName);
if (i != null) {
return i.intValue();
} else {
return -1;
}
| public java.lang.String[] | getColumnNames()
return mColumns;
| public int | getCount()
if (mCount == NO_COUNT) {
fillWindow(0);
}
return mCount;
| public SQLiteDatabase | getDatabase()Get the database that this cursor is associated with.
return mQuery.getDatabase();
| public boolean | onMove(int oldPosition, int newPosition)
// Make sure the row at newPosition is present in the window
if (mWindow == null || newPosition < mWindow.getStartPosition() ||
newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
fillWindow(newPosition);
}
return true;
| public boolean | requery()
if (isClosed()) {
return false;
}
synchronized (this) {
if (!mQuery.getDatabase().isOpen()) {
return false;
}
if (mWindow != null) {
mWindow.clear();
}
mPos = -1;
mCount = NO_COUNT;
mDriver.cursorRequeried(this);
}
try {
return super.requery();
} catch (IllegalStateException e) {
// for backwards compatibility, just return false
Log.w(TAG, "requery() failed " + e.getMessage(), e);
return false;
}
| public void | setSelectionArguments(java.lang.String[] selectionArgs)Changes the selection arguments. The new values take effect after a call to requery().
mDriver.setBindArguments(selectionArgs);
| public void | setWindow(android.database.CursorWindow window)
super.setWindow(window);
mCount = NO_COUNT;
|
|