diff options
| author | 2011-10-12 17:42:41 -0700 | |
|---|---|---|
| committer | 2011-10-12 22:19:42 -0700 | |
| commit | 80e7b80fa607e13d31d7dab68ddfd4d9f0372e38 (patch) | |
| tree | 4b93f873b4a79225f623ad25e37f0c8294f06a4b | |
| parent | 5e5d6d8ba04d7579df840cda055cd5dfa9d7666f (diff) | |
Make default implementation of fillWindow typesafe.
Bug: 5218310
This change fixes problems calling the default fillWindow
on Cursors that contain BLOBs. It should also be more efficient
by avoiding redundant string conversions for numeric datatypes.
Change-Id: Ied515bf6299bc8d3c14e76055d85fd35e7c05952
| -rw-r--r-- | core/java/android/database/AbstractCursor.java | 46 | ||||
| -rw-r--r-- | core/java/android/database/CursorWindow.java | 57 | ||||
| -rw-r--r-- | core/java/android/database/DatabaseUtils.java | 79 |
3 files changed, 103 insertions, 79 deletions
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java index ee6aec6f0d2d..74fef2993272 100644 --- a/core/java/android/database/AbstractCursor.java +++ b/core/java/android/database/AbstractCursor.java @@ -53,7 +53,10 @@ public abstract class AbstractCursor implements CrossProcessCursor { abstract public boolean isNull(int column); public int getType(int column) { - throw new UnsupportedOperationException(); + // Reflects the assumption that all commonly used field types (meaning everything + // but blobs) are convertible to strings so it should be safe to call + // getString to retrieve them. + return FIELD_TYPE_STRING; } // TODO implement getBlob in all cursor types @@ -185,46 +188,9 @@ public abstract class AbstractCursor implements CrossProcessCursor { return result; } - /** - * Copy data from cursor to CursorWindow - * @param position start position of data - * @param window - */ + @Override public void fillWindow(int position, CursorWindow window) { - if (position < 0 || position >= getCount()) { - return; - } - window.acquireReference(); - try { - int oldpos = mPos; - mPos = position - 1; - window.clear(); - window.setStartPosition(position); - int columnNum = getColumnCount(); - window.setNumColumns(columnNum); - while (moveToNext() && window.allocRow()) { - for (int i = 0; i < columnNum; i++) { - String field = getString(i); - if (field != null) { - if (!window.putString(field, mPos, i)) { - window.freeLastRow(); - break; - } - } else { - if (!window.putNull(mPos, i)) { - window.freeLastRow(); - break; - } - } - } - } - - mPos = oldpos; - } catch (IllegalStateException e){ - // simply ignore it - } finally { - window.releaseReference(); - } + DatabaseUtils.cursorFillWindow(this, position, window); } public final boolean move(int offset) { diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java index 7ccb8012577e..9c933247f6f6 100644 --- a/core/java/android/database/CursorWindow.java +++ b/core/java/android/database/CursorWindow.java @@ -271,8 +271,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * Returns true if the field at the specified row and column index * has type {@link Cursor#FIELD_TYPE_NULL}. * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return True if the field has type {@link Cursor#FIELD_TYPE_NULL}. * @deprecated Use {@link #getType(int, int)} instead. @@ -286,8 +285,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * Returns true if the field at the specified row and column index * has type {@link Cursor#FIELD_TYPE_BLOB} or {@link Cursor#FIELD_TYPE_NULL}. * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return True if the field has type {@link Cursor#FIELD_TYPE_BLOB} or * {@link Cursor#FIELD_TYPE_NULL}. @@ -303,8 +301,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * Returns true if the field at the specified row and column index * has type {@link Cursor#FIELD_TYPE_INTEGER}. * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return True if the field has type {@link Cursor#FIELD_TYPE_INTEGER}. * @deprecated Use {@link #getType(int, int)} instead. @@ -318,8 +315,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * Returns true if the field at the specified row and column index * has type {@link Cursor#FIELD_TYPE_FLOAT}. * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return True if the field has type {@link Cursor#FIELD_TYPE_FLOAT}. * @deprecated Use {@link #getType(int, int)} instead. @@ -333,8 +329,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * Returns true if the field at the specified row and column index * has type {@link Cursor#FIELD_TYPE_STRING} or {@link Cursor#FIELD_TYPE_NULL}. * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return True if the field has type {@link Cursor#FIELD_TYPE_STRING} * or {@link Cursor#FIELD_TYPE_NULL}. @@ -359,8 +354,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * </ul> * </p> * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return The field type. */ @@ -390,8 +384,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * </ul> * </p> * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return The value of the field as a byte array. */ @@ -426,8 +419,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * </ul> * </p> * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return The value of the field as a string. */ @@ -465,8 +457,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * </ul> * </p> * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @param buffer The {@link CharArrayBuffer} to hold the string. It is automatically * resized if the requested string is larger than the buffer's current capacity. @@ -501,8 +492,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * </ul> * </p> * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return The value of the field as a <code>long</code>. */ @@ -534,8 +524,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * </ul> * </p> * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return The value of the field as a <code>double</code>. */ @@ -556,8 +545,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * result to <code>short</code>. * </p> * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return The value of the field as a <code>short</code>. */ @@ -573,8 +561,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * result to <code>int</code>. * </p> * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return The value of the field as an <code>int</code>. */ @@ -590,8 +577,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * result to <code>float</code>. * </p> * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return The value of the field as an <code>float</code>. */ @@ -603,8 +589,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * Copies a byte array into the field at the specified row and column index. * * @param value The value to store. - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return True if successful. */ @@ -621,8 +606,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * Copies a string into the field at the specified row and column index. * * @param value The value to store. - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return True if successful. */ @@ -639,8 +623,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * Puts a long integer into the field at the specified row and column index. * * @param value The value to store. - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return True if successful. */ @@ -658,8 +641,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * specified row and column index. * * @param value The value to store. - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return True if successful. */ @@ -675,8 +657,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { /** * Puts a null value into the field at the specified row and column index. * - * @param row The zero-based row index, relative to the cursor window's - * start position ({@link #getStartPosition()}). + * @param row The zero-based row index. * @param column The zero-based column index. * @return True if successful. */ diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java index 8e6f69971a65..a10ca1502a77 100644 --- a/core/java/android/database/DatabaseUtils.java +++ b/core/java/android/database/DatabaseUtils.java @@ -237,7 +237,8 @@ public class DatabaseUtils { return Cursor.FIELD_TYPE_BLOB; } else if (obj instanceof Float || obj instanceof Double) { return Cursor.FIELD_TYPE_FLOAT; - } else if (obj instanceof Long || obj instanceof Integer) { + } else if (obj instanceof Long || obj instanceof Integer + || obj instanceof Short || obj instanceof Byte) { return Cursor.FIELD_TYPE_INTEGER; } else { return Cursor.FIELD_TYPE_STRING; @@ -245,6 +246,82 @@ public class DatabaseUtils { } /** + * Fills the specified cursor window by iterating over the contents of the cursor. + * The window is filled until the cursor is exhausted or the window runs out + * of space. + * + * The original position of the cursor is left unchanged by this operation. + * + * @param cursor The cursor that contains the data to put in the window. + * @param position The start position for filling the window. + * @param window The window to fill. + * @hide + */ + public static void cursorFillWindow(final Cursor cursor, + int position, final CursorWindow window) { + if (position < 0 || position >= cursor.getCount()) { + return; + } + window.acquireReference(); + try { + final int oldPos = cursor.getPosition(); + final int numColumns = cursor.getColumnCount(); + window.clear(); + window.setStartPosition(position); + window.setNumColumns(numColumns); + if (cursor.moveToPosition(position)) { + do { + if (!window.allocRow()) { + break; + } + for (int i = 0; i < numColumns; i++) { + final int type = cursor.getType(i); + final boolean success; + switch (type) { + case Cursor.FIELD_TYPE_NULL: + success = window.putNull(position, i); + break; + + case Cursor.FIELD_TYPE_INTEGER: + success = window.putLong(cursor.getLong(i), position, i); + break; + + case Cursor.FIELD_TYPE_FLOAT: + success = window.putDouble(cursor.getDouble(i), position, i); + break; + + case Cursor.FIELD_TYPE_BLOB: { + final byte[] value = cursor.getBlob(i); + success = value != null ? window.putBlob(value, position, i) + : window.putNull(position, i); + break; + } + + default: // assume value is convertible to String + case Cursor.FIELD_TYPE_STRING: { + final String value = cursor.getString(i); + success = value != null ? window.putString(value, position, i) + : window.putNull(position, i); + break; + } + } + if (!success) { + window.freeLastRow(); + break; + } + } + position += 1; + } while (cursor.moveToNext()); + } + cursor.moveToPosition(oldPos); + } catch (IllegalStateException e){ + // simply ignore it + } finally { + window.releaseReference(); + } + } + + /** * Appends an SQL string to the given StringBuilder, including the opening * and closing single quotes. Any single quotes internal to sqlString will * be escaped. |