commonMain.io.realm.kotlin.internal.query.ObjectQuery.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of library-base-jvm Show documentation
Show all versions of library-base-jvm Show documentation
Library code for Realm Kotlin. This artifact is not supposed to be consumed directly, but through 'io.realm.kotlin:gradle-plugin:1.11.1' instead.
/*
* Copyright 2021 Realm Inc.
*
* 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 io.realm.kotlin.internal.query
import io.realm.kotlin.internal.InternalDeleteable
import io.realm.kotlin.internal.Mediator
import io.realm.kotlin.internal.Notifiable
import io.realm.kotlin.internal.Observable
import io.realm.kotlin.internal.RealmReference
import io.realm.kotlin.internal.RealmResultsImpl
import io.realm.kotlin.internal.RealmValueArgumentConverter.convertToQueryArgs
import io.realm.kotlin.internal.asInternalDeleteable
import io.realm.kotlin.internal.interop.ClassKey
import io.realm.kotlin.internal.interop.RealmInterop
import io.realm.kotlin.internal.interop.RealmQueryPointer
import io.realm.kotlin.internal.interop.RealmResultsPointer
import io.realm.kotlin.internal.interop.inputScope
import io.realm.kotlin.internal.schema.ClassMetadata
import io.realm.kotlin.notifications.ResultsChange
import io.realm.kotlin.query.RealmQuery
import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.query.RealmScalarNullableQuery
import io.realm.kotlin.query.RealmScalarQuery
import io.realm.kotlin.query.RealmSingleQuery
import io.realm.kotlin.query.Sort
import io.realm.kotlin.types.BaseRealmObject
import kotlinx.coroutines.flow.Flow
import kotlin.reflect.KClass
@Suppress("SpreadOperator", "LongParameterList")
internal class ObjectQuery constructor(
internal val realmReference: RealmReference,
private val classKey: ClassKey,
internal val clazz: KClass,
private val mediator: Mediator,
internal val queryPointer: RealmQueryPointer,
) : RealmQuery, InternalDeleteable, Observable, ResultsChange> {
private val resultsPointer: RealmResultsPointer by lazy {
RealmInterop.realm_query_find_all(queryPointer)
}
private val classMetadata: ClassMetadata? = realmReference.schemaMetadata[classKey]
internal constructor(
realmReference: RealmReference,
key: ClassKey,
clazz: KClass,
mediator: Mediator,
filter: String,
args: Array
) : this(
realmReference,
key,
clazz,
mediator,
parseQuery(realmReference, key, filter, args),
)
internal constructor(
composedQueryPointer: RealmQueryPointer,
objectQuery: ObjectQuery
) : this(
objectQuery.realmReference,
objectQuery.classKey,
objectQuery.clazz,
objectQuery.mediator,
composedQueryPointer,
)
override fun find(): RealmResults =
RealmResultsImpl(realmReference, resultsPointer, classKey, clazz, mediator)
override fun query(filter: String, vararg arguments: Any?): RealmQuery =
inputScope {
val appendedQuery = RealmInterop.realm_query_append_query(
queryPointer,
filter,
convertToQueryArgs(arguments)
)
ObjectQuery(appendedQuery, this@ObjectQuery)
}
// TODO OPTIMIZE Descriptors are added using 'append_query', which requires an actual predicate.
// This might result into query strings like "TRUEPREDICATE AND TRUEPREDICATE SORT(...)". We
// should look into how to avoid this, perhaps by exposing a different function that internally
// ignores unnecessary default predicates.
override fun sort(property: String, sortOrder: Sort): RealmQuery =
query("TRUEPREDICATE SORT($property ${sortOrder.name})")
override fun sort(
propertyAndSortOrder: Pair,
vararg additionalPropertiesAndOrders: Pair
): RealmQuery {
val (property, order) = propertyAndSortOrder
val stringBuilder = StringBuilder().append("TRUEPREDICATE SORT($property $order")
additionalPropertiesAndOrders.forEach { (extraProperty, extraOrder) ->
stringBuilder.append(", $extraProperty $extraOrder")
}
stringBuilder.append(")")
return query(stringBuilder.toString())
}
override fun distinct(property: String, vararg extraProperties: String): RealmQuery {
val stringBuilder = StringBuilder().append("TRUEPREDICATE DISTINCT($property")
extraProperties.forEach { extraProperty ->
stringBuilder.append(", $extraProperty")
}
stringBuilder.append(")")
return query(stringBuilder.toString())
}
override fun limit(limit: Int): RealmQuery = query("TRUEPREDICATE LIMIT($limit)")
override fun first(): RealmSingleQuery =
SingleQuery(realmReference, queryPointer, classKey, clazz, mediator)
override fun min(property: String, type: KClass): RealmScalarNullableQuery =
MinMaxQuery(
realmReference,
queryPointer,
mediator,
classKey,
clazz,
classMetadata!!.getOrThrow(property),
type,
AggregatorQueryType.MIN
)
override fun max(property: String, type: KClass): RealmScalarNullableQuery =
MinMaxQuery(
realmReference,
queryPointer,
mediator,
classKey,
clazz,
classMetadata!!.getOrThrow(property),
type,
AggregatorQueryType.MAX
)
override fun sum(property: String, type: KClass): RealmScalarQuery =
SumQuery(
realmReference,
queryPointer,
mediator,
classKey,
clazz,
classMetadata!!.getOrThrow(property),
type
)
override fun count(): RealmScalarQuery =
CountQuery(realmReference, queryPointer, mediator, classKey, clazz)
override fun notifiable(): Notifiable, ResultsChange> =
QueryResultNotifiable(resultsPointer, classKey, clazz, mediator)
override fun asFlow(keyPath: List?): Flow> {
val keyPathInfo = keyPath?.let { Pair(classKey, it) }
return realmReference.owner
.registerObserver(this, keyPathInfo)
}
override fun delete() {
// TODO C-API doesn't implement realm_query_delete_all so just fetch the result and delete
// that
find().asInternalDeleteable().delete()
}
override fun description(): String {
return RealmInterop.realm_query_get_description(queryPointer)
}
companion object {
private fun parseQuery(
realmReference: RealmReference,
classKey: ClassKey,
filter: String,
args: Array
): RealmQueryPointer = inputScope {
val queryArgs = convertToQueryArgs(args)
try {
RealmInterop.realm_query_parse(realmReference.dbPointer, classKey, filter, queryArgs)
} catch (e: IndexOutOfBoundsException) {
throw IllegalArgumentException(e.message, e.cause)
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy