Migrate Rx query result adapters to driver APIs
Migrate Rx query adapters by using newly added helper utility functions that can let generated code act on the connection to perform the query while returning the appropriate Rx type.
For the reactive types, Flowable and Observable the coroutine-rx bridges are used to convert from Flow to Rx. While for Single and Maybe a fromCallable builder is used along with performBlocking. This is done to maintain existing behaviour where emitter thread is controlled by subscriber, where as if we use the Coroutines Rx builders in the library, they require a Coroutine context or use Dispatchers.Default causing the actual query to be performed in a background thread not controlled by the subscriber.
Test: DaoKotlinCodeGenTest
Change-Id: I4dad5b8506c366ee3e715ee9e7e3e49ce86a0dd2
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt b/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt
index f57ed83..7c0e658 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt
@@ -222,20 +222,39 @@
}
object RoomRxJava2TypeNames {
- val RX_ROOM = XClassName.get(ROOM_PACKAGE, "RxRoom")
- val RX_ROOM_CREATE_FLOWABLE = "createFlowable"
- val RX_ROOM_CREATE_OBSERVABLE = "createObservable"
- val RX_EMPTY_RESULT_SET_EXCEPTION = XClassName.get(ROOM_PACKAGE, "EmptyResultSetException")
+ val RX2_ROOM = XClassName.get(ROOM_PACKAGE, "RxRoom")
+ val RX2_EMPTY_RESULT_SET_EXCEPTION = XClassName.get(ROOM_PACKAGE, "EmptyResultSetException")
+}
+
+object RoomRxJava2MemberNames {
+ val RX_ROOM_CREATE_FLOWABLE =
+ RoomRxJava2TypeNames.RX2_ROOM.companionMember("createFlowable", isJvmStatic = true)
+ val RX_ROOM_CREATE_OBSERVABLE =
+ RoomRxJava2TypeNames.RX2_ROOM.companionMember("createObservable", isJvmStatic = true)
+ val RX_ROOM_CREATE_SINGLE =
+ RoomRxJava2TypeNames.RX2_ROOM.companionMember("createSingle", isJvmStatic = true)
+ val RX_ROOM_CREATE_MAYBE =
+ RoomRxJava2TypeNames.RX2_ROOM.companionMember("createMaybe", isJvmStatic = true)
+ val RX_ROOM_CREATE_COMPLETABLE =
+ RoomRxJava2TypeNames.RX2_ROOM.companionMember("createCompletable", isJvmStatic = true)
}
object RoomRxJava3TypeNames {
- val RX_ROOM = XClassName.get("$ROOM_PACKAGE.rxjava3", "RxRoom")
- val RX_ROOM_CREATE_FLOWABLE = "createFlowable"
- val RX_ROOM_CREATE_OBSERVABLE = "createObservable"
- val RX_EMPTY_RESULT_SET_EXCEPTION =
+ val RX3_ROOM = XClassName.get("$ROOM_PACKAGE.rxjava3", "RxRoom")
+ val RX3_ROOM_MARKER = XClassName.get("$ROOM_PACKAGE.rxjava3", "Rx3RoomArtifactMarker")
+ val RX3_EMPTY_RESULT_SET_EXCEPTION =
XClassName.get("$ROOM_PACKAGE.rxjava3", "EmptyResultSetException")
}
+object RoomRxJava3MemberNames {
+ val RX_ROOM_CREATE_FLOWABLE = RoomRxJava3TypeNames.RX3_ROOM.packageMember("createFlowable")
+ val RX_ROOM_CREATE_OBSERVABLE = RoomRxJava3TypeNames.RX3_ROOM.packageMember("createObservable")
+ val RX_ROOM_CREATE_SINGLE = RoomRxJava3TypeNames.RX3_ROOM.packageMember("createSingle")
+ val RX_ROOM_CREATE_MAYBE = RoomRxJava3TypeNames.RX3_ROOM.packageMember("createMaybe")
+ val RX_ROOM_CREATE_COMPLETABLE =
+ RoomRxJava3TypeNames.RX3_ROOM.packageMember("createCompletable")
+}
+
object RoomPagingTypeNames {
val LIMIT_OFFSET_PAGING_SOURCE =
XClassName.get("$ROOM_PACKAGE.paging", "LimitOffsetPagingSource")
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
index 762028e..b6b1fd6 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
@@ -17,7 +17,10 @@
package androidx.room.solver
import androidx.room.compiler.codegen.XClassName
+import androidx.room.compiler.codegen.XMemberName
+import androidx.room.ext.RoomRxJava2MemberNames
import androidx.room.ext.RoomRxJava2TypeNames
+import androidx.room.ext.RoomRxJava3MemberNames
import androidx.room.ext.RoomRxJava3TypeNames
import androidx.room.ext.RxJava2TypeNames
import androidx.room.ext.RxJava3TypeNames
@@ -26,54 +29,80 @@
internal enum class RxType(
val version: RxVersion,
val className: XClassName,
- val factoryMethodName: String? = null,
+ val factoryMethodName: XMemberName,
val canBeNull: Boolean = false
) {
// RxJava2 types
RX2_FLOWABLE(
version = RxVersion.TWO,
className = RxJava2TypeNames.FLOWABLE,
- factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_FLOWABLE
+ factoryMethodName = RoomRxJava2MemberNames.RX_ROOM_CREATE_FLOWABLE
),
RX2_OBSERVABLE(
version = RxVersion.TWO,
className = RxJava2TypeNames.OBSERVABLE,
- factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_OBSERVABLE
+ factoryMethodName = RoomRxJava2MemberNames.RX_ROOM_CREATE_OBSERVABLE
),
- RX2_SINGLE(version = RxVersion.TWO, className = RxJava2TypeNames.SINGLE),
- RX2_MAYBE(version = RxVersion.TWO, className = RxJava2TypeNames.MAYBE, canBeNull = true),
- RX2_COMPLETABLE(version = RxVersion.TWO, className = RxJava2TypeNames.COMPLETABLE),
+ RX2_SINGLE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.SINGLE,
+ factoryMethodName = RoomRxJava2MemberNames.RX_ROOM_CREATE_SINGLE
+ ),
+ RX2_MAYBE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.MAYBE,
+ factoryMethodName = RoomRxJava2MemberNames.RX_ROOM_CREATE_MAYBE,
+ canBeNull = true
+ ),
+ RX2_COMPLETABLE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.COMPLETABLE,
+ factoryMethodName = RoomRxJava2MemberNames.RX_ROOM_CREATE_COMPLETABLE
+ ),
// RxJava3 types
RX3_FLOWABLE(
version = RxVersion.THREE,
className = RxJava3TypeNames.FLOWABLE,
- factoryMethodName = RoomRxJava3TypeNames.RX_ROOM_CREATE_FLOWABLE
+ factoryMethodName = RoomRxJava3MemberNames.RX_ROOM_CREATE_FLOWABLE
),
RX3_OBSERVABLE(
version = RxVersion.THREE,
className = RxJava3TypeNames.OBSERVABLE,
- factoryMethodName = RoomRxJava3TypeNames.RX_ROOM_CREATE_OBSERVABLE
+ factoryMethodName = RoomRxJava3MemberNames.RX_ROOM_CREATE_OBSERVABLE
),
- RX3_SINGLE(version = RxVersion.THREE, className = RxJava3TypeNames.SINGLE),
- RX3_MAYBE(version = RxVersion.THREE, className = RxJava3TypeNames.MAYBE, canBeNull = true),
- RX3_COMPLETABLE(version = RxVersion.THREE, className = RxJava3TypeNames.COMPLETABLE);
+ RX3_SINGLE(
+ version = RxVersion.THREE,
+ className = RxJava3TypeNames.SINGLE,
+ factoryMethodName = RoomRxJava3MemberNames.RX_ROOM_CREATE_SINGLE
+ ),
+ RX3_MAYBE(
+ version = RxVersion.THREE,
+ className = RxJava3TypeNames.MAYBE,
+ factoryMethodName = RoomRxJava3MemberNames.RX_ROOM_CREATE_MAYBE,
+ canBeNull = true
+ ),
+ RX3_COMPLETABLE(
+ version = RxVersion.THREE,
+ className = RxJava3TypeNames.COMPLETABLE,
+ factoryMethodName = RoomRxJava3MemberNames.RX_ROOM_CREATE_COMPLETABLE
+ );
fun isSingle() = this == RX2_SINGLE || this == RX3_SINGLE
}
internal enum class RxVersion(
- val rxRoomClassName: XClassName,
+ val rxMarkerClassName: XClassName,
val emptyResultExceptionClassName: XClassName,
val missingArtifactMessage: String
) {
TWO(
- rxRoomClassName = RoomRxJava2TypeNames.RX_ROOM,
- emptyResultExceptionClassName = RoomRxJava2TypeNames.RX_EMPTY_RESULT_SET_EXCEPTION,
+ rxMarkerClassName = RoomRxJava2TypeNames.RX2_ROOM,
+ emptyResultExceptionClassName = RoomRxJava2TypeNames.RX2_EMPTY_RESULT_SET_EXCEPTION,
missingArtifactMessage = ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT
),
THREE(
- rxRoomClassName = RoomRxJava3TypeNames.RX_ROOM,
- emptyResultExceptionClassName = RoomRxJava3TypeNames.RX_EMPTY_RESULT_SET_EXCEPTION,
+ rxMarkerClassName = RoomRxJava3TypeNames.RX3_ROOM_MARKER,
+ emptyResultExceptionClassName = RoomRxJava3TypeNames.RX3_EMPTY_RESULT_SET_EXCEPTION,
missingArtifactMessage = ProcessorErrors.MISSING_ROOM_RXJAVA3_ARTIFACT
)
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index 4523c50..abe96e5 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -54,9 +54,9 @@
import androidx.room.solver.binderprovider.ListenableFuturePagingSourceQueryResultBinderProvider
import androidx.room.solver.binderprovider.LiveDataQueryResultBinderProvider
import androidx.room.solver.binderprovider.PagingSourceQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxCallableQueryResultBinderProvider
import androidx.room.solver.binderprovider.RxJava2PagingSourceQueryResultBinderProvider
import androidx.room.solver.binderprovider.RxJava3PagingSourceQueryResultBinderProvider
+import androidx.room.solver.binderprovider.RxLambdaQueryResultBinderProvider
import androidx.room.solver.binderprovider.RxQueryResultBinderProvider
import androidx.room.solver.prepared.binder.PreparedQueryResultBinder
import androidx.room.solver.prepared.binderprovider.GuavaListenableFuturePreparedQueryResultBinderProvider
@@ -208,7 +208,7 @@
add(LiveDataQueryResultBinderProvider(context))
add(GuavaListenableFutureQueryResultBinderProvider(context))
addAll(RxQueryResultBinderProvider.getAll(context))
- addAll(RxCallableQueryResultBinderProvider.getAll(context))
+ addAll(RxLambdaQueryResultBinderProvider.getAll(context))
add(DataSourceQueryResultBinderProvider(context))
add(DataSourceFactoryQueryResultBinderProvider(context))
add(RxJava2PagingSourceQueryResultBinderProvider(context))
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxLambdaQueryResultBinderProvider.kt
similarity index 89%
rename from room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
rename to room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxLambdaQueryResultBinderProvider.kt
index 129241d..701cf87 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxLambdaQueryResultBinderProvider.kt
@@ -24,9 +24,9 @@
import androidx.room.solver.RxType
import androidx.room.solver.TypeAdapterExtras
import androidx.room.solver.query.result.QueryResultBinder
-import androidx.room.solver.query.result.RxCallableQueryResultBinder
+import androidx.room.solver.query.result.RxLambdaQueryResultBinder
-class RxCallableQueryResultBinderProvider
+class RxLambdaQueryResultBinderProvider
private constructor(val context: Context, private val rxType: RxType) : QueryResultBinderProvider {
override fun provide(
declared: XType,
@@ -40,7 +40,7 @@
)
val typeArg = extractTypeArg(declared)
val adapter = context.typeAdapterStore.findQueryResultAdapter(typeArg, query, extras)
- return RxCallableQueryResultBinder(rxType, typeArg, adapter)
+ return RxLambdaQueryResultBinder(rxType, typeArg, adapter)
}
override fun matches(declared: XType): Boolean =
@@ -62,10 +62,10 @@
companion object {
fun getAll(context: Context) =
listOf(RxType.RX2_SINGLE, RxType.RX2_MAYBE, RxType.RX3_SINGLE, RxType.RX3_MAYBE).map {
- RxCallableQueryResultBinderProvider(context, it)
+ RxLambdaQueryResultBinderProvider(context, it)
.requireArtifact(
context = context,
- requiredType = it.version.rxRoomClassName,
+ requiredType = it.version.rxMarkerClassName,
missingArtifactErrorMsg = it.version.missingArtifactMessage
)
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
index a592faaf..aad54a6 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
@@ -25,6 +25,7 @@
import androidx.room.solver.query.result.QueryResultBinder
import androidx.room.solver.query.result.RxQueryResultBinder
+/** Generic result binder for Rx classes that are reactive. */
class RxQueryResultBinderProvider
private constructor(context: Context, private val rxType: RxType) :
ObservableQueryResultBinderProvider(context) {
@@ -69,7 +70,7 @@
RxQueryResultBinderProvider(context, it)
.requireArtifact(
context = context,
- requiredType = it.version.rxRoomClassName,
+ requiredType = it.version.rxMarkerClassName,
missingArtifactErrorMsg = it.version.missingArtifactMessage
)
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
index 5b5a248..48dbfa5 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
@@ -29,7 +29,8 @@
PreparedQueryResultBinderProvider {
private val hasRxJavaArtifact by lazy {
- context.processingEnv.findTypeElement(rxType.version.rxRoomClassName.canonicalName) != null
+ context.processingEnv.findTypeElement(rxType.version.rxMarkerClassName.canonicalName) !=
+ null
}
override fun matches(declared: XType): Boolean =
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxLambdaQueryResultBinder.kt
similarity index 68%
rename from room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
rename to room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxLambdaQueryResultBinder.kt
index a16c91f..10973f3 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxLambdaQueryResultBinder.kt
@@ -19,20 +19,25 @@
import androidx.room.compiler.codegen.CodeLanguage
import androidx.room.compiler.codegen.VisibilityModifier
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
+import androidx.room.compiler.codegen.XTypeName
import androidx.room.compiler.codegen.XTypeSpec
import androidx.room.compiler.processing.XNullability
import androidx.room.compiler.processing.XType
import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.CallableTypeSpecBuilder
+import androidx.room.ext.InvokeWithLambdaParameter
+import androidx.room.ext.LambdaSpec
import androidx.room.ext.RoomMemberNames.DB_UTIL_QUERY
+import androidx.room.ext.SQLiteDriverTypeNames
import androidx.room.solver.CodeGenScope
import androidx.room.solver.RxType
-/** Generic Result binder for Rx classes that accept a callable. */
-internal class RxCallableQueryResultBinder(
+/** Generic result binder for Rx classes that are not reactive. */
+internal class RxLambdaQueryResultBinder(
private val rxType: RxType,
val typeArg: XType,
adapter: QueryResultAdapter?
@@ -68,7 +73,7 @@
.build()
scope.builder.apply {
if (rxType.isSingle()) {
- addStatement("return %T.createSingle(%L)", rxType.version.rxRoomClassName, callable)
+ addStatement("return %M(%L)", rxType.factoryMethodName, callable)
} else {
addStatement("return %T.fromCallable(%L)", rxType.className, callable)
}
@@ -160,4 +165,57 @@
.build()
)
}
+
+ override fun isMigratedToDriver() = adapter?.isMigratedToDriver() == true
+
+ override fun convertAndReturn(
+ sqlQueryVar: String,
+ dbProperty: XPropertySpec,
+ bindStatement: CodeGenScope.(String) -> Unit,
+ returnTypeName: XTypeName,
+ inTransaction: Boolean,
+ scope: CodeGenScope
+ ) {
+ val connectionVar = scope.getTmpVar("_connection")
+ val performBlock =
+ InvokeWithLambdaParameter(
+ scope = scope,
+ functionName = rxType.factoryMethodName,
+ argFormat = listOf("%N", "%L", "%L"),
+ args = listOf(dbProperty, /* isReadOnly= */ true, inTransaction),
+ lambdaSpec =
+ object :
+ LambdaSpec(
+ parameterTypeName = SQLiteDriverTypeNames.CONNECTION,
+ parameterName = connectionVar,
+ returnTypeName = typeArg.asTypeName(),
+ javaLambdaSyntaxAvailable = scope.javaLambdaSyntaxAvailable
+ ) {
+ override fun XCodeBlock.Builder.body(scope: CodeGenScope) {
+ val returnPrefix =
+ when (language) {
+ CodeLanguage.JAVA -> "return "
+ CodeLanguage.KOTLIN -> ""
+ }
+ val statementVar = scope.getTmpVar("_stmt")
+ addLocalVal(
+ statementVar,
+ SQLiteDriverTypeNames.STATEMENT,
+ "%L.prepare(%L)",
+ connectionVar,
+ sqlQueryVar
+ )
+ beginControlFlow("try")
+ bindStatement(scope, statementVar)
+ val outVar = scope.getTmpVar("_result")
+ adapter?.convert(outVar, statementVar, scope)
+ addStatement("$returnPrefix%L", outVar)
+ nextControlFlow("finally")
+ addStatement("%L.close()", statementVar)
+ endControlFlow()
+ }
+ }
+ )
+ scope.builder.add("return %L", performBlock)
+ }
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
index 838c502..bc8877e 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
@@ -16,12 +16,18 @@
package androidx.room.solver.query.result
+import androidx.room.compiler.codegen.CodeLanguage
import androidx.room.compiler.codegen.XCodeBlock
+import androidx.room.compiler.codegen.XCodeBlock.Builder.Companion.addLocalVal
import androidx.room.compiler.codegen.XPropertySpec
+import androidx.room.compiler.codegen.XTypeName
import androidx.room.compiler.processing.XType
import androidx.room.ext.ArrayLiteral
import androidx.room.ext.CallableTypeSpecBuilder
import androidx.room.ext.CommonTypeNames
+import androidx.room.ext.InvokeWithLambdaParameter
+import androidx.room.ext.LambdaSpec
+import androidx.room.ext.SQLiteDriverTypeNames
import androidx.room.solver.CodeGenScope
import androidx.room.solver.RxType
@@ -69,9 +75,8 @@
*queryTableNames.toTypedArray()
)
addStatement(
- "return %T.%N(%N, %L, %L, %L)",
- rxType.version.rxRoomClassName,
- rxType.factoryMethodName!!,
+ "return %M(%N, %L, %L, %L)",
+ rxType.factoryMethodName,
dbProperty,
if (inTransaction) "true" else "false",
arrayOfTableNamesLiteral,
@@ -79,4 +84,66 @@
)
}
}
+
+ override fun isMigratedToDriver() = adapter?.isMigratedToDriver() ?: false
+
+ override fun convertAndReturn(
+ sqlQueryVar: String,
+ dbProperty: XPropertySpec,
+ bindStatement: CodeGenScope.(String) -> Unit,
+ returnTypeName: XTypeName,
+ inTransaction: Boolean,
+ scope: CodeGenScope
+ ) {
+ val connectionVar = scope.getTmpVar("_connection")
+ val performBlock =
+ InvokeWithLambdaParameter(
+ scope = scope,
+ functionName = rxType.factoryMethodName,
+ argFormat = listOf("%N", "%L", "%L"),
+ args =
+ listOf(
+ dbProperty,
+ inTransaction,
+ ArrayLiteral(
+ scope.language,
+ CommonTypeNames.STRING,
+ *queryTableNames.toTypedArray()
+ )
+ ),
+ lambdaSpec =
+ object :
+ LambdaSpec(
+ parameterTypeName = SQLiteDriverTypeNames.CONNECTION,
+ parameterName = connectionVar,
+ returnTypeName = typeArg.asTypeName(),
+ javaLambdaSyntaxAvailable = scope.javaLambdaSyntaxAvailable
+ ) {
+ override fun XCodeBlock.Builder.body(scope: CodeGenScope) {
+ val returnPrefix =
+ when (language) {
+ CodeLanguage.JAVA -> "return "
+ CodeLanguage.KOTLIN -> ""
+ }
+ val statementVar = scope.getTmpVar("_stmt")
+ addLocalVal(
+ statementVar,
+ SQLiteDriverTypeNames.STATEMENT,
+ "%L.prepare(%L)",
+ connectionVar,
+ sqlQueryVar
+ )
+ beginControlFlow("try")
+ bindStatement(scope, statementVar)
+ val outVar = scope.getTmpVar("_result")
+ adapter?.convert(outVar, statementVar, scope)
+ addStatement("$returnPrefix%L", outVar)
+ nextControlFlow("finally")
+ addStatement("%L.close()", statementVar)
+ endControlFlow()
+ }
+ }
+ )
+ scope.builder.add("return %L", performBlock)
+ }
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index 0ebee23..8aa2f41 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -29,6 +29,7 @@
import androidx.room.compiler.processing.isTypeElement
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.XTestInvocation
+import androidx.room.compiler.processing.util.compileFiles
import androidx.room.compiler.processing.util.runProcessorTest
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.GuavaUtilConcurrentTypeNames
@@ -697,15 +698,20 @@
listOf(COMMON.RX2_FLOWABLE to COMMON.RX2_ROOM, COMMON.RX3_FLOWABLE to COMMON.RX3_ROOM)
.forEach { (rxTypeSrc, rxRoomSrc) ->
runProcessorTest(
- sources =
- listOf(
- COMMON.RX2_SINGLE,
- COMMON.RX3_SINGLE,
- COMMON.RX2_OBSERVABLE,
- COMMON.RX3_OBSERVABLE,
- COMMON.PUBLISHER,
- rxTypeSrc,
- rxRoomSrc
+ sources = listOf(rxTypeSrc, rxRoomSrc),
+ classpath =
+ compileFiles(
+ listOf(
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.PUBLISHER,
+ )
)
) { invocation ->
val publisher =
@@ -731,15 +737,20 @@
)
.forEach { (rxTypeSrc, rxRoomSrc, rxTypeClassName) ->
runProcessorTest(
- sources =
- listOf(
- COMMON.RX2_SINGLE,
- COMMON.RX3_SINGLE,
- COMMON.RX2_OBSERVABLE,
- COMMON.RX3_OBSERVABLE,
- COMMON.PUBLISHER,
- rxTypeSrc,
- rxRoomSrc
+ sources = listOf(rxTypeSrc, rxRoomSrc),
+ classpath =
+ compileFiles(
+ listOf(
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.PUBLISHER,
+ )
)
) { invocation ->
val flowable = invocation.processingEnv.requireTypeElement(rxTypeClassName)
@@ -761,15 +772,22 @@
)
.forEach { (rxTypeSrc, rxRoomSrc, rxTypeClassName) ->
runProcessorTest(
- sources =
- listOf(
- COMMON.RX2_SINGLE,
- COMMON.RX3_SINGLE,
- COMMON.RX2_FLOWABLE,
- COMMON.RX3_FLOWABLE,
- COMMON.PUBLISHER,
- rxTypeSrc,
- rxRoomSrc
+ sources = listOf(rxTypeSrc, rxRoomSrc),
+ classpath =
+ compileFiles(
+ listOf(
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX2_FLOWABLE,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.RX3_FLOWABLE,
+ COMMON.PUBLISHER,
+ )
)
) { invocation ->
val observable = invocation.processingEnv.requireTypeElement(rxTypeClassName)
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt b/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt
index 7f3e54e..95c2eb0 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt
@@ -31,8 +31,6 @@
import androidx.room.ext.KotlinTypeNames
import androidx.room.ext.LifecyclesTypeNames
import androidx.room.ext.ReactiveStreamsTypeNames
-import androidx.room.ext.RoomRxJava2TypeNames
-import androidx.room.ext.RoomRxJava3TypeNames
import androidx.room.ext.RxJava2TypeNames
import androidx.room.ext.RxJava3TypeNames
import androidx.room.processor.DatabaseViewProcessor
@@ -123,9 +121,7 @@
)
}
- val RX2_ROOM by lazy {
- loadJavaCode("common/input/Rx2Room.java", RoomRxJava2TypeNames.RX_ROOM.canonicalName)
- }
+ val RX2_ROOM by lazy { loadKotlinCode("common/input/Rx2Room.kt") }
val RX3_FLOWABLE by lazy {
loadJavaCode("common/input/rxjava3/Flowable.java", RxJava3TypeNames.FLOWABLE.canonicalName)
@@ -150,9 +146,7 @@
)
}
- val RX3_ROOM by lazy {
- loadJavaCode("common/input/Rx3Room.java", RoomRxJava3TypeNames.RX_ROOM.canonicalName)
- }
+ val RX3_ROOM by lazy { loadKotlinCode("common/input/Rx3Room.kt") }
val DATA_SOURCE_FACTORY by lazy { loadKotlinCode("common/input/DataSource.kt") }
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
index 02646fd..b461902 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
@@ -1982,18 +1982,6 @@
@Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
fun getMaybe(vararg arg: String?): Maybe<MyEntity>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getFlowableNullable(vararg arg: String?): Flowable<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getObservableNullable(vararg arg: String?): Observable<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getSingleNullable(vararg arg: String?): Single<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getMaybeNullable(vararg arg: String?): Maybe<MyEntity?>
}
@Entity
@@ -2010,13 +1998,19 @@
listOf(
src,
databaseSrc,
- COMMON.RX2_ROOM,
- COMMON.RX2_FLOWABLE,
- COMMON.RX2_OBSERVABLE,
- COMMON.RX2_SINGLE,
- COMMON.RX2_MAYBE,
- COMMON.PUBLISHER,
- COMMON.RX2_EMPTY_RESULT_SET_EXCEPTION
+ ),
+ compiledFiles =
+ compileFiles(
+ listOf(
+ COMMON.RX2_ROOM,
+ COMMON.RX2_FLOWABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.PUBLISHER,
+ COMMON.RX2_EMPTY_RESULT_SET_EXCEPTION
+ )
),
expectedFilePath = getTestGoldenPath(testName.methodName)
)
@@ -2044,18 +2038,6 @@
@Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
fun getMaybe(vararg arg: String?): Maybe<MyEntity>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getFlowableNullable(vararg arg: String?): Flowable<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getObservableNullable(vararg arg: String?): Observable<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getSingleNullable(vararg arg: String?): Single<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getMaybeNullable(vararg arg: String?): Maybe<MyEntity?>
}
@Entity
@@ -2072,13 +2054,19 @@
listOf(
src,
databaseSrc,
- COMMON.RX3_ROOM,
- COMMON.RX3_FLOWABLE,
- COMMON.RX3_OBSERVABLE,
- COMMON.RX3_SINGLE,
- COMMON.RX3_MAYBE,
- COMMON.PUBLISHER,
- COMMON.RX3_EMPTY_RESULT_SET_EXCEPTION
+ ),
+ compiledFiles =
+ compileFiles(
+ listOf(
+ COMMON.RX3_ROOM,
+ COMMON.RX3_FLOWABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.PUBLISHER,
+ COMMON.RX3_EMPTY_RESULT_SET_EXCEPTION
+ )
),
expectedFilePath = getTestGoldenPath(testName.methodName)
)
@@ -2119,14 +2107,19 @@
listOf(
src,
databaseSrc,
- COMMON.RX2_ROOM,
- COMMON.RX2_FLOWABLE,
- COMMON.RX2_OBSERVABLE,
- COMMON.RX2_SINGLE,
- COMMON.RX2_MAYBE,
- COMMON.RX2_COMPLETABLE,
- COMMON.PUBLISHER,
- COMMON.RX2_EMPTY_RESULT_SET_EXCEPTION
+ ),
+ compiledFiles =
+ compileFiles(
+ listOf(
+ COMMON.RX2_ROOM,
+ COMMON.RX2_FLOWABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.PUBLISHER,
+ COMMON.RX2_EMPTY_RESULT_SET_EXCEPTION
+ )
),
expectedFilePath = getTestGoldenPath(testName.methodName)
)
@@ -2167,14 +2160,19 @@
listOf(
src,
databaseSrc,
- COMMON.RX3_ROOM,
- COMMON.RX3_FLOWABLE,
- COMMON.RX3_OBSERVABLE,
- COMMON.RX3_SINGLE,
- COMMON.RX3_MAYBE,
- COMMON.RX3_COMPLETABLE,
- COMMON.PUBLISHER,
- COMMON.RX3_EMPTY_RESULT_SET_EXCEPTION
+ ),
+ compiledFiles =
+ compileFiles(
+ listOf(
+ COMMON.RX3_ROOM,
+ COMMON.RX3_FLOWABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.PUBLISHER,
+ COMMON.RX3_EMPTY_RESULT_SET_EXCEPTION
+ )
),
expectedFilePath = getTestGoldenPath(testName.methodName)
)
diff --git a/room/room-compiler/src/test/test-data/common/input/Rx2Room.java b/room/room-compiler/src/test/test-data/common/input/Rx2Room.java
deleted file mode 100644
index 9e06920..0000000
--- a/room/room-compiler/src/test/test-data/common/input/Rx2Room.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2022 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
- *
- * 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
- * limitations under the License.
- */
-
-// mock rx2 helper
-package androidx.room;
-
-import androidx.room.RoomDatabase;
-import java.util.concurrent.Callable;
-import io.reactivex.Flowable;
-import io.reactivex.Observable;
-import io.reactivex.Single;
-public class RxRoom {
- public static <T> Flowable<T> createFlowable(final RoomDatabase database,
- final boolean inTransaction, final String[] tableNames, final Callable<T> callable) {
- return null;
- }
-
- public static <T> Observable<T> createObservable(final RoomDatabase database,
- final boolean inTransaction, final String[] tableNames, final Callable<T> callable) {
- return null;
- }
-
- public static <T> Single<T> createSingle(final Callable<? extends T> callable) {
- return null;
- }
-}
diff --git a/room/room-compiler/src/test/test-data/common/input/Rx2Room.kt b/room/room-compiler/src/test/test-data/common/input/Rx2Room.kt
new file mode 100644
index 0000000..771a7c1
--- /dev/null
+++ b/room/room-compiler/src/test/test-data/common/input/Rx2Room.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 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
+ *
+ * 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
+ * limitations under the License.
+ */
+package androidx.room
+
+import androidx.sqlite.SQLiteConnection
+import io.reactivex.Completable
+import io.reactivex.Flowable
+import io.reactivex.Maybe
+import io.reactivex.Observable
+import io.reactivex.Single
+import java.util.concurrent.Callable
+
+// mock rx2 helper
+ class RxRoom {
+
+ companion object {
+
+ @JvmField
+ val NOTHING: Any = Any()
+
+ @JvmStatic
+ fun <T : Any> createFlowable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+ ): Flowable<T> {
+ TODO()
+ }
+
+ @JvmStatic
+ fun <T : Any> createObservable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+ ): Observable<T> {
+ TODO()
+ }
+
+ @JvmStatic
+ fun <T : Any> createMaybe(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+ ): Maybe<T> {
+ TODO()
+ }
+
+ @JvmStatic
+ fun createCompletable(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> Unit
+ ): Completable {
+ TODO()
+ }
+
+ @JvmStatic
+ fun <T : Any> createSingle(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+ ): Single<T> {
+ TODO()
+ }
+
+ @JvmStatic
+ fun createFlowable(database: RoomDatabase, vararg tableNames: String): Flowable<Any> {
+ TODO()
+ }
+
+ @JvmStatic
+ fun createObservable(database: RoomDatabase, vararg tableNames: String): Observable<Any> {
+ TODO()
+ }
+ }
+}
diff --git a/room/room-compiler/src/test/test-data/common/input/Rx3Room.java b/room/room-compiler/src/test/test-data/common/input/Rx3Room.java
deleted file mode 100644
index 518609d..0000000
--- a/room/room-compiler/src/test/test-data/common/input/Rx3Room.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2022 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
- *
- * 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
- * limitations under the License.
- */
-
-// mock rx3 helper
-package androidx.room.rxjava3;
-
-import androidx.room.RoomDatabase;
-import java.util.concurrent.Callable;
-import io.reactivex.rxjava3.core.Flowable;
-import io.reactivex.rxjava3.core.Observable;
-import io.reactivex.rxjava3.core.Single;
-
-public class RxRoom {
- public static <T> Flowable<T> createFlowable(final RoomDatabase database,
- final boolean inTransaction, final String[] tableNames, final Callable<T> callable) {
- return null;
- }
-
- public static <T> Observable<T> createObservable(final RoomDatabase database,
- final boolean inTransaction, final String[] tableNames, final Callable<T> callable) {
- return null;
- }
-
- public static <T> Single<T> createSingle(final Callable<? extends T> callable) {
- return null;
- }
-}
diff --git a/room/room-compiler/src/test/test-data/common/input/Rx3Room.kt b/room/room-compiler/src/test/test-data/common/input/Rx3Room.kt
new file mode 100644
index 0000000..663e479
--- /dev/null
+++ b/room/room-compiler/src/test/test-data/common/input/Rx3Room.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2024 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
+ *
+ * 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
+ * limitations under the License.
+ */
+
+// mock rx2 helper
+@file:JvmName("RxRoom")
+
+package androidx.room.rxjava3
+
+import androidx.room.RoomDatabase
+import androidx.sqlite.SQLiteConnection
+import io.reactivex.rxjava3.core.Completable
+import io.reactivex.rxjava3.core.Flowable
+import io.reactivex.rxjava3.core.Maybe
+import io.reactivex.rxjava3.core.Observable
+import io.reactivex.rxjava3.core.Single
+import java.util.concurrent.Callable
+
+class Rx3RoomArtifactMarker private constructor()
+
+@JvmField
+val NOTHING: Any = Any()
+
+fun <T : Any> createFlowable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+): Flowable<T> {
+ TODO()
+}
+
+fun <T : Any> createObservable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+): Observable<T> {
+ TODO()
+}
+
+fun <T : Any> createMaybe(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+): Maybe<T> {
+ TODO()
+}
+
+fun createCompletable(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> Unit
+): Completable {
+ TODO()
+}
+
+fun <T : Any> createSingle(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+): Single<T> {
+ TODO()
+}
+
+fun createFlowable(
+ database: RoomDatabase,
+ vararg tableNames: String
+): Flowable<Any> {
+ TODO()
+}
+
+fun <T : Any> createFlowable(
+ database: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ callable: Callable<out T>
+): Flowable<T> {
+ TODO()
+}
+
+fun createObservable(
+ database: RoomDatabase,
+ vararg tableNames: String
+): Observable<Any> {
+ TODO()
+}
+
+fun <T : Any> createObservable(
+ database: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ callable: Callable<out T>
+): Observable<T> {
+ TODO()
+}
+
+fun <T : Any> createSingle(callable: Callable<out T>): Single<T> {
+ TODO()
+}
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx2.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx2.kt
index 3ac3f8a..18e3a2b 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx2.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx2.kt
@@ -1,17 +1,15 @@
-import android.database.Cursor
-import androidx.room.EmptyResultSetException
import androidx.room.RoomDatabase
-import androidx.room.RoomSQLiteQuery
-import androidx.room.RoomSQLiteQuery.Companion.acquire
-import androidx.room.RxRoom
+import androidx.room.RxRoom.Companion.createFlowable
+import androidx.room.RxRoom.Companion.createMaybe
+import androidx.room.RxRoom.Companion.createObservable
+import androidx.room.RxRoom.Companion.createSingle
import androidx.room.util.appendPlaceholders
import androidx.room.util.getColumnIndexOrThrow
-import androidx.room.util.query
+import androidx.sqlite.SQLiteStatement
import io.reactivex.Flowable
import io.reactivex.Maybe
import io.reactivex.Observable
import io.reactivex.Single
-import java.util.concurrent.Callable
import javax.`annotation`.processing.Generated
import kotlin.Int
import kotlin.String
@@ -37,43 +35,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createFlowable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity> {
- public override fun call(): MyEntity {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createFlowable(__db, false, arrayOf("MyEntity")) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getObservable(vararg arg: String?): Observable<MyEntity> {
@@ -83,43 +73,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createObservable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity> {
- public override fun call(): MyEntity {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createObservable(__db, false, arrayOf("MyEntity")) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getSingle(vararg arg: String?): Single<MyEntity> {
@@ -129,46 +111,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createSingle(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createSingle(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- _result = null
+ _stmt.bindText(_argIndex, _item)
}
- if (_result == null) {
- throw EmptyResultSetException("Query returned empty result set: " + _statement.sql)
- }
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity?
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ _result = null
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getMaybe(vararg arg: String?): Maybe<MyEntity> {
@@ -178,230 +149,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return Maybe.fromCallable(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createMaybe(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- _result = null
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity?
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ _result = null
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getFlowableNullable(vararg arg: String?): Flowable<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
}
- return RxRoom.createFlowable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getObservableNullable(vararg arg: String?): Observable<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createObservable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getSingleNullable(vararg arg: String?): Single<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createSingle(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- if (_result == null) {
- throw EmptyResultSetException("Query returned empty result set: " + _statement.sql)
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getMaybeNullable(vararg arg: String?): Maybe<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return Maybe.fromCallable(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
}
public companion object {
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx3.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx3.kt
index 491de60..463fa8b 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx3.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx3.kt
@@ -1,17 +1,15 @@
-import android.database.Cursor
import androidx.room.RoomDatabase
-import androidx.room.RoomSQLiteQuery
-import androidx.room.RoomSQLiteQuery.Companion.acquire
-import androidx.room.rxjava3.EmptyResultSetException
-import androidx.room.rxjava3.RxRoom
+import androidx.room.rxjava3.createFlowable
+import androidx.room.rxjava3.createMaybe
+import androidx.room.rxjava3.createObservable
+import androidx.room.rxjava3.createSingle
import androidx.room.util.appendPlaceholders
import androidx.room.util.getColumnIndexOrThrow
-import androidx.room.util.query
+import androidx.sqlite.SQLiteStatement
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single
-import java.util.concurrent.Callable
import javax.`annotation`.processing.Generated
import kotlin.Int
import kotlin.String
@@ -37,43 +35,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createFlowable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity> {
- public override fun call(): MyEntity {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createFlowable(__db, false, arrayOf("MyEntity")) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getObservable(vararg arg: String?): Observable<MyEntity> {
@@ -83,43 +73,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createObservable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity> {
- public override fun call(): MyEntity {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createObservable(__db, false, arrayOf("MyEntity")) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getSingle(vararg arg: String?): Single<MyEntity> {
@@ -129,46 +111,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createSingle(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createSingle(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- _result = null
+ _stmt.bindText(_argIndex, _item)
}
- if (_result == null) {
- throw EmptyResultSetException("Query returned empty result set: " + _statement.sql)
- }
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity?
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ _result = null
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getMaybe(vararg arg: String?): Maybe<MyEntity> {
@@ -178,230 +149,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return Maybe.fromCallable(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createMaybe(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- _result = null
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity?
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ _result = null
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getFlowableNullable(vararg arg: String?): Flowable<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
}
- return RxRoom.createFlowable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getObservableNullable(vararg arg: String?): Observable<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createObservable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getSingleNullable(vararg arg: String?): Single<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createSingle(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- if (_result == null) {
- throw EmptyResultSetException("Query returned empty result set: " + _statement.sql)
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getMaybeNullable(vararg arg: String?): Maybe<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return Maybe.fromCallable(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
}
public companion object {
diff --git a/room/room-paging-rxjava2/src/main/java/androidx/room/paging/rxjava2/LimitOffsetRxPagingSource.kt b/room/room-paging-rxjava2/src/main/java/androidx/room/paging/rxjava2/LimitOffsetRxPagingSource.kt
index db0f5ae..7bd8f30 100644
--- a/room/room-paging-rxjava2/src/main/java/androidx/room/paging/rxjava2/LimitOffsetRxPagingSource.kt
+++ b/room/room-paging-rxjava2/src/main/java/androidx/room/paging/rxjava2/LimitOffsetRxPagingSource.kt
@@ -24,7 +24,7 @@
import androidx.paging.rxjava2.RxPagingSource
import androidx.room.RoomDatabase
import androidx.room.RoomSQLiteQuery
-import androidx.room.RxRoom.createSingle
+import androidx.room.RxRoom
import androidx.room.paging.util.INITIAL_ITEM_COUNT
import androidx.room.paging.util.INVALID
import androidx.room.paging.util.ThreadSafeInvalidationObserver
@@ -56,7 +56,7 @@
override fun loadSingle(params: LoadParams<Int>): Single<LoadResult<Int, Value>> {
val scheduler = Schedulers.from(db.queryExecutor)
- return createSingle {
+ return RxRoom.createSingle {
observer.registerIfNecessary(db)
val tempCount = itemCount.get()
if (tempCount == INITIAL_ITEM_COUNT) {
diff --git a/room/room-paging-rxjava3/src/main/java/androidx/room/paging/rxjava3/LimitOffsetRxPagingSource.kt b/room/room-paging-rxjava3/src/main/java/androidx/room/paging/rxjava3/LimitOffsetRxPagingSource.kt
index 6067c44..a2792a0 100644
--- a/room/room-paging-rxjava3/src/main/java/androidx/room/paging/rxjava3/LimitOffsetRxPagingSource.kt
+++ b/room/room-paging-rxjava3/src/main/java/androidx/room/paging/rxjava3/LimitOffsetRxPagingSource.kt
@@ -30,7 +30,7 @@
import androidx.room.paging.util.getClippedRefreshKey
import androidx.room.paging.util.queryDatabase
import androidx.room.paging.util.queryItemCount
-import androidx.room.rxjava3.RxRoom.createSingle
+import androidx.room.rxjava3.createSingle
import androidx.sqlite.db.SupportSQLiteQuery
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
diff --git a/room/room-rxjava2/api/restricted_current.txt b/room/room-rxjava2/api/restricted_current.txt
index 4665a60..9a2d59c 100644
--- a/room/room-rxjava2/api/restricted_current.txt
+++ b/room/room-rxjava2/api/restricted_current.txt
@@ -7,24 +7,34 @@
public class RxRoom {
ctor @Deprecated public RxRoom();
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final io.reactivex.Completable createCompletable(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,kotlin.Unit> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
method public static final io.reactivex.Flowable<java.lang.Object> createFlowable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase database, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Maybe<T> createMaybe(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
method public static final io.reactivex.Observable<java.lang.Object> createObservable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase database, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Single<T> createSingle(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Single<T> createSingle(java.util.concurrent.Callable<? extends T> callable);
field public static final androidx.room.RxRoom.Companion Companion;
field public static final Object NOTHING;
}
public static final class RxRoom.Companion {
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public io.reactivex.Completable createCompletable(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,kotlin.Unit> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
method public io.reactivex.Flowable<java.lang.Object> createFlowable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase database, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Maybe<T> createMaybe(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
method public io.reactivex.Observable<java.lang.Object> createObservable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase database, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Single<T> createSingle(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Single<T> createSingle(java.util.concurrent.Callable<? extends T> callable);
}
diff --git a/room/room-rxjava2/build.gradle b/room/room-rxjava2/build.gradle
index c49ef63..2b23d3f 100644
--- a/room/room-rxjava2/build.gradle
+++ b/room/room-rxjava2/build.gradle
@@ -36,6 +36,7 @@
implementation("androidx.arch.core:core-runtime:2.2.0")
implementation(libs.kotlinStdlib)
+ implementation(libs.kotlinCoroutinesRx2)
testImplementation(project(":kruth:kruth"))
testImplementation(libs.kotlinTest)
diff --git a/room/room-rxjava2/src/main/java/androidx/room/RxRoom.kt b/room/room-rxjava2/src/main/java/androidx/room/RxRoom.kt
index 3d3d73f..2ae5937 100644
--- a/room/room-rxjava2/src/main/java/androidx/room/RxRoom.kt
+++ b/room/room-rxjava2/src/main/java/androidx/room/RxRoom.kt
@@ -16,7 +16,11 @@
package androidx.room
import androidx.annotation.RestrictTo
+import androidx.room.coroutines.createFlow
+import androidx.room.util.performBlocking
+import androidx.sqlite.SQLiteConnection
import io.reactivex.BackpressureStrategy
+import io.reactivex.Completable
import io.reactivex.Flowable
import io.reactivex.Maybe
import io.reactivex.Observable
@@ -25,6 +29,8 @@
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.Callable
import java.util.concurrent.Executor
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.rx2.asObservable
open class RxRoom
@Deprecated("This type should not be instantiated as it contains only utility functions.")
@@ -35,6 +41,75 @@
/** Data dispatched by the publisher created by [createFlowable]. */
@JvmField val NOTHING: Any = Any()
+ /** Helper function used by generated code to create a [Flowable] */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun <T : Any> createFlowable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+ ): Flowable<T> =
+ createObservable(db, inTransaction, tableNames, block)
+ .toFlowable(BackpressureStrategy.LATEST)
+
+ /** Helper function used by generated code to create a [Observable] */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun <T : Any> createObservable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+ ): Observable<T> =
+ createFlow(db, inTransaction, tableNames, block)
+ .filterNotNull()
+ .asObservable(db.getQueryContext())
+
+ /** Helper function used by generated code to create a [Maybe] */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun <T : Any> createMaybe(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+ ): Maybe<T> = Maybe.fromCallable { performBlocking(db, isReadOnly, inTransaction, block) }
+
+ /** Helper function used by generated code to create a [Completable] */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun createCompletable(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> Unit
+ ): Completable =
+ Completable.fromAction { performBlocking(db, isReadOnly, inTransaction, block) }
+
+ /** Helper function used by generated code to create a [Single] */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun <T : Any> createSingle(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+ ): Single<T> =
+ Single.create { emitter ->
+ if (emitter.isDisposed) return@create
+ try {
+ val result = performBlocking(db, isReadOnly, inTransaction, block)
+ if (result != null) {
+ emitter.onSuccess(result)
+ } else {
+ throw EmptyResultSetException("Query returned empty result set.")
+ }
+ } catch (e: EmptyResultSetException) {
+ emitter.tryOnError(e)
+ }
+ }
+
/**
* Creates a [Flowable] that emits at least once and also re-emits whenever one of the
* observed tables is updated.
@@ -92,7 +167,7 @@
tableNames: Array<String>,
callable: Callable<out T>
): Flowable<T> {
- return createFlowable(database, false, tableNames, callable)
+ @Suppress("DEPRECATION") return createFlowable(database, false, tableNames, callable)
}
/**
@@ -101,6 +176,7 @@
*/
@JvmStatic
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ @Deprecated("No longer used by generated code.")
fun <T : Any> createFlowable(
database: RoomDatabase,
inTransaction: Boolean,
@@ -162,7 +238,7 @@
tableNames: Array<String>,
callable: Callable<out T>
): Observable<T> {
- return createObservable(database, false, tableNames, callable)
+ @Suppress("DEPRECATION") return createObservable(database, false, tableNames, callable)
}
/**
@@ -171,6 +247,7 @@
*/
@JvmStatic
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ @Deprecated("No longer used by generated code.")
fun <T : Any> createObservable(
database: RoomDatabase,
inTransaction: Boolean,
diff --git a/room/room-rxjava2/src/test/java/androidx/room/RxRoomTest.kt b/room/room-rxjava2/src/test/java/androidx/room/RxRoomTest.kt
index 32b23a8..2dcc9d5 100644
--- a/room/room-rxjava2/src/test/java/androidx/room/RxRoomTest.kt
+++ b/room/room-rxjava2/src/test/java/androidx/room/RxRoomTest.kt
@@ -21,6 +21,7 @@
import io.reactivex.functions.Consumer
import io.reactivex.observers.TestObserver
import io.reactivex.subscribers.TestSubscriber
+import java.util.concurrent.Callable
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
import org.junit.Before
@@ -138,12 +139,12 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun internalCallable_Flowable() {
val value = AtomicReference<Any>(null)
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val flowable = RxRoom.createFlowable(mDatabase, false, tables) { value.get() }
+ val flowable = RxRoom.createFlowable(mDatabase, false, tables, Callable { value.get() })
val consumer = CountingConsumer()
flowable.subscribe(consumer)
drain()
@@ -167,12 +168,12 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun internalCallable_Observable() {
val value = AtomicReference<Any>(null)
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val flowable = RxRoom.createObservable(mDatabase, false, tables) { value.get() }
+ val flowable = RxRoom.createObservable(mDatabase, false, tables, Callable { value.get() })
val consumer = CountingConsumer()
flowable.subscribe(consumer)
drain()
@@ -196,11 +197,15 @@
}
@Test
+ @Suppress("DEPRECATION")
fun exception_Flowable() {
val flowable =
- RxRoom.createFlowable<String>(mDatabase, false, arrayOf("a")) {
- throw Exception("i want exception")
- }
+ RxRoom.createFlowable<String>(
+ mDatabase,
+ false,
+ arrayOf("a"),
+ Callable { throw Exception("i want exception") }
+ )
val subscriber = TestSubscriber<String>()
flowable.subscribe(subscriber)
drain()
@@ -209,11 +214,15 @@
}
@Test
+ @Suppress("DEPRECATION")
fun exception_Observable() {
val flowable =
- RxRoom.createObservable<String>(mDatabase, false, arrayOf("a")) {
- throw Exception("i want exception")
- }
+ RxRoom.createObservable<String>(
+ mDatabase,
+ false,
+ arrayOf("a"),
+ Callable { throw Exception("i want exception") }
+ )
val observer = TestObserver<String>()
flowable.subscribe(observer)
drain()
diff --git a/room/room-rxjava3/api/restricted_current.txt b/room/room-rxjava3/api/restricted_current.txt
index 2e15c90..9b71011 100644
--- a/room/room-rxjava3/api/restricted_current.txt
+++ b/room/room-rxjava3/api/restricted_current.txt
@@ -6,10 +6,15 @@
}
public final class RxRoom {
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Flowable<T> createFlowable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static io.reactivex.rxjava3.core.Completable createCompletable(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,kotlin.Unit> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Flowable<T> createFlowable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Flowable<T> createFlowable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
method public static io.reactivex.rxjava3.core.Flowable<java.lang.Object> createFlowable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Observable<T> createObservable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Maybe<T> createMaybe(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Observable<T> createObservable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Observable<T> createObservable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
method public static io.reactivex.rxjava3.core.Observable<java.lang.Object> createObservable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Single<T> createSingle(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Single<T> createSingle(java.util.concurrent.Callable<? extends T> callable);
field public static final Object NOTHING;
}
diff --git a/room/room-rxjava3/build.gradle b/room/room-rxjava3/build.gradle
index dd068ad..96c86a1 100644
--- a/room/room-rxjava3/build.gradle
+++ b/room/room-rxjava3/build.gradle
@@ -27,7 +27,6 @@
id("AndroidXPlugin")
id("com.android.library")
id("kotlin-android")
- id("com.google.devtools.ksp")
}
dependencies {
@@ -37,6 +36,7 @@
implementation("androidx.arch.core:core-runtime:2.2.0")
implementation(libs.kotlinStdlib)
+ implementation(libs.kotlinCoroutinesRx3)
testImplementation(project(":kruth:kruth"))
testImplementation(libs.kotlinTest)
diff --git a/room/room-rxjava3/src/main/java/androidx/room/rxjava3/RxRoom.kt b/room/room-rxjava3/src/main/java/androidx/room/rxjava3/RxRoom.kt
index 4619f12..82ee4b5 100644
--- a/room/room-rxjava3/src/main/java/androidx/room/rxjava3/RxRoom.kt
+++ b/room/room-rxjava3/src/main/java/androidx/room/rxjava3/RxRoom.kt
@@ -20,7 +20,11 @@
import androidx.annotation.RestrictTo
import androidx.room.InvalidationTracker
import androidx.room.RoomDatabase
+import androidx.room.coroutines.createFlow
+import androidx.room.util.performBlocking
+import androidx.sqlite.SQLiteConnection
import io.reactivex.rxjava3.core.BackpressureStrategy
+import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.FlowableEmitter
import io.reactivex.rxjava3.core.Maybe
@@ -31,10 +35,78 @@
import io.reactivex.rxjava3.schedulers.Schedulers
import java.util.concurrent.Callable
import java.util.concurrent.Executor
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.rx3.asObservable
+
+/** Marker class used by annotation processor to identify dependency is in the classpath. */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) class Rx3RoomArtifactMarker private constructor()
/** Data dispatched by the publisher created by [createFlowable]. */
@JvmField val NOTHING: Any = Any()
+/** Helper function used by generated code to create a [Flowable] */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun <T : Any> createFlowable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+): Flowable<T> =
+ createObservable(db, inTransaction, tableNames, block).toFlowable(BackpressureStrategy.LATEST)
+
+/** Helper function used by generated code to create a [Observable] */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun <T : Any> createObservable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+): Observable<T> =
+ createFlow(db, inTransaction, tableNames, block)
+ .filterNotNull()
+ .asObservable(db.getQueryContext())
+
+/** Helper function used by generated code to create a [Maybe] */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun <T : Any> createMaybe(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+): Maybe<T> =
+ Maybe.fromCallable(Callable<T> { performBlocking(db, isReadOnly, inTransaction, block) })
+
+/** Helper function used by generated code to create a [Completable] */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun createCompletable(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> Unit
+): Completable = Completable.fromCallable { performBlocking(db, isReadOnly, inTransaction, block) }
+
+/** Helper function used by generated code to create a [Single] */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun <T : Any> createSingle(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+): Single<T> =
+ Single.create { emitter ->
+ if (emitter.isDisposed) return@create
+ try {
+ val result = performBlocking(db, isReadOnly, inTransaction, block)
+ if (result != null) {
+ emitter.onSuccess(result)
+ } else {
+ throw EmptyResultSetException("Query returned empty result set.")
+ }
+ } catch (e: EmptyResultSetException) {
+ emitter.tryOnError(e)
+ }
+ }
+
/**
* Creates a [Flowable] that emits at least once and also re-emits whenever one of the observed
* tables is updated.
@@ -82,6 +154,7 @@
* thread and will automatically block null values since RxJava3 does not like null.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+@Deprecated("No longer used by generated code.")
fun <T : Any> createFlowable(
database: RoomDatabase,
inTransaction: Boolean,
@@ -135,6 +208,7 @@
* thread and will automatically block null values since RxJava3 does not like null.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+@Deprecated("No longer used by generated code.")
fun <T : Any> createObservable(
database: RoomDatabase,
inTransaction: Boolean,
diff --git a/room/room-rxjava3/src/test/java/androidx/room/rxjava3/RxRoomTest.kt b/room/room-rxjava3/src/test/java/androidx/room/rxjava3/RxRoomTest.kt
index 256e5c2..27f5606 100644
--- a/room/room-rxjava3/src/test/java/androidx/room/rxjava3/RxRoomTest.kt
+++ b/room/room-rxjava3/src/test/java/androidx/room/rxjava3/RxRoomTest.kt
@@ -23,6 +23,7 @@
import io.reactivex.rxjava3.functions.Consumer
import io.reactivex.rxjava3.observers.TestObserver
import io.reactivex.rxjava3.subscribers.TestSubscriber
+import java.util.concurrent.Callable
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
import org.junit.Before
@@ -62,7 +63,7 @@
@Test
fun basicAddRemove_Flowable() {
- val flowable = RxRoom.createFlowable(mDatabase, "a", "b")
+ val flowable = createFlowable(mDatabase, "a", "b")
verify(mInvalidationTracker, never()).addObserver(any())
var disposable = flowable.subscribe()
verify(mInvalidationTracker).addObserver(any())
@@ -82,7 +83,7 @@
@Test
fun basicAddRemove_Observable() {
- val observable = RxRoom.createObservable(mDatabase, "a", "b")
+ val observable = createObservable(mDatabase, "a", "b")
verify(mInvalidationTracker, never()).addObserver(any())
var disposable = observable.subscribe()
verify(mInvalidationTracker).addObserver(any())
@@ -104,7 +105,7 @@
fun basicNotify_Flowable() {
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val flowable = RxRoom.createFlowable(mDatabase, *tables)
+ val flowable = createFlowable(mDatabase, *tables)
val consumer = CountingConsumer()
val disposable = flowable.subscribe(consumer)
assertThat(mAddedObservers.size).isEqualTo(1)
@@ -123,7 +124,7 @@
fun basicNotify_Observable() {
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val observable = RxRoom.createObservable(mDatabase, *tables)
+ val observable = createObservable(mDatabase, *tables)
val consumer = CountingConsumer()
val disposable = observable.subscribe(consumer)
assertThat(mAddedObservers.size).isEqualTo(1)
@@ -139,12 +140,12 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun internalCallable_Flowable() {
val value = AtomicReference<Any>(null)
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val flowable = RxRoom.createFlowable(mDatabase, false, tables) { value.get() }
+ val flowable = createFlowable(mDatabase, false, tables, Callable { value.get() })
val consumer = CountingConsumer()
val disposable = flowable.subscribe(consumer)
drain()
@@ -169,12 +170,12 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun internalCallable_Observable() {
val value = AtomicReference<Any>(null)
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val flowable = RxRoom.createObservable(mDatabase, false, tables) { value.get() }
+ val flowable = createObservable(mDatabase, false, tables, Callable { value.get() })
val consumer = CountingConsumer()
val disposable = flowable.subscribe(consumer)
drain()
@@ -199,12 +200,15 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun exception_Flowable() {
val flowable =
- RxRoom.createFlowable<String>(mDatabase, false, arrayOf("a")) {
- throw Exception("i want exception")
- }
+ createFlowable<String>(
+ mDatabase,
+ false,
+ arrayOf("a"),
+ Callable { throw Exception("i want exception") }
+ )
val subscriber = TestSubscriber<String>()
flowable.subscribe(subscriber)
drain()
@@ -212,12 +216,15 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun exception_Observable() {
val flowable =
- RxRoom.createObservable<String>(mDatabase, false, arrayOf("a")) {
- throw Exception("i want exception")
- }
+ createObservable<String>(
+ mDatabase,
+ false,
+ arrayOf("a"),
+ Callable { throw Exception("i want exception") }
+ )
val observer = TestObserver<String>()
flowable.subscribe(observer)
drain()