Merge "Add convenience APIs for Float, Int and Boolean in SQLiteStatement" into androidx-main
diff --git a/room/room-common/api/restricted_current.txt b/room/room-common/api/restricted_current.txt
index a618b5c..d6c9b38 100644
--- a/room/room-common/api/restricted_current.txt
+++ b/room/room-common/api/restricted_current.txt
@@ -1,6 +1,12 @@
// Signature format: 4.0
package androidx.room {
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class AmbiguousColumnResolver {
+ method public static int[][] resolve(String[] resultColumns, String[][] mappings);
+ method public static int[][] resolve(java.util.List<java.lang.String> resultColumns, String[][] mappings);
+ field public static final androidx.room.AmbiguousColumnResolver INSTANCE;
+ }
+
@kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.CLASS) public @interface AutoMigration {
method public abstract int from();
method public abstract Class<?> spec() default java.lang.Object;
diff --git a/room/room-common/src/commonMain/kotlin/androidx/room/AmbiguousColumnResolver.kt b/room/room-common/src/commonMain/kotlin/androidx/room/AmbiguousColumnResolver.kt
index c810bde..ba3536d 100644
--- a/room/room-common/src/commonMain/kotlin/androidx/room/AmbiguousColumnResolver.kt
+++ b/room/room-common/src/commonMain/kotlin/androidx/room/AmbiguousColumnResolver.kt
@@ -47,7 +47,7 @@
* are continuous.
*
*/
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
public object AmbiguousColumnResolver {
/**
@@ -61,6 +61,23 @@
*/
@JvmStatic
public fun resolve(
+ resultColumns: List<String>,
+ mappings: Array<Array<String>>
+ ): Array<IntArray> {
+ return resolve(resultColumns.toTypedArray(), mappings)
+ }
+
+ /**
+ * Maps query result column indices to result object columns.
+ *
+ * @param resultColumns The ordered result column names.
+ * @param mappings An array containing the list of result object column names that must be
+ * mapped to indices of `resultColumns`.
+ * @return An array with the same dimensions as `mappings` whose values correspond to the
+ * index in `resultColumns` that match the object column at `mappings[i][j]`.
+ */
+ @JvmStatic
+ public fun resolve(
resultColumns: Array<String>,
mappings: Array<Array<String>>
): Array<IntArray> {
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/AmbiguousColumnIndexAdapter.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/AmbiguousColumnIndexAdapter.kt
index 3090f83..31c6b80 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/AmbiguousColumnIndexAdapter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/AmbiguousColumnIndexAdapter.kt
@@ -18,7 +18,6 @@
import androidx.room.AmbiguousColumnResolver
import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XMemberName.Companion.packageMember
import androidx.room.compiler.codegen.XTypeName
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.DoubleArrayLiteral
@@ -84,24 +83,13 @@
typeName = XTypeName.getArrayName(
XTypeName.getArrayName(XTypeName.PRIMITIVE_INT)
),
- assignExpr = if (scope.useDriverApi) {
- XCodeBlock.of(
- language,
- "%T.resolve(%M(%L), %L)",
- RoomTypeNames.AMBIGUOUS_COLUMN_RESOLVER,
- RoomTypeNames.STATEMENT_UTIL.packageMember("getColumnNames"),
- cursorVarName,
- rowMappings
- )
- } else {
- XCodeBlock.of(
- language,
- "%T.resolve(%L.getColumnNames(), %L)",
- RoomTypeNames.AMBIGUOUS_COLUMN_RESOLVER,
- cursorVarName,
- rowMappings
- )
- }
+ assignExpr = XCodeBlock.of(
+ language,
+ "%T.resolve(%L.getColumnNames(), %L)",
+ RoomTypeNames.AMBIGUOUS_COLUMN_RESOLVER,
+ cursorVarName,
+ rowMappings
+ )
)
}
}
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/queryResultAdapter_map_ambiguousIndexAdapter.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/queryResultAdapter_map_ambiguousIndexAdapter.kt
index 449a95f..379cfe0 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/queryResultAdapter_map_ambiguousIndexAdapter.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/queryResultAdapter_map_ambiguousIndexAdapter.kt
@@ -4,7 +4,6 @@
import androidx.room.RoomSQLiteQuery
import androidx.room.RoomSQLiteQuery.Companion.acquire
import androidx.room.util.getColumnIndex
-import androidx.room.util.getColumnNames
import androidx.room.util.performBlocking
import androidx.room.util.query
import androidx.room.util.wrapMappedColumns
@@ -38,8 +37,9 @@
return performBlocking(__db, true, false) { _connection ->
val _stmt: SQLiteStatement = _connection.prepare(_sql)
try {
- val _cursorIndices: Array<IntArray> = AmbiguousColumnResolver.resolve(getColumnNames(_stmt),
- arrayOf(arrayOf("id", "name"), arrayOf("id", "userId", "text")))
+ val _cursorIndices: Array<IntArray> =
+ AmbiguousColumnResolver.resolve(_stmt.getColumnNames(), arrayOf(arrayOf("id", "name"),
+ arrayOf("id", "userId", "text")))
val _result: MutableMap<User, MutableList<Comment>> =
LinkedHashMap<User, MutableList<Comment>>()
while (_stmt.step()) {
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/queryResultAdapter_nestedMap_ambiguousIndexAdapter.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/queryResultAdapter_nestedMap_ambiguousIndexAdapter.kt
index 375ce65..571867b 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/queryResultAdapter_nestedMap_ambiguousIndexAdapter.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/queryResultAdapter_nestedMap_ambiguousIndexAdapter.kt
@@ -1,6 +1,5 @@
import androidx.room.AmbiguousColumnResolver
import androidx.room.RoomDatabase
-import androidx.room.util.getColumnNames
import androidx.room.util.performBlocking
import androidx.sqlite.SQLiteStatement
import java.nio.ByteBuffer
@@ -34,9 +33,9 @@
return performBlocking(__db, true, false) { _connection ->
val _stmt: SQLiteStatement = _connection.prepare(_sql)
try {
- val _cursorIndices: Array<IntArray> = AmbiguousColumnResolver.resolve(getColumnNames(_stmt),
- arrayOf(arrayOf("id", "name"), arrayOf("userId", "url", "data"), arrayOf("id", "userId",
- "text")))
+ val _cursorIndices: Array<IntArray> =
+ AmbiguousColumnResolver.resolve(_stmt.getColumnNames(), arrayOf(arrayOf("id", "name"),
+ arrayOf("userId", "url", "data"), arrayOf("id", "userId", "text")))
val _result: MutableMap<User, MutableMap<Avatar, MutableList<Comment>>> =
LinkedHashMap<User, MutableMap<Avatar, MutableList<Comment>>>()
while (_stmt.step()) {
diff --git a/room/room-runtime/api/restricted_current.txt b/room/room-runtime/api/restricted_current.txt
index 6fb1bbd..4ca2f68 100644
--- a/room/room-runtime/api/restricted_current.txt
+++ b/room/room-runtime/api/restricted_current.txt
@@ -500,7 +500,6 @@
public final class SQLiteStatementUtil {
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static int getColumnIndexOrThrow(androidx.sqlite.SQLiteStatement stmt, String name);
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static String[] getColumnNames(androidx.sqlite.SQLiteStatement statement);
}
@RestrictTo({androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX}) public final class StringUtil {
diff --git a/room/room-runtime/src/commonMain/kotlin/androidx/room/util/StatementUtil.kt b/room/room-runtime/src/commonMain/kotlin/androidx/room/util/StatementUtil.kt
index 8145bcf..cebd289 100644
--- a/room/room-runtime/src/commonMain/kotlin/androidx/room/util/StatementUtil.kt
+++ b/room/room-runtime/src/commonMain/kotlin/androidx/room/util/StatementUtil.kt
@@ -53,13 +53,3 @@
}
return -1
}
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-fun getColumnNames(statement: SQLiteStatement): Array<String> {
- val columnCount = statement.getColumnCount()
- val columnNames = mutableListOf<String>()
- for (index in 0 until columnCount) {
- columnNames.add(index, statement.getColumnName(index))
- }
- return columnNames.toTypedArray()
-}
diff --git a/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseConformanceTest.kt b/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseConformanceTest.kt
index a4621c1..92b183a 100644
--- a/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseConformanceTest.kt
+++ b/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseConformanceTest.kt
@@ -55,28 +55,65 @@
@Test
fun bindAndReadColumns() = testWithConnection { connection ->
connection.execSQL(
- "CREATE TABLE Test(integerCol INTEGER, realCol REAL, textCol TEXT, blobCol BLOB)"
+ """
+ CREATE TABLE Test(
+ integerCol_long INTEGER,
+ integerCol_int INTEGER,
+ integerCol_boolean INTEGER,
+ realCol_double REAL,
+ realCol_float REAL,
+ textCol TEXT,
+ blobCol BLOB
+ )
+ """.trimIndent()
)
- connection.prepare(
- "INSERT INTO Test (integerCol, realCol, textCol, blobCol) VALUES (?, ?, ?, ?)"
+ connection.prepare("""
+ INSERT INTO Test (
+ integerCol_long,
+ integerCol_int,
+ integerCol_boolean,
+ realCol_double,
+ realCol_float,
+ textCol,
+ blobCol
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
+ """.trimIndent()
).use {
it.bindLong(1, 3)
- it.bindDouble(2, 7.87)
- it.bindText(3, "PR")
- it.bindBlob(4, byteArrayOf(0x0F, 0x12, 0x1B))
+ it.bindInt(2, 22)
+ it.bindBoolean(3, true)
+ it.bindDouble(4, 7.87)
+ it.bindFloat(5, 9.39f)
+ it.bindText(6, "PR")
+ it.bindBlob(7, byteArrayOf(0x0F, 0x12, 0x1B))
assertThat(it.step()).isFalse() // SQLITE_DONE
}
connection.prepare("SELECT * FROM Test").use {
assertThat(it.step()).isTrue() // SQLITE_ROW
- assertThat(it.getColumnCount()).isEqualTo(4)
- assertThat(it.getColumnName(0)).isEqualTo("integerCol")
- assertThat(it.getColumnName(1)).isEqualTo("realCol")
- assertThat(it.getColumnName(2)).isEqualTo("textCol")
- assertThat(it.getColumnName(3)).isEqualTo("blobCol")
+ assertThat(it.getColumnCount()).isEqualTo(7)
+ assertThat(it.getColumnName(0)).isEqualTo("integerCol_long")
+ assertThat(it.getColumnName(1)).isEqualTo("integerCol_int")
+ assertThat(it.getColumnName(2)).isEqualTo("integerCol_boolean")
+ assertThat(it.getColumnName(3)).isEqualTo("realCol_double")
+ assertThat(it.getColumnName(4)).isEqualTo("realCol_float")
+ assertThat(it.getColumnName(5)).isEqualTo("textCol")
+ assertThat(it.getColumnName(6)).isEqualTo("blobCol")
+ assertThat(it.getColumnNames()).containsExactly(
+ "integerCol_long",
+ "integerCol_int",
+ "integerCol_boolean",
+ "realCol_double",
+ "realCol_float",
+ "textCol",
+ "blobCol"
+ ).inOrder()
assertThat(it.getLong(0)).isEqualTo(3)
- assertThat(it.getDouble(1)).isEqualTo(7.87)
- assertThat(it.getText(2)).isEqualTo("PR")
- assertThat(it.getBlob(3)).isEqualTo(byteArrayOf(0x0F, 0x12, 0x1B))
+ assertThat(it.getInt(1)).isEqualTo(22)
+ assertThat(it.getBoolean(2)).isTrue()
+ assertThat(it.getDouble(3)).isEqualTo(7.87)
+ assertThat(it.getFloat(4)).isEqualTo(9.39f)
+ assertThat(it.getText(5)).isEqualTo("PR")
+ assertThat(it.getBlob(6)).isEqualTo(byteArrayOf(0x0F, 0x12, 0x1B))
assertThat(it.step()).isFalse() // SQLITE_DONE
}
}
diff --git a/sqlite/sqlite/api/current.txt b/sqlite/sqlite/api/current.txt
index 7c8bfc7..9e31171 100644
--- a/sqlite/sqlite/api/current.txt
+++ b/sqlite/sqlite/api/current.txt
@@ -18,16 +18,23 @@
public interface SQLiteStatement {
method public void bindBlob(int index, byte[] value);
+ method public default void bindBoolean(int index, boolean value);
method public void bindDouble(int index, double value);
+ method public default void bindFloat(int index, float value);
+ method public default void bindInt(int index, int value);
method public void bindLong(int index, long value);
method public void bindNull(int index);
method public void bindText(int index, String value);
method public void clearBindings();
method public void close();
method public byte[] getBlob(int index);
+ method public default boolean getBoolean(int index);
method public int getColumnCount();
method public String getColumnName(int index);
+ method public default java.util.List<java.lang.String> getColumnNames();
method public double getDouble(int index);
+ method public default float getFloat(int index);
+ method public default int getInt(int index);
method public long getLong(int index);
method public String getText(int index);
method public boolean isNull(int index);
diff --git a/sqlite/sqlite/api/restricted_current.txt b/sqlite/sqlite/api/restricted_current.txt
index 7c8bfc7..9e31171 100644
--- a/sqlite/sqlite/api/restricted_current.txt
+++ b/sqlite/sqlite/api/restricted_current.txt
@@ -18,16 +18,23 @@
public interface SQLiteStatement {
method public void bindBlob(int index, byte[] value);
+ method public default void bindBoolean(int index, boolean value);
method public void bindDouble(int index, double value);
+ method public default void bindFloat(int index, float value);
+ method public default void bindInt(int index, int value);
method public void bindLong(int index, long value);
method public void bindNull(int index);
method public void bindText(int index, String value);
method public void clearBindings();
method public void close();
method public byte[] getBlob(int index);
+ method public default boolean getBoolean(int index);
method public int getColumnCount();
method public String getColumnName(int index);
+ method public default java.util.List<java.lang.String> getColumnNames();
method public double getDouble(int index);
+ method public default float getFloat(int index);
+ method public default int getInt(int index);
method public long getLong(int index);
method public String getText(int index);
method public boolean isNull(int index);
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
index e0f62d6..e0b16bd 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
@@ -43,6 +43,16 @@
fun bindDouble(index: Int, value: Double)
/**
+ * Binds a Float value to this statement at an index.
+ *
+ * @param index the 1-based index of the parameter to bind
+ * @param value the value to bind
+ */
+ fun bindFloat(index: Int, value: Float) {
+ bindDouble(index, value.toDouble())
+ }
+
+ /**
* Binds a Long value to this statement at an index.
*
* @param index the 1-based index of the parameter to bind
@@ -51,6 +61,26 @@
fun bindLong(index: Int, value: Long)
/**
+ * Binds a Int value to this statement at an index.
+ *
+ * @param index the 1-based index of the parameter to bind
+ * @param value the value to bind
+ */
+ fun bindInt(index: Int, value: Int) {
+ bindLong(index, value.toLong())
+ }
+
+ /**
+ * Binds a Boolean value to this statement at an index.
+ *
+ * @param index the 1-based index of the parameter to bind
+ * @param value the value to bind
+ */
+ fun bindBoolean(index: Int, value: Boolean) {
+ bindLong(index, if (value) 1L else 0L)
+ }
+
+ /**
* Binds a String value to this statement at an index.
*
* @param index the 1-based index of the parameter to bind
@@ -82,6 +112,16 @@
fun getDouble(index: Int): Double
/**
+ * Returns the value of the column at [index] as a Float.
+ *
+ * @param index the 0-based index of the column
+ * @return the value of the column
+ */
+ fun getFloat(index: Int): Float {
+ return getDouble(index).toFloat()
+ }
+
+ /**
* Returns the value of the column at [index] as a Long.
*
* @param index the 0-based index of the column
@@ -90,6 +130,26 @@
fun getLong(index: Int): Long
/**
+ * Returns the value of the column at [index] as a Int.
+ *
+ * @param index the 0-based index of the column
+ * @return the value of the column
+ */
+ fun getInt(index: Int): Int {
+ return getLong(index).toInt()
+ }
+
+ /**
+ * Returns the value of the column at [index] as a Boolean.
+ *
+ * @param index the 0-based index of the column
+ * @return the value of the column
+ */
+ fun getBoolean(index: Int): Boolean {
+ return getLong(index) != 0L
+ }
+
+ /**
* Returns the value of the column at [index] as a String.
*
* @param index the 0-based index of the column
@@ -106,7 +166,7 @@
fun isNull(index: Int): Boolean
/**
- * Returns the numbers of columns in the result of the statement.
+ * Returns the number of columns in the result of the statement.
*
* @return the number of columns
*/
@@ -121,6 +181,15 @@
fun getColumnName(index: Int): String
/**
+ * Returns the name of the columns in the result of the statement ordered by their index.
+ *
+ * @return the names of the columns
+ */
+ fun getColumnNames(): List<String> {
+ return List(getColumnCount()) { i -> getColumnName(i) }
+ }
+
+ /**
* Executes the statement and evaluates the next result row if available.
*
* A statement is initially prepared and compiled but is not executed until one or more calls