diff options
author | Vasu Nori <vnori@google.com> | 2010-05-18 11:54:31 -0700 |
---|---|---|
committer | Vasu Nori <vnori@google.com> | 2010-06-02 17:40:41 -0700 |
commit | 8b0dd7da360d70920a37802eb455ba41500d3b45 (patch) | |
tree | d31a63e67bbfad53c2dfe4002795b73286b7c361 | |
parent | 3e7432f823b9f0457e935614787cff4eb71a8f2b (diff) | |
download | frameworks_base-8b0dd7da360d70920a37802eb455ba41500d3b45.zip frameworks_base-8b0dd7da360d70920a37802eb455ba41500d3b45.tar.gz frameworks_base-8b0dd7da360d70920a37802eb455ba41500d3b45.tar.bz2 |
add API to Cursor to get column value type
Change-Id: I3ef1bcdb2eb1c45f68e829ccb6e3ecde28076591
-rw-r--r-- | api/current.xml | 132 | ||||
-rw-r--r-- | core/java/android/database/AbstractCursor.java | 4 | ||||
-rw-r--r-- | core/java/android/database/AbstractWindowedCursor.java | 55 | ||||
-rw-r--r-- | core/java/android/database/Cursor.java | 40 | ||||
-rw-r--r-- | core/java/android/database/CursorWindow.java | 68 | ||||
-rw-r--r-- | core/java/android/database/CursorWrapper.java | 4 | ||||
-rw-r--r-- | core/java/android/database/DatabaseUtils.java | 31 | ||||
-rw-r--r-- | core/java/android/database/MatrixCursor.java | 5 | ||||
-rw-r--r-- | core/java/android/database/MergeCursor.java | 5 | ||||
-rw-r--r-- | core/java/com/android/internal/database/SortCursor.java | 5 | ||||
-rw-r--r-- | core/jni/android_database_CursorWindow.cpp | 17 | ||||
-rw-r--r-- | include/binder/CursorWindow.h | 20 | ||||
-rw-r--r-- | test-runner/src/android/test/mock/MockCursor.java | 4 |
13 files changed, 306 insertions, 84 deletions
diff --git a/api/current.xml b/api/current.xml index 2b31a64..bafbb68 100644 --- a/api/current.xml +++ b/api/current.xml @@ -55658,6 +55658,19 @@ <parameter name="column" type="int"> </parameter> </method> +<method name="getType" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="column" type="int"> +</parameter> +</method> <method name="getUpdatedField" return="java.lang.Object" abstract="false" @@ -56681,6 +56694,19 @@ <parameter name="columnIndex" type="int"> </parameter> </method> +<method name="getType" + return="int" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="columnIndex" type="int"> +</parameter> +</method> <method name="getWantsAllOnMoveCalls" return="boolean" abstract="true" @@ -56921,6 +56947,61 @@ <parameter name="observer" type="android.database.DataSetObserver"> </parameter> </method> +<field name="FIELD_TYPE_BLOB" + type="int" + transient="false" + volatile="false" + value="4" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="FIELD_TYPE_FLOAT" + type="int" + transient="false" + volatile="false" + value="2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="FIELD_TYPE_INTEGER" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="FIELD_TYPE_NULL" + type="int" + transient="false" + volatile="false" + value="0" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="FIELD_TYPE_STRING" + type="int" + transient="false" + volatile="false" + value="3" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> </interface> <class name="CursorIndexOutOfBoundsException" extends="java.lang.IndexOutOfBoundsException" @@ -57278,6 +57359,21 @@ <parameter name="col" type="int"> </parameter> </method> +<method name="getType" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="row" type="int"> +</parameter> +<parameter name="col" type="int"> +</parameter> +</method> <method name="isBlob" return="boolean" abstract="false" @@ -57285,7 +57381,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="row" type="int"> @@ -57300,7 +57396,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="row" type="int"> @@ -57315,7 +57411,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="row" type="int"> @@ -57330,7 +57426,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="row" type="int"> @@ -57345,7 +57441,7 @@ synchronized="false" static="false" final="false" - deprecated="not deprecated" + deprecated="deprecated" visibility="public" > <parameter name="row" type="int"> @@ -57756,6 +57852,19 @@ <parameter name="columnIndex" type="int"> </parameter> </method> +<method name="getType" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="columnIndex" type="int"> +</parameter> +</method> <method name="getWantsAllOnMoveCalls" return="boolean" abstract="false" @@ -155557,6 +155666,19 @@ <parameter name="columnIndex" type="int"> </parameter> </method> +<method name="getType" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="columnIndex" type="int"> +</parameter> +</method> <method name="getWantsAllOnMoveCalls" return="boolean" abstract="false" diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java index 6170bae..b1f33ec 100644 --- a/core/java/android/database/AbstractCursor.java +++ b/core/java/android/database/AbstractCursor.java @@ -51,6 +51,10 @@ public abstract class AbstractCursor implements CrossProcessCursor { abstract public double getDouble(int column); abstract public boolean isNull(int column); + public int getType(int column) { + throw new UnsupportedOperationException(); + } + // TODO implement getBlob in all cursor types public byte[] getBlob(int column) { throw new UnsupportedOperationException("getBlob is not supported"); diff --git a/core/java/android/database/AbstractWindowedCursor.java b/core/java/android/database/AbstractWindowedCursor.java index 27a02e2..e47d9ce 100644 --- a/core/java/android/database/AbstractWindowedCursor.java +++ b/core/java/android/database/AbstractWindowedCursor.java @@ -149,63 +149,36 @@ public abstract class AbstractWindowedCursor extends AbstractCursor } } - return mWindow.isNull(mPos, columnIndex); + return mWindow.getType(mPos, columnIndex) == Cursor.FIELD_TYPE_NULL; } - public boolean isBlob(int columnIndex) - { - checkPosition(); - - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Object object = getUpdatedField(columnIndex); - return object == null || object instanceof byte[]; - } - } - - return mWindow.isBlob(mPos, columnIndex); + public boolean isBlob(int columnIndex) { + return getType(columnIndex) == Cursor.FIELD_TYPE_BLOB; } - public boolean isString(int columnIndex) - { - checkPosition(); - - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Object object = getUpdatedField(columnIndex); - return object == null || object instanceof String; - } - } - - return mWindow.isString(mPos, columnIndex); + public boolean isString(int columnIndex) { + return getType(columnIndex) == Cursor.FIELD_TYPE_STRING; } - public boolean isLong(int columnIndex) - { - checkPosition(); - - synchronized(mUpdatedRows) { - if (isFieldUpdated(columnIndex)) { - Object object = getUpdatedField(columnIndex); - return object != null && (object instanceof Integer || object instanceof Long); - } - } + public boolean isLong(int columnIndex) { + return getType(columnIndex) == Cursor.FIELD_TYPE_INTEGER; + } - return mWindow.isLong(mPos, columnIndex); + public boolean isFloat(int columnIndex) { + return getType(columnIndex) == Cursor.FIELD_TYPE_FLOAT; } - public boolean isFloat(int columnIndex) + @Override + public int getType(int columnIndex) { checkPosition(); - synchronized(mUpdatedRows) { if (isFieldUpdated(columnIndex)) { - Object object = getUpdatedField(columnIndex); - return object != null && (object instanceof Float || object instanceof Double); + return DatabaseUtils.getTypeOfObject(getUpdatedField(columnIndex)); } } - return mWindow.isFloat(mPos, columnIndex); + return mWindow.getType(mPos, columnIndex); } @Override diff --git a/core/java/android/database/Cursor.java b/core/java/android/database/Cursor.java index fee658a..c03c586 100644 --- a/core/java/android/database/Cursor.java +++ b/core/java/android/database/Cursor.java @@ -30,6 +30,25 @@ import java.util.Map; * threads should perform its own synchronization when using the Cursor. */ public interface Cursor { + /* + * Values returned by {@link #getType(int)}. + * These should be consistent with the corresponding types defined in CursorWindow.h + */ + /** Value returned by {@link #getType(int)} if the specified column is null */ + static final int FIELD_TYPE_NULL = 0; + + /** Value returned by {@link #getType(int)} if the specified column type is integer */ + static final int FIELD_TYPE_INTEGER = 1; + + /** Value returned by {@link #getType(int)} if the specified column type is float */ + static final int FIELD_TYPE_FLOAT = 2; + + /** Value returned by {@link #getType(int)} if the specified column type is string */ + static final int FIELD_TYPE_STRING = 3; + + /** Value returned by {@link #getType(int)} if the specified column type is blob */ + static final int FIELD_TYPE_BLOB = 4; + /** * Returns the numbers of rows in the cursor. * @@ -279,6 +298,27 @@ public interface Cursor { double getDouble(int columnIndex); /** + * Returns data type of the given column's value. + * The preferred type of the column is returned but the data may be converted to other types + * as documented in the get-type methods such as {@link #getInt(int)}, {@link #getFloat(int)} + * etc. + *<p> + * Returned column types are + * <ul> + * <li>{@link #FIELD_TYPE_NULL}</li> + * <li>{@link #FIELD_TYPE_INTEGER}</li> + * <li>{@link #FIELD_TYPE_FLOAT}</li> + * <li>{@link #FIELD_TYPE_STRING}</li> + * <li>{@link #FIELD_TYPE_BLOB}</li> + *</ul> + *</p> + * + * @param columnIndex the zero-based index of the target column. + * @return column value type + */ + int getType(int columnIndex); + + /** * Returns <code>true</code> if the value in the indicated column is null. * * @param columnIndex the zero-based index of the target column. diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java index c756825..39889b9 100644 --- a/core/java/android/database/CursorWindow.java +++ b/core/java/android/database/CursorWindow.java @@ -217,14 +217,11 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return {@code true} if given field is {@code NULL} + * @deprecated use {@link #getType(int, int)} instead */ + @Deprecated public boolean isNull(int row, int col) { - acquireReference(); - try { - return isNull_native(row - mStartPos, col); - } finally { - releaseReference(); - } + return getType(row, col) == Cursor.FIELD_TYPE_NULL; } private native boolean isNull_native(int row, int col); @@ -248,35 +245,55 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { private native byte[] getBlob_native(int row, int col); /** - * Checks if a field contains either a blob or is null. + * Returns data type of the given column's value. + *<p> + * Returned column types are + * <ul> + * <li>{@link Cursor#FIELD_TYPE_NULL}</li> + * <li>{@link Cursor#FIELD_TYPE_INTEGER}</li> + * <li>{@link Cursor#FIELD_TYPE_FLOAT}</li> + * <li>{@link Cursor#FIELD_TYPE_STRING}</li> + * <li>{@link Cursor#FIELD_TYPE_BLOB}</li> + *</ul> + *</p> * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from - * @return {@code true} if given field is {@code NULL} or a blob + * @return the value type */ - public boolean isBlob(int row, int col) { + public int getType(int row, int col) { acquireReference(); try { - return isBlob_native(row - mStartPos, col); + return getType_native(row - mStartPos, col); } finally { releaseReference(); } } /** + * Checks if a field contains either a blob or is null. + * + * @param row the row to read from, row - getStartPosition() being the actual row in the window + * @param col the column to read from + * @return {@code true} if given field is {@code NULL} or a blob + * @deprecated use {@link #getType(int, int)} instead + */ + @Deprecated + public boolean isBlob(int row, int col) { + return getType(row, col) == Cursor.FIELD_TYPE_BLOB; + } + + /** * Checks if a field contains a long * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return {@code true} if given field is a long + * @deprecated use {@link #getType(int, int)} instead */ + @Deprecated public boolean isLong(int row, int col) { - acquireReference(); - try { - return isInteger_native(row - mStartPos, col); - } finally { - releaseReference(); - } + return getType(row, col) == Cursor.FIELD_TYPE_INTEGER; } /** @@ -285,14 +302,11 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return {@code true} if given field is a float + * @deprecated use {@link #getType(int, int)} instead */ + @Deprecated public boolean isFloat(int row, int col) { - acquireReference(); - try { - return isFloat_native(row - mStartPos, col); - } finally { - releaseReference(); - } + return getType(row, col) == Cursor.FIELD_TYPE_FLOAT; } /** @@ -301,20 +315,18 @@ public class CursorWindow extends SQLiteClosable implements Parcelable { * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return {@code true} if given field is {@code NULL} or a String + * @deprecated use {@link #getType(int, int)} instead */ + @Deprecated public boolean isString(int row, int col) { - acquireReference(); - try { - return isString_native(row - mStartPos, col); - } finally { - releaseReference(); - } + return getType(row, col) == Cursor.FIELD_TYPE_STRING; } private native boolean isBlob_native(int row, int col); private native boolean isString_native(int row, int col); private native boolean isInteger_native(int row, int col); private native boolean isFloat_native(int row, int col); + private native int getType_native(int row, int col); /** * Returns a String for the given field. diff --git a/core/java/android/database/CursorWrapper.java b/core/java/android/database/CursorWrapper.java index 633b2b3..2ac9470 100644 --- a/core/java/android/database/CursorWrapper.java +++ b/core/java/android/database/CursorWrapper.java @@ -130,6 +130,10 @@ public class CursorWrapper implements Cursor { return mCursor.isLast(); } + public int getType(int columnIndex) { + return mCursor.getType(columnIndex); + } + public boolean isNull(int columnIndex) { return mCursor.isNull(columnIndex); } diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java index 9bfbb74..af93eee 100644 --- a/core/java/android/database/DatabaseUtils.java +++ b/core/java/android/database/DatabaseUtils.java @@ -193,6 +193,37 @@ public class DatabaseUtils { } /** + * Returns data type of the given object's value. + *<p> + * Returned values are + * <ul> + * <li>{@link Cursor#FIELD_TYPE_NULL}</li> + * <li>{@link Cursor#FIELD_TYPE_INTEGER}</li> + * <li>{@link Cursor#FIELD_TYPE_FLOAT}</li> + * <li>{@link Cursor#FIELD_TYPE_STRING}</li> + * <li>{@link Cursor#FIELD_TYPE_BLOB}</li> + *</ul> + *</p> + * + * @param obj the object whose value type is to be returned + * @return object value type + * @hide + */ + public static int getTypeOfObject(Object obj) { + if (obj == null) { + return Cursor.FIELD_TYPE_NULL; + } else if (obj instanceof byte[]) { + 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) { + return Cursor.FIELD_TYPE_INTEGER; + } else { + return Cursor.FIELD_TYPE_STRING; + } + } + + /** * Appends an SQL string to the given StringBuilder, including the opening * and closing single quotes. Any single quotes internal to sqlString will * be escaped. diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java index d5c3a32..5c1b968 100644 --- a/core/java/android/database/MatrixCursor.java +++ b/core/java/android/database/MatrixCursor.java @@ -272,6 +272,11 @@ public class MatrixCursor extends AbstractCursor { } @Override + public int getType(int column) { + return DatabaseUtils.getTypeOfObject(get(column)); + } + + @Override public boolean isNull(int column) { return get(column) == null; } diff --git a/core/java/android/database/MergeCursor.java b/core/java/android/database/MergeCursor.java index cb6d7ac..2c25db7 100644 --- a/core/java/android/database/MergeCursor.java +++ b/core/java/android/database/MergeCursor.java @@ -129,6 +129,11 @@ public class MergeCursor extends AbstractCursor } @Override + public int getType(int column) { + return mCursor.getType(column); + } + + @Override public boolean isNull(int column) { return mCursor.isNull(column); diff --git a/core/java/com/android/internal/database/SortCursor.java b/core/java/com/android/internal/database/SortCursor.java index 12248a2..0025512 100644 --- a/core/java/com/android/internal/database/SortCursor.java +++ b/core/java/com/android/internal/database/SortCursor.java @@ -218,6 +218,11 @@ public class SortCursor extends AbstractCursor } @Override + public int getType(int column) { + return mCursor.getType(column); + } + + @Override public boolean isNull(int column) { return mCursor.isNull(column); diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp index fba6f0f..55f5252 100644 --- a/core/jni/android_database_CursorWindow.cpp +++ b/core/jni/android_database_CursorWindow.cpp @@ -652,6 +652,22 @@ static void freeLastRow(JNIEnv * env, jobject object) { window->freeLastRow(); } +static jint getType_native(JNIEnv* env, jobject object, jint row, jint column) +{ + int32_t err; + CursorWindow * window = GET_WINDOW(env, object); + LOG_WINDOW("returning column type affinity for %d,%d from %p", row, column, window); + + field_slot_t field; + err = window->read_field_slot(row, column, &field); + if (err != 0) { + throwExceptionWithRowCol(env, row, column); + return NULL; + } + + return field.type; +} + static JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ @@ -679,6 +695,7 @@ static JNINativeMethod sMethods[] = {"isString_native", "(II)Z", (void *)isString_native}, {"isFloat_native", "(II)Z", (void *)isFloat_native}, {"isInteger_native", "(II)Z", (void *)isInteger_native}, + {"getType_native", "(II)I", (void *)getType_native}, }; int register_android_database_CursorWindow(JNIEnv * env) diff --git a/include/binder/CursorWindow.h b/include/binder/CursorWindow.h index bda0d31..4fbff2a 100644 --- a/include/binder/CursorWindow.h +++ b/include/binder/CursorWindow.h @@ -1,16 +1,16 @@ /* * Copyright (C) 2006 The Android Open Source Project * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. */ @@ -80,11 +80,11 @@ typedef struct } data; } __attribute__((packed)) field_slot_t; +#define FIELD_TYPE_NULL 0 #define FIELD_TYPE_INTEGER 1 #define FIELD_TYPE_FLOAT 2 #define FIELD_TYPE_STRING 3 #define FIELD_TYPE_BLOB 4 -#define FIELD_TYPE_NULL 5 /** * This class stores a set of rows from a database in a buffer. The begining of the @@ -170,7 +170,7 @@ public: row_slot_t * allocRowSlot(); row_slot_t * getRowSlot(int row); - + /** * return NULL if Failed to find rowSlot or * Invalid rowSlot diff --git a/test-runner/src/android/test/mock/MockCursor.java b/test-runner/src/android/test/mock/MockCursor.java index c817532..baa150a 100644 --- a/test-runner/src/android/test/mock/MockCursor.java +++ b/test-runner/src/android/test/mock/MockCursor.java @@ -191,4 +191,8 @@ public class MockCursor implements Cursor { public void unregisterDataSetObserver(DataSetObserver observer) { throw new UnsupportedOperationException("unimplemented mock method"); } + + public int getType(int columnIndex) { + throw new UnsupportedOperationException("unimplemented mock method"); + } }
\ No newline at end of file |