summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff Brown <jeffbrown@google.com> 2011-10-12 17:42:41 -0700
committer Jeff Brown <jeffbrown@google.com> 2011-10-12 22:19:42 -0700
commit80e7b80fa607e13d31d7dab68ddfd4d9f0372e38 (patch)
tree4b93f873b4a79225f623ad25e37f0c8294f06a4b
parent5e5d6d8ba04d7579df840cda055cd5dfa9d7666f (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.java46
-rw-r--r--core/java/android/database/CursorWindow.java57
-rw-r--r--core/java/android/database/DatabaseUtils.java79
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.