Fix broken Relation support in Room Paging KMP.
This CL fixes an issue in code generation in Room Paging which emerged when using @Relation with PagingSource. The solution resolves the issue by declaring a new suspend convertRows() method that can acquire a connection to perform the query.
Bug: 369136627
Test: BaseQueryTest.kt
Relnote: Revisit the newly added convertRows() method signature to be a suspend function that receives a RawRoomQuery for room-paging.
Change-Id: Ie57b558e217ce995a7d3dfe772c314aabbfcda8c
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/BooksDao.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/BooksDao.kt
index 87bb342..8fd3564 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/BooksDao.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/BooksDao.kt
@@ -17,11 +17,13 @@
package androidx.room.integration.kotlintestapp.dao
import androidx.lifecycle.LiveData
+import androidx.room.ColumnInfo
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.RawQuery
+import androidx.room.Relation
import androidx.room.RoomWarnings
import androidx.room.Transaction
import androidx.room.TypeConverters
@@ -474,4 +476,15 @@
@Upsert suspend fun upsertBookSuspendReturnId(book: Book): Long
@Upsert suspend fun upsertBooksSuspendReturnIds(books: List<Book>): List<Long>
+
+ @Transaction
+ @Query("SELECT * FROM Publisher")
+ fun getPagingSourceRelation(): androidx.paging.PagingSource<Int, PublisherRelation>
+
+ data class PublisherRelation(
+ val publisherId: String,
+ @ColumnInfo(defaultValue = "0") val name: String,
+ @Relation(parentColumn = "publisherId", entityColumn = "publisherId")
+ val relationEntity: Publisher
+ )
}
diff --git a/room/integration-tests/multiplatformtestapp/src/commonTest/kotlin/androidx/room/integration/multiplatformtestapp/test/SampleDatabase.kt b/room/integration-tests/multiplatformtestapp/src/commonTest/kotlin/androidx/room/integration/multiplatformtestapp/test/SampleDatabase.kt
index 1b0d047..81aefdb7c 100644
--- a/room/integration-tests/multiplatformtestapp/src/commonTest/kotlin/androidx/room/integration/multiplatformtestapp/test/SampleDatabase.kt
+++ b/room/integration-tests/multiplatformtestapp/src/commonTest/kotlin/androidx/room/integration/multiplatformtestapp/test/SampleDatabase.kt
@@ -243,6 +243,16 @@
@Query("SELECT * FROM StringSampleEntity1")
suspend fun getSampleManyToMany(): SampleManyAndMany
+ @Transaction
+ @Query("SELECT * FROM SampleEntity3")
+ fun getPagingSourceRelation(): androidx.paging.PagingSource<Int, SampleRelation>
+
+ data class SampleRelation(
+ val pk3: Long,
+ @ColumnInfo(defaultValue = "0") val data3: Long,
+ @Relation(parentColumn = "pk3", entityColumn = "pk3") val relationEntity: SampleEntity3
+ )
+
@Query("SELECT * FROM SampleEntity")
fun getAllIds(): androidx.paging.PagingSource<Int, SampleEntity>
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/MultiTypedPagingSourceQueryResultBinderProvider.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/MultiTypedPagingSourceQueryResultBinderProvider.kt
index 384b238..ebc088f 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/MultiTypedPagingSourceQueryResultBinderProvider.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/MultiTypedPagingSourceQueryResultBinderProvider.kt
@@ -18,9 +18,11 @@
import androidx.room.compiler.codegen.XClassName
import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XRawType
import androidx.room.compiler.processing.XType
import androidx.room.ext.CommonTypeNames
+import androidx.room.ext.CommonTypeNames.LIST
import androidx.room.ext.PagingTypeNames
import androidx.room.parser.ParsedQuery
import androidx.room.processor.Context
@@ -41,6 +43,16 @@
context.processingEnv.findType(pagingSourceTypeName.canonicalName)?.rawType
}
+ private val roomPagingSourceTypeElement by lazy {
+ context.processingEnv.requireTypeElement(roomPagingClassName)
+ }
+
+ private val convertExecutableElement by lazy {
+ roomPagingSourceTypeElement.getDeclaredMethods().first {
+ it.isSuspendFunction() && it.name == "convertRows"
+ }
+ }
+
override fun provide(
declared: XType,
query: ParsedQuery,
@@ -58,11 +70,24 @@
((listAdapter?.accessedTableNames() ?: emptyList()) + query.tables.map { it.name })
.toSet()
+ val convertRowsOverrideInfo =
+ if (pagingSourceTypeName == PagingTypeNames.PAGING_SOURCE) {
+ ConvertRowsOverrideInfo(
+ method = convertExecutableElement,
+ continuationParamName = convertExecutableElement.parameters.last().name,
+ owner =
+ context.processingEnv.getDeclaredType(roomPagingSourceTypeElement, typeArg),
+ returnTypeName = LIST.parametrizedBy(typeArg.asTypeName())
+ )
+ } else {
+ null
+ }
+
return MultiTypedPagingSourceQueryResultBinder(
listAdapter = listAdapter,
tableNames = tableNames,
className = roomPagingClassName,
- isBasePagingSource = pagingSourceTypeName == PagingTypeNames.PAGING_SOURCE
+ convertRowsOverrideInfo = convertRowsOverrideInfo
)
}
@@ -94,3 +119,11 @@
return true
}
}
+
+/** Data class used to store necessary info when generating the suspending `convertRows` method. */
+class ConvertRowsOverrideInfo(
+ val continuationParamName: String,
+ val method: XMethodElement,
+ val owner: XType,
+ val returnTypeName: XTypeName
+)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultiTypedPagingSourceQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultiTypedPagingSourceQueryResultBinder.kt
index 055401a..92d90c5 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultiTypedPagingSourceQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultiTypedPagingSourceQueryResultBinder.kt
@@ -20,6 +20,7 @@
import androidx.room.compiler.codegen.VisibilityModifier
import androidx.room.compiler.codegen.XClassName
import androidx.room.compiler.codegen.XCodeBlock
+import androidx.room.compiler.codegen.XCodeBlock.Builder.Companion.addLocalVal
import androidx.room.compiler.codegen.XFunSpec
import androidx.room.compiler.codegen.XFunSpec.Builder.Companion.addStatement
import androidx.room.compiler.codegen.XPropertySpec
@@ -28,10 +29,14 @@
import androidx.room.ext.AndroidTypeNames
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.Function1TypeSpec
+import androidx.room.ext.InvokeWithLambdaParameter
import androidx.room.ext.KotlinTypeNames
+import androidx.room.ext.LambdaSpec
+import androidx.room.ext.RoomMemberNames.DB_UTIL_PERFORM_SUSPENDING
import androidx.room.ext.RoomTypeNames.RAW_QUERY
import androidx.room.ext.SQLiteDriverTypeNames
import androidx.room.solver.CodeGenScope
+import androidx.room.solver.binderprovider.ConvertRowsOverrideInfo
/**
* This Binder binds queries directly to native Paging3 PagingSource (i.e.
@@ -42,14 +47,14 @@
private val listAdapter: ListQueryResultAdapter?,
private val tableNames: Set<String>,
className: XClassName,
- val isBasePagingSource: Boolean
+ val convertRowsOverrideInfo: ConvertRowsOverrideInfo?
) : QueryResultBinder(listAdapter) {
private val itemTypeName: XTypeName =
listAdapter?.rowAdapters?.firstOrNull()?.out?.asTypeName() ?: XTypeName.ANY_OBJECT
private val pagingSourceTypeName: XTypeName = className.parametrizedBy(itemTypeName)
- override fun isMigratedToDriver(): Boolean = isBasePagingSource
+ override fun isMigratedToDriver(): Boolean = convertRowsOverrideInfo != null
override fun convertAndReturn(
roomSQLiteQueryVar: String,
@@ -71,12 +76,26 @@
.apply {
superclass(pagingSourceTypeName)
addFunction(
- createConvertRowsMethod(
- scope = scope,
- stmtParamName = "cursor",
- stmtParamTypeName = AndroidTypeNames.CURSOR,
- rawQueryParamName = null
- )
+ XFunSpec.builder(
+ language = scope.language,
+ name = "convertRows",
+ visibility = VisibilityModifier.PROTECTED,
+ isOverride = true
+ )
+ .apply {
+ val rowsScope = scope.fork()
+ val cursorParamName = "cursor"
+ val resultVar = scope.getTmpVar("_result")
+ returns(CommonTypeNames.LIST.parametrizedBy(itemTypeName))
+ addParameter(
+ typeName = AndroidTypeNames.CURSOR,
+ name = cursorParamName
+ )
+ listAdapter?.convert(resultVar, cursorParamName, rowsScope)
+ addCode(rowsScope.generate())
+ addStatement("return %L", resultVar)
+ }
+ .build(),
)
}
.build()
@@ -92,7 +111,7 @@
inTransaction: Boolean,
scope: CodeGenScope
) {
- check(isBasePagingSource) {
+ checkNotNull(convertRowsOverrideInfo) {
"This version of `convertAndReturn` should only be called when the binder is for the " +
"base PagingSource. "
}
@@ -130,13 +149,25 @@
sqlQueryVar
)
}
- scope.builder.addLocalVariable(
- name = rawQueryVarName,
- typeName = RAW_QUERY,
- assignExpr = assignExpr
- )
+ scope.builder.apply {
+ addLocalVariable(
+ name = rawQueryVarName,
+ typeName = RAW_QUERY,
+ assignExpr = assignExpr
+ )
+ addStatement(
+ "return %L",
+ createPagingSourceSpec(
+ scope = scope,
+ rawQueryVarName = rawQueryVarName,
+ dbProperty = dbProperty,
+ stmtVarName = stmtVarName,
+ inTransaction = inTransaction
+ )
+ )
+ }
}
- CodeLanguage.KOTLIN ->
+ CodeLanguage.KOTLIN -> {
scope.builder.apply {
if (bindStatement != null) {
beginControlFlow(
@@ -162,69 +193,117 @@
)
)
}
- }
- }
-
- scope.builder.apply {
- val tableNamesList = tableNames.joinToString(", ") { "\"$it\"" }
- val statementParamName = "statement"
- val pagingSourceSpec =
- XTypeSpec.anonymousClassBuilder(
- language = language,
- argsFormat = "%L, %N, %L",
- rawQueryVarName,
- dbProperty,
- tableNamesList
- )
- .apply {
- superclass(pagingSourceTypeName)
- addFunction(
- createConvertRowsMethod(
- scope = scope,
- stmtParamName = statementParamName,
- stmtParamTypeName = SQLiteDriverTypeNames.STATEMENT,
- rawQueryParamName = rawQueryVarName
- )
+ addStatement(
+ "return %L",
+ createPagingSourceSpec(
+ scope = scope,
+ rawQueryVarName = rawQueryVarName,
+ stmtVarName = stmtVarName,
+ dbProperty = dbProperty,
+ inTransaction = false
)
- }
- .build()
- addStatement("return %L", pagingSourceSpec)
+ )
+ }
+ }
}
}
+ private fun XCodeBlock.Builder.createPagingSourceSpec(
+ scope: CodeGenScope,
+ rawQueryVarName: String,
+ stmtVarName: String,
+ dbProperty: XPropertySpec,
+ inTransaction: Boolean
+ ): XTypeSpec {
+ val tableNamesList = tableNames.joinToString(", ") { "\"$it\"" }
+ return XTypeSpec.anonymousClassBuilder(
+ language = language,
+ argsFormat = "%L, %N, %L",
+ rawQueryVarName,
+ dbProperty,
+ tableNamesList
+ )
+ .apply {
+ superclass(pagingSourceTypeName)
+ addFunction(
+ createConvertRowsMethod(
+ scope = scope,
+ dbProperty = dbProperty,
+ stmtVarName = stmtVarName,
+ inTransaction = inTransaction
+ )
+ )
+ }
+ .build()
+ }
+
private fun createConvertRowsMethod(
scope: CodeGenScope,
- stmtParamName: String,
- stmtParamTypeName: XTypeName,
- rawQueryParamName: String?
+ dbProperty: XPropertySpec,
+ stmtVarName: String,
+ inTransaction: Boolean
): XFunSpec {
- return XFunSpec.builder(
+ val resultVar = scope.getTmpVar("_result")
+ checkNotNull(convertRowsOverrideInfo)
+ return XFunSpec.overridingBuilder(
language = scope.language,
- name = "convertRows",
- visibility = VisibilityModifier.PROTECTED,
- isOverride = true
+ element = convertRowsOverrideInfo.method,
+ owner = convertRowsOverrideInfo.owner
)
.apply {
- returns(CommonTypeNames.LIST.parametrizedBy(itemTypeName))
- addParameter(typeName = stmtParamTypeName, name = stmtParamName)
- if (stmtParamTypeName == SQLiteDriverTypeNames.STATEMENT) {
- // The SQLiteStatement version requires a second parameter for backwards
- // compatibility for delegating to CursorSQLiteStatement.
- addParameter(typeName = XTypeName.PRIMITIVE_INT, name = "itemCount")
- }
- val resultVar = scope.getTmpVar("_result")
+ val limitRawQueryParamName = "limitOffsetQuery"
val rowsScope = scope.fork()
- if (stmtParamTypeName == SQLiteDriverTypeNames.STATEMENT) {
- checkNotNull(rawQueryParamName)
- addStatement(
- "%L.getBindingFunction().invoke(%L)",
- rawQueryParamName,
- stmtParamName,
+ val connectionVar = scope.getTmpVar("_connection")
+ val performBlock =
+ InvokeWithLambdaParameter(
+ scope = scope,
+ functionName = DB_UTIL_PERFORM_SUSPENDING,
+ argFormat = listOf("%N", "%L", "%L"),
+ args = listOf(dbProperty, /* isReadOnly= */ true, inTransaction),
+ continuationParamName = convertRowsOverrideInfo.continuationParamName,
+ lambdaSpec =
+ object :
+ LambdaSpec(
+ parameterTypeName = SQLiteDriverTypeNames.CONNECTION,
+ parameterName = connectionVar,
+ returnTypeName = convertRowsOverrideInfo.returnTypeName,
+ javaLambdaSyntaxAvailable = scope.javaLambdaSyntaxAvailable
+ ) {
+ override fun XCodeBlock.Builder.body(scope: CodeGenScope) {
+ val returnPrefix =
+ when (language) {
+ CodeLanguage.JAVA -> "return "
+ CodeLanguage.KOTLIN -> ""
+ }
+ val getSql =
+ when (language) {
+ CodeLanguage.JAVA -> "getSql()"
+ CodeLanguage.KOTLIN -> "sql"
+ }
+ addLocalVal(
+ stmtVarName,
+ SQLiteDriverTypeNames.STATEMENT,
+ "%L.prepare(%L.$getSql)",
+ connectionVar,
+ limitRawQueryParamName
+ )
+ addStatement(
+ "%L.getBindingFunction().invoke(%L)",
+ limitRawQueryParamName,
+ stmtVarName
+ )
+ beginControlFlow("try").apply {
+ listAdapter?.convert(resultVar, stmtVarName, scope)
+ addStatement("$returnPrefix%L", resultVar)
+ }
+ nextControlFlow("finally")
+ addStatement("%L.close()", stmtVarName)
+ endControlFlow()
+ }
+ }
)
- }
- listAdapter?.convert(resultVar, stmtParamName, rowsScope)
+ rowsScope.builder.add("return %L", performBlock)
addCode(rowsScope.generate())
- addStatement("return %L", resultVar)
}
.build()
}
diff --git a/room/room-compiler/src/test/test-data/common/input/LimitOffsetPagingSource.kt b/room/room-compiler/src/test/test-data/common/input/LimitOffsetPagingSource.kt
index a9921a2..cf90bd9 100644
--- a/room/room-compiler/src/test/test-data/common/input/LimitOffsetPagingSource.kt
+++ b/room/room-compiler/src/test/test-data/common/input/LimitOffsetPagingSource.kt
@@ -18,7 +18,7 @@
import androidx.paging.PagingState
import androidx.room.RoomDatabase
import androidx.room.RoomRawQuery
-import androidx.sqlite.SQLiteStatement
+import androidx.sqlite.SQLiteConnection
@Suppress("UNUSED_PARAMETER")
abstract class LimitOffsetPagingSource<T : Any>(
@@ -33,5 +33,5 @@
override public suspend fun load(params: LoadParams<Int>): LoadResult<Int, T> {
return LoadResult.Invalid()
}
- protected abstract fun convertRows(statement: SQLiteStatement, itemCount: Int): List<T>
+ protected abstract suspend fun convertRows(limitOffsetQuery: RoomRawQuery, itemCount: Int): List<T>
}
\ No newline at end of file
diff --git a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/ComplexDao.java b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/ComplexDao.java
index 32f9284..4af5e72 100644
--- a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/ComplexDao.java
+++ b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/ComplexDao.java
@@ -16,6 +16,7 @@
import com.google.common.util.concurrent.ListenableFuture;
import java.lang.Class;
import java.lang.Integer;
+import java.lang.Object;
import java.lang.Override;
import java.lang.String;
import java.lang.StringBuilder;
@@ -24,6 +25,7 @@
import java.util.Collections;
import java.util.List;
import javax.annotation.processing.Generated;
+import kotlin.coroutines.Continuation;
@Generated("androidx.room.RoomProcessor")
@SuppressWarnings({"unchecked", "deprecation", "removal"})
@@ -634,41 +636,47 @@
final RoomRawQuery _rawQuery = new RoomRawQuery(_sql);
return new LimitOffsetPagingSource<Child1>(_rawQuery, __db, "Child1") {
@Override
- @NonNull
- protected List<Child1> convertRows(@NonNull final SQLiteStatement statement,
- final int itemCount) {
- _rawQuery.getBindingFunction().invoke(statement);
- final int _cursorIndexOfId = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "id");
- final int _cursorIndexOfName = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "name");
- final int _cursorIndexOfSerial = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "serial");
- final int _cursorIndexOfCode = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "code");
- final List<Child1> _result = new ArrayList<Child1>();
- while (statement.step()) {
- final Child1 _item;
- final int _tmpId;
- _tmpId = (int) (statement.getLong(_cursorIndexOfId));
- final String _tmpName;
- if (statement.isNull(_cursorIndexOfName)) {
- _tmpName = null;
- } else {
- _tmpName = statement.getText(_cursorIndexOfName);
- }
- final Info _tmpInfo;
- if (!(statement.isNull(_cursorIndexOfSerial) && statement.isNull(_cursorIndexOfCode))) {
- _tmpInfo = new Info();
- _tmpInfo.serial = (int) (statement.getLong(_cursorIndexOfSerial));
- if (statement.isNull(_cursorIndexOfCode)) {
- _tmpInfo.code = null;
- } else {
- _tmpInfo.code = statement.getText(_cursorIndexOfCode);
+ protected Object convertRows(final RoomRawQuery limitOffsetQuery, final int itemCount,
+ final Continuation<? super List<? extends Child1>> arg2) {
+ return DBUtil.performSuspending(__db, true, false, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(limitOffsetQuery.getSql());
+ limitOffsetQuery.getBindingFunction().invoke(_stmt);
+ try {
+ final int _cursorIndexOfId = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "id");
+ final int _cursorIndexOfName = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "name");
+ final int _cursorIndexOfSerial = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "serial");
+ final int _cursorIndexOfCode = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "code");
+ final List<Child1> _result = new ArrayList<Child1>();
+ while (_stmt.step()) {
+ final Child1 _item;
+ final int _tmpId;
+ _tmpId = (int) (_stmt.getLong(_cursorIndexOfId));
+ final String _tmpName;
+ if (_stmt.isNull(_cursorIndexOfName)) {
+ _tmpName = null;
+ } else {
+ _tmpName = _stmt.getText(_cursorIndexOfName);
+ }
+ final Info _tmpInfo;
+ if (!(_stmt.isNull(_cursorIndexOfSerial) && _stmt.isNull(_cursorIndexOfCode))) {
+ _tmpInfo = new Info();
+ _tmpInfo.serial = (int) (_stmt.getLong(_cursorIndexOfSerial));
+ if (_stmt.isNull(_cursorIndexOfCode)) {
+ _tmpInfo.code = null;
+ } else {
+ _tmpInfo.code = _stmt.getText(_cursorIndexOfCode);
+ }
+ } else {
+ _tmpInfo = null;
+ }
+ _item = new Child1(_tmpId,_tmpName,_tmpInfo);
+ _result.add(_item);
}
- } else {
- _tmpInfo = null;
+ return _result;
+ } finally {
+ _stmt.close();
}
- _item = new Child1(_tmpId,_tmpName,_tmpInfo);
- _result.add(_item);
- }
- return _result;
+ }, arg2);
}
};
}
diff --git a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/ComplexDao.java b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/ComplexDao.java
index 6d31a43..e924379 100644
--- a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/ComplexDao.java
+++ b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/ComplexDao.java
@@ -19,6 +19,7 @@
import java.lang.Boolean;
import java.lang.Class;
import java.lang.Integer;
+import java.lang.Object;
import java.lang.Override;
import java.lang.String;
import java.lang.StringBuilder;
@@ -27,6 +28,7 @@
import java.util.Collections;
import java.util.List;
import javax.annotation.processing.Generated;
+import kotlin.coroutines.Continuation;
import kotlin.jvm.functions.Function1;
@Generated("androidx.room.RoomProcessor")
@@ -697,41 +699,51 @@
final RoomRawQuery _rawQuery = new RoomRawQuery(_sql);
return new LimitOffsetPagingSource<Child1>(_rawQuery, __db, "Child1") {
@Override
- @NonNull
- protected List<Child1> convertRows(@NonNull final SQLiteStatement statement,
- final int itemCount) {
- _rawQuery.getBindingFunction().invoke(statement);
- final int _cursorIndexOfId = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "id");
- final int _cursorIndexOfName = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "name");
- final int _cursorIndexOfSerial = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "serial");
- final int _cursorIndexOfCode = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "code");
- final List<Child1> _result = new ArrayList<Child1>();
- while (statement.step()) {
- final Child1 _item;
- final int _tmpId;
- _tmpId = (int) (statement.getLong(_cursorIndexOfId));
- final String _tmpName;
- if (statement.isNull(_cursorIndexOfName)) {
- _tmpName = null;
- } else {
- _tmpName = statement.getText(_cursorIndexOfName);
- }
- final Info _tmpInfo;
- if (!(statement.isNull(_cursorIndexOfSerial) && statement.isNull(_cursorIndexOfCode))) {
- _tmpInfo = new Info();
- _tmpInfo.serial = (int) (statement.getLong(_cursorIndexOfSerial));
- if (statement.isNull(_cursorIndexOfCode)) {
- _tmpInfo.code = null;
- } else {
- _tmpInfo.code = statement.getText(_cursorIndexOfCode);
+ protected Object convertRows(final RoomRawQuery limitOffsetQuery, final int itemCount,
+ final Continuation<? super List<? extends Child1>> arg2) {
+ return DBUtil.performSuspending(__db, true, false, new Function1<SQLiteConnection, List<Child1>>() {
+ @Override
+ @NonNull
+ public List<Child1> invoke(@NonNull final SQLiteConnection _connection) {
+ final SQLiteStatement _stmt = _connection.prepare(limitOffsetQuery.getSql());
+ limitOffsetQuery.getBindingFunction().invoke(_stmt);
+ try {
+ final int _cursorIndexOfId = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "id");
+ final int _cursorIndexOfName = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "name");
+ final int _cursorIndexOfSerial = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "serial");
+ final int _cursorIndexOfCode = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "code");
+ final List<Child1> _result = new ArrayList<Child1>();
+ while (_stmt.step()) {
+ final Child1 _item;
+ final int _tmpId;
+ _tmpId = (int) (_stmt.getLong(_cursorIndexOfId));
+ final String _tmpName;
+ if (_stmt.isNull(_cursorIndexOfName)) {
+ _tmpName = null;
+ } else {
+ _tmpName = _stmt.getText(_cursorIndexOfName);
+ }
+ final Info _tmpInfo;
+ if (!(_stmt.isNull(_cursorIndexOfSerial) && _stmt.isNull(_cursorIndexOfCode))) {
+ _tmpInfo = new Info();
+ _tmpInfo.serial = (int) (_stmt.getLong(_cursorIndexOfSerial));
+ if (_stmt.isNull(_cursorIndexOfCode)) {
+ _tmpInfo.code = null;
+ } else {
+ _tmpInfo.code = _stmt.getText(_cursorIndexOfCode);
+ }
+ } else {
+ _tmpInfo = null;
+ }
+ _item = new Child1(_tmpId,_tmpName,_tmpInfo);
+ _result.add(_item);
+ }
+ return _result;
+ } finally {
+ _stmt.close();
}
- } else {
- _tmpInfo = null;
}
- _item = new Child1(_tmpId,_tmpName,_tmpInfo);
- _result.add(_item);
- }
- return _result;
+ }, arg2);
}
};
}
diff --git a/room/room-compiler/src/test/test-data/daoWriter/output/ksp/ComplexDao.java b/room/room-compiler/src/test/test-data/daoWriter/output/ksp/ComplexDao.java
index 41bd29f..fafe000 100644
--- a/room/room-compiler/src/test/test-data/daoWriter/output/ksp/ComplexDao.java
+++ b/room/room-compiler/src/test/test-data/daoWriter/output/ksp/ComplexDao.java
@@ -16,6 +16,7 @@
import com.google.common.util.concurrent.ListenableFuture;
import java.lang.Class;
import java.lang.Integer;
+import java.lang.Object;
import java.lang.Override;
import java.lang.String;
import java.lang.StringBuilder;
@@ -24,6 +25,7 @@
import java.util.Collections;
import java.util.List;
import javax.annotation.processing.Generated;
+import kotlin.coroutines.Continuation;
@Generated("androidx.room.RoomProcessor")
@SuppressWarnings({"unchecked", "deprecation", "removal"})
@@ -630,41 +632,47 @@
final RoomRawQuery _rawQuery = new RoomRawQuery(_sql);
return new LimitOffsetPagingSource<Child1>(_rawQuery, __db, "Child1") {
@Override
- @NonNull
- protected List<Child1> convertRows(@NonNull final SQLiteStatement statement,
- final int itemCount) {
- _rawQuery.getBindingFunction().invoke(statement);
- final int _cursorIndexOfId = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "id");
- final int _cursorIndexOfName = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "name");
- final int _cursorIndexOfSerial = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "serial");
- final int _cursorIndexOfCode = SQLiteStatementUtil.getColumnIndexOrThrow(statement, "code");
- final List<Child1> _result = new ArrayList<Child1>();
- while (statement.step()) {
- final Child1 _item;
- final int _tmpId;
- _tmpId = (int) (statement.getLong(_cursorIndexOfId));
- final String _tmpName;
- if (statement.isNull(_cursorIndexOfName)) {
- _tmpName = null;
- } else {
- _tmpName = statement.getText(_cursorIndexOfName);
- }
- final Info _tmpInfo;
- if (!(statement.isNull(_cursorIndexOfSerial) && statement.isNull(_cursorIndexOfCode))) {
- _tmpInfo = new Info();
- _tmpInfo.serial = (int) (statement.getLong(_cursorIndexOfSerial));
- if (statement.isNull(_cursorIndexOfCode)) {
- _tmpInfo.code = null;
- } else {
- _tmpInfo.code = statement.getText(_cursorIndexOfCode);
+ protected Object convertRows(final RoomRawQuery limitOffsetQuery, final int itemCount,
+ final Continuation<? super List<? extends Child1>> $completion) {
+ return DBUtil.performSuspending(__db, true, false, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(limitOffsetQuery.getSql());
+ limitOffsetQuery.getBindingFunction().invoke(_stmt);
+ try {
+ final int _cursorIndexOfId = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "id");
+ final int _cursorIndexOfName = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "name");
+ final int _cursorIndexOfSerial = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "serial");
+ final int _cursorIndexOfCode = SQLiteStatementUtil.getColumnIndexOrThrow(_stmt, "code");
+ final List<Child1> _result = new ArrayList<Child1>();
+ while (_stmt.step()) {
+ final Child1 _item;
+ final int _tmpId;
+ _tmpId = (int) (_stmt.getLong(_cursorIndexOfId));
+ final String _tmpName;
+ if (_stmt.isNull(_cursorIndexOfName)) {
+ _tmpName = null;
+ } else {
+ _tmpName = _stmt.getText(_cursorIndexOfName);
+ }
+ final Info _tmpInfo;
+ if (!(_stmt.isNull(_cursorIndexOfSerial) && _stmt.isNull(_cursorIndexOfCode))) {
+ _tmpInfo = new Info();
+ _tmpInfo.serial = (int) (_stmt.getLong(_cursorIndexOfSerial));
+ if (_stmt.isNull(_cursorIndexOfCode)) {
+ _tmpInfo.code = null;
+ } else {
+ _tmpInfo.code = _stmt.getText(_cursorIndexOfCode);
+ }
+ } else {
+ _tmpInfo = null;
+ }
+ _item = new Child1(_tmpId,_tmpName,_tmpInfo);
+ _result.add(_item);
}
- } else {
- _tmpInfo = null;
+ return _result;
+ } finally {
+ _stmt.close();
}
- _item = new Child1(_tmpId,_tmpName,_tmpInfo);
- _result.add(_item);
- }
- return _result;
+ }, $completion);
}
};
}
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/multiTypedPagingSourceResultBinder.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/multiTypedPagingSourceResultBinder.kt
index eab9d14..fb9b14c 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/multiTypedPagingSourceResultBinder.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/multiTypedPagingSourceResultBinder.kt
@@ -8,6 +8,7 @@
import androidx.room.paging.LimitOffsetPagingSource
import androidx.room.paging.guava.LimitOffsetListenableFuturePagingSource
import androidx.room.util.getColumnIndexOrThrow
+import androidx.room.util.performSuspending
import androidx.sqlite.SQLiteStatement
import javax.`annotation`.processing.Generated
import kotlin.Int
@@ -37,19 +38,24 @@
val _sql: String = "SELECT pk FROM MyEntity"
val _rawQuery: RoomRawQuery = RoomRawQuery(_sql)
return object : LimitOffsetPagingSource<MyEntity>(_rawQuery, __db, "MyEntity") {
- protected override fun convertRows(statement: SQLiteStatement, itemCount: Int):
- List<MyEntity> {
- _rawQuery.getBindingFunction().invoke(statement)
- val _cursorIndexOfPk: Int = 0
- val _result: MutableList<MyEntity> = mutableListOf()
- while (statement.step()) {
- val _item: MyEntity
- val _tmpPk: Int
- _tmpPk = statement.getLong(_cursorIndexOfPk).toInt()
- _item = MyEntity(_tmpPk)
- _result.add(_item)
+ protected override suspend fun convertRows(limitOffsetQuery: RoomRawQuery, itemCount: Int):
+ List<MyEntity> = performSuspending(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(limitOffsetQuery.sql)
+ limitOffsetQuery.getBindingFunction().invoke(_stmt)
+ try {
+ val _cursorIndexOfPk: Int = 0
+ val _result: MutableList<MyEntity> = mutableListOf()
+ while (_stmt.step()) {
+ val _item: MyEntity
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ _item = MyEntity(_tmpPk)
+ _result.add(_item)
+ }
+ _result
+ } finally {
+ _stmt.close()
}
- return _result
}
}
}
@@ -61,19 +67,24 @@
_stmt.bindLong(_argIndex, gt)
}
return object : LimitOffsetPagingSource<MyEntity>(_rawQuery, __db, "MyEntity") {
- protected override fun convertRows(statement: SQLiteStatement, itemCount: Int):
- List<MyEntity> {
- _rawQuery.getBindingFunction().invoke(statement)
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(statement, "pk")
- val _result: MutableList<MyEntity> = mutableListOf()
- while (statement.step()) {
- val _item: MyEntity
- val _tmpPk: Int
- _tmpPk = statement.getLong(_cursorIndexOfPk).toInt()
- _item = MyEntity(_tmpPk)
- _result.add(_item)
+ protected override suspend fun convertRows(limitOffsetQuery: RoomRawQuery, itemCount: Int):
+ List<MyEntity> = performSuspending(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(limitOffsetQuery.sql)
+ limitOffsetQuery.getBindingFunction().invoke(_stmt)
+ try {
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _result: MutableList<MyEntity> = mutableListOf()
+ while (_stmt.step()) {
+ val _item: MyEntity
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ _item = MyEntity(_tmpPk)
+ _result.add(_item)
+ }
+ _result
+ } finally {
+ _stmt.close()
}
- return _result
}
}
}
diff --git a/room/room-paging/bcv/native/current.txt b/room/room-paging/bcv/native/current.txt
index 0fc19cc..ebce7db 100644
--- a/room/room-paging/bcv/native/current.txt
+++ b/room/room-paging/bcv/native/current.txt
@@ -18,8 +18,8 @@
open val jumpingSupported // androidx.room.paging/LimitOffsetPagingSource.jumpingSupported|{}jumpingSupported[0]
open fun <get-jumpingSupported>(): kotlin/Boolean // androidx.room.paging/LimitOffsetPagingSource.jumpingSupported.<get-jumpingSupported>|<get-jumpingSupported>(){}[0]
- open fun convertRows(androidx.sqlite/SQLiteStatement, kotlin/Int): kotlin.collections/List<#A> // androidx.room.paging/LimitOffsetPagingSource.convertRows|convertRows(androidx.sqlite.SQLiteStatement;kotlin.Int){}[0]
open fun getRefreshKey(androidx.paging/PagingState<kotlin/Int, #A>): kotlin/Int? // androidx.room.paging/LimitOffsetPagingSource.getRefreshKey|getRefreshKey(androidx.paging.PagingState<kotlin.Int,1:0>){}[0]
+ open suspend fun convertRows(androidx.room/RoomRawQuery, kotlin/Int): kotlin.collections/List<#A> // androidx.room.paging/LimitOffsetPagingSource.convertRows|convertRows(androidx.room.RoomRawQuery;kotlin.Int){}[0]
open suspend fun load(androidx.paging/PagingSource.LoadParams<kotlin/Int>): androidx.paging/PagingSource.LoadResult<kotlin/Int, #A> // androidx.room.paging/LimitOffsetPagingSource.load|load(androidx.paging.PagingSource.LoadParams<kotlin.Int>){}[0]
}
@@ -29,5 +29,5 @@
final fun <#A: kotlin/Any> (androidx.paging/PagingState<kotlin/Int, #A>).androidx.room.paging.util/getClippedRefreshKey(): kotlin/Int? // androidx.room.paging.util/getClippedRefreshKey|[email protected]<kotlin.Int,0:0>(){0§<kotlin.Any>}[0]
final fun androidx.room.paging.util/getLimit(androidx.paging/PagingSource.LoadParams<kotlin/Int>, kotlin/Int): kotlin/Int // androidx.room.paging.util/getLimit|getLimit(androidx.paging.PagingSource.LoadParams<kotlin.Int>;kotlin.Int){}[0]
final fun androidx.room.paging.util/getOffset(androidx.paging/PagingSource.LoadParams<kotlin/Int>, kotlin/Int, kotlin/Int): kotlin/Int // androidx.room.paging.util/getOffset|getOffset(androidx.paging.PagingSource.LoadParams<kotlin.Int>;kotlin.Int;kotlin.Int){}[0]
-final suspend fun <#A: kotlin/Any> androidx.room.paging.util/queryDatabase(androidx.paging/PagingSource.LoadParams<kotlin/Int>, androidx.room/RoomRawQuery, androidx.room/RoomDatabase, kotlin/Int, kotlin/Function2<androidx.sqlite/SQLiteStatement, kotlin/Int, kotlin.collections/List<#A>>): androidx.paging/PagingSource.LoadResult<kotlin/Int, #A> // androidx.room.paging.util/queryDatabase|queryDatabase(androidx.paging.PagingSource.LoadParams<kotlin.Int>;androidx.room.RoomRawQuery;androidx.room.RoomDatabase;kotlin.Int;kotlin.Function2<androidx.sqlite.SQLiteStatement,kotlin.Int,kotlin.collections.List<0:0>>){0§<kotlin.Any>}[0]
+final suspend fun <#A: kotlin/Any> androidx.room.paging.util/queryDatabase(androidx.paging/PagingSource.LoadParams<kotlin/Int>, androidx.room/RoomRawQuery, kotlin/Int, kotlin.coroutines/SuspendFunction2<androidx.room/RoomRawQuery, kotlin/Int, kotlin.collections/List<#A>>): androidx.paging/PagingSource.LoadResult<kotlin/Int, #A> // androidx.room.paging.util/queryDatabase|queryDatabase(androidx.paging.PagingSource.LoadParams<kotlin.Int>;androidx.room.RoomRawQuery;kotlin.Int;kotlin.coroutines.SuspendFunction2<androidx.room.RoomRawQuery,kotlin.Int,kotlin.collections.List<0:0>>){0§<kotlin.Any>}[0]
final suspend fun androidx.room.paging.util/queryItemCount(androidx.room/RoomRawQuery, androidx.room/RoomDatabase): kotlin/Int // androidx.room.paging.util/queryItemCount|queryItemCount(androidx.room.RoomRawQuery;androidx.room.RoomDatabase){}[0]
diff --git a/room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/LimitOffsetPagingSourceTest.kt b/room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/LimitOffsetPagingSourceTest.kt
index 9d2384b..34a717a 100644
--- a/room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/LimitOffsetPagingSourceTest.kt
+++ b/room/room-paging/src/androidInstrumentedTest/kotlin/androidx/room/paging/LimitOffsetPagingSourceTest.kt
@@ -29,7 +29,8 @@
import androidx.room.RoomRawQuery
import androidx.room.paging.util.getClippedRefreshKey
import androidx.room.util.getColumnIndexOrThrow
-import androidx.sqlite.SQLiteStatement
+import androidx.room.util.performSuspending
+import androidx.sqlite.use
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -774,15 +775,21 @@
db = db,
tables = arrayOf(tableName)
) {
-
- override fun convertRows(statement: SQLiteStatement, itemCount: Int): List<TestItem> {
- val stmtIndexOfId = getColumnIndexOrThrow(statement, "id")
- val data = mutableListOf<TestItem>()
- while (statement.step()) {
- val tmpId = statement.getInt(stmtIndexOfId)
- data.add(TestItem(tmpId))
+ override suspend fun convertRows(
+ limitOffsetQuery: RoomRawQuery,
+ itemCount: Int
+ ): List<TestItem> {
+ return performSuspending(db, isReadOnly = true, inTransaction = false) { connection ->
+ connection.prepare(limitOffsetQuery.sql).use { statement ->
+ val stmtIndexOfId = getColumnIndexOrThrow(statement, "id")
+ buildList {
+ while (statement.step()) {
+ val tmpId = statement.getInt(stmtIndexOfId)
+ add(TestItem(tmpId))
+ }
+ }
+ }
}
- return data
}
override fun convertRows(cursor: Cursor): List<TestItem> {
diff --git a/room/room-paging/src/androidMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.android.kt b/room/room-paging/src/androidMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.android.kt
index 0cdb47b..13120a0 100644
--- a/room/room-paging/src/androidMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.android.kt
+++ b/room/room-paging/src/androidMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.android.kt
@@ -25,8 +25,9 @@
import androidx.room.RoomSQLiteQuery
import androidx.room.paging.CommonLimitOffsetImpl.Companion.BUG_LINK
import androidx.room.paging.util.getClippedRefreshKey
-import androidx.sqlite.SQLiteStatement
+import androidx.room.util.performSuspending
import androidx.sqlite.db.SupportSQLiteQuery
+import androidx.sqlite.use
/**
* An implementation of [PagingSource] to perform a LIMIT OFFSET query
@@ -78,7 +79,15 @@
)
}
- protected actual open fun convertRows(statement: SQLiteStatement, itemCount: Int): List<Value> {
- return convertRows(SQLiteStatementCursor(statement, itemCount))
+ protected actual open suspend fun convertRows(
+ limitOffsetQuery: RoomRawQuery,
+ itemCount: Int
+ ): List<Value> {
+ return performSuspending(db, isReadOnly = true, inTransaction = false) { connection ->
+ connection.prepare(limitOffsetQuery.sql).use { statement ->
+ limitOffsetQuery.getBindingFunction().invoke(statement)
+ convertRows(SQLiteStatementCursor(statement, itemCount))
+ }
+ }
}
}
diff --git a/room/room-paging/src/commonMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.kt b/room/room-paging/src/commonMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.kt
index 7a043aa..32296b1 100644
--- a/room/room-paging/src/commonMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.kt
+++ b/room/room-paging/src/commonMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.kt
@@ -27,7 +27,6 @@
import androidx.room.paging.util.queryDatabase
import androidx.room.paging.util.queryItemCount
import androidx.room.useReaderConnection
-import androidx.sqlite.SQLiteStatement
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Job
@@ -52,13 +51,16 @@
public val itemCount: Int
- protected open fun convertRows(statement: SQLiteStatement, itemCount: Int): List<Value>
+ protected open suspend fun convertRows(
+ limitOffsetQuery: RoomRawQuery,
+ itemCount: Int
+ ): List<Value>
}
internal class CommonLimitOffsetImpl<Value : Any>(
private val tables: Array<out String>,
private val pagingSource: LimitOffsetPagingSource<Value>,
- private val convertRows: (SQLiteStatement, Int) -> List<Value>
+ private val convertRows: suspend (RoomRawQuery, Int) -> List<Value>
) {
private val db = pagingSource.db
private val sourceQuery = pagingSource.sourceQuery
@@ -116,7 +118,6 @@
queryDatabase(
params = params,
sourceQuery = sourceQuery,
- db = db,
itemCount = tempCount,
convertRows = convertRows,
)
@@ -132,7 +133,6 @@
queryDatabase(
params = params,
sourceQuery = sourceQuery,
- db = db,
itemCount = tempCount,
convertRows = convertRows
)
diff --git a/room/room-paging/src/commonMain/kotlin/androidx/room/paging/util/RoomPagingUtil.kt b/room/room-paging/src/commonMain/kotlin/androidx/room/paging/util/RoomPagingUtil.kt
index 64c6150..d08a210 100644
--- a/room/room-paging/src/commonMain/kotlin/androidx/room/paging/util/RoomPagingUtil.kt
+++ b/room/room-paging/src/commonMain/kotlin/androidx/room/paging/util/RoomPagingUtil.kt
@@ -29,7 +29,6 @@
import androidx.room.RoomDatabase
import androidx.room.RoomRawQuery
import androidx.room.useReaderConnection
-import androidx.sqlite.SQLiteStatement
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
@@ -110,9 +109,8 @@
public suspend fun <Value : Any> queryDatabase(
params: LoadParams<Int>,
sourceQuery: RoomRawQuery,
- db: RoomDatabase,
itemCount: Int,
- convertRows: (SQLiteStatement, Int) -> List<Value>
+ convertRows: suspend (RoomRawQuery, Int) -> List<Value>
): LoadResult<Int, Value> {
val key = params.key ?: 0
val limit = getLimit(params, key)
@@ -123,16 +121,13 @@
} else {
limit
}
- val limitOffsetQuery = "SELECT * FROM ( ${sourceQuery.sql} ) LIMIT $limit OFFSET $offset"
+ val limitOffsetQuery =
+ RoomRawQuery(
+ sql = "SELECT * FROM ( ${sourceQuery.sql} ) LIMIT $limit OFFSET $offset",
+ onBindStatement = sourceQuery.getBindingFunction()
+ )
- val data: List<Value> =
- db.useReaderConnection { connection ->
- connection.usePrepared(limitOffsetQuery) { stmt ->
- sourceQuery.getBindingFunction().invoke(stmt)
- convertRows(stmt, rowsCount)
- }
- }
-
+ val data: List<Value> = convertRows(limitOffsetQuery, rowsCount)
val nextPosToLoad = offset + data.size
val nextKey =
if (data.isEmpty() || data.size < limit || nextPosToLoad >= itemCount) {
diff --git a/room/room-paging/src/jvmNativeMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.jvmNative.kt b/room/room-paging/src/jvmNativeMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.jvmNative.kt
index 4094d2d..91d075a 100644
--- a/room/room-paging/src/jvmNativeMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.jvmNative.kt
+++ b/room/room-paging/src/jvmNativeMain/kotlin/androidx/room/paging/LimitOffsetPagingSource.jvmNative.kt
@@ -23,7 +23,6 @@
import androidx.room.RoomRawQuery
import androidx.room.paging.CommonLimitOffsetImpl.Companion.BUG_LINK
import androidx.room.paging.util.getClippedRefreshKey
-import androidx.sqlite.SQLiteStatement
/**
* An implementation of [PagingSource] to perform a LIMIT OFFSET query
@@ -52,7 +51,10 @@
override fun getRefreshKey(state: PagingState<Int, Value>): Int? = state.getClippedRefreshKey()
- protected actual open fun convertRows(statement: SQLiteStatement, itemCount: Int): List<Value> {
+ protected actual open suspend fun convertRows(
+ limitOffsetQuery: RoomRawQuery,
+ itemCount: Int
+ ): List<Value> {
throw NotImplementedError(
"Unexpected call to a function with no implementation that Room is suppose to " +
"generate. Please file a bug at: $BUG_LINK."