Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,16 @@ class FirebaseDatabasePlugin :
@Suppress("UNCHECKED_CAST")
private fun getQuery(arguments: Map<String, Any>): Query {
val ref = getReference(arguments)
val modifiers = arguments[Constants.MODIFIERS] as List<Map<String, Any>>
return QueryBuilder(ref, modifiers).build()
val modifiers = arguments[Constants.MODIFIERS] as List<Map<String, Any?>>
return queryFromModifiers(ref, modifiers)
}

/** Applies [modifiers]. */
private fun queryFromModifiers(
reference: DatabaseReference,
modifiers: List<Map<String, Any?>>,
): Query = QueryBuilder(reference, modifiers).build()

private fun goOnline(arguments: Map<String, Any>): Task<Void> {
val taskCompletionSource = TaskCompletionSource<Void>()

Expand Down Expand Up @@ -844,84 +850,7 @@ class FirebaseDatabasePlugin :
Log.d("FirebaseDatabase", "🔍 Kotlin: Setting up query observe for path=${request.path}")
val database = getDatabaseFromPigeonApp(app)
val reference = database.getReference(request.path)

// Apply query modifiers if any
var query: com.google.firebase.database.Query = reference
// Note: no hasOrderModifier needed — Android SDK defaults to PriorityIndex
// when no orderBy is specified, so cursors work without an explicit orderBy.

for (modifier in request.modifiers) {
when (modifier["type"] as String) {
"orderBy" -> {
when (modifier["name"] as String) {
"orderByChild" -> {
query = query.orderByChild(modifier["path"] as String)
}
"orderByKey" -> {
query = query.orderByKey()
}
"orderByValue" -> {
query = query.orderByValue()
}
"orderByPriority" -> {
query = query.orderByPriority()
}
}
}
"cursor" -> {
when (modifier["name"] as String) {
"startAt" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.startAt(value) else query.startAt(value, key)
is Number -> if (key == null) query.startAt(value.toDouble()) else query.startAt(value.toDouble(), key)
else -> if (key == null) query.startAt(value.toString()) else query.startAt(value.toString(), key)
}
}
"startAfter" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.startAfter(value) else query.startAfter(value, key)
is Number -> if (key == null) query.startAfter(value.toDouble()) else query.startAfter(value.toDouble(), key)
else -> if (key == null) query.startAfter(value.toString()) else query.startAfter(value.toString(), key)
}
}
"endAt" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.endAt(value) else query.endAt(value, key)
is Number -> if (key == null) query.endAt(value.toDouble()) else query.endAt(value.toDouble(), key)
else -> if (key == null) query.endAt(value.toString()) else query.endAt(value.toString(), key)
}
}
"endBefore" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.endBefore(value) else query.endBefore(value, key)
is Number -> if (key == null) query.endBefore(value.toDouble()) else query.endBefore(value.toDouble(), key)
else -> if (key == null) query.endBefore(value.toString()) else query.endBefore(value.toString(), key)
}
}
}
}
"limit" -> {
when (modifier["name"] as String) {
"limitToFirst" -> {
val value = (modifier["limit"] as Number).toInt()
query = query.limitToFirst(value)
}
"limitToLast" -> {
val value = (modifier["limit"] as Number).toInt()
query = query.limitToLast(value)
}
}
}
}
}
val query = queryFromModifiers(reference, request.modifiers)

// Generate a unique channel name
val channelName = "firebase_database_query_${System.currentTimeMillis()}_${request.path.hashCode()}"
Expand All @@ -947,84 +876,7 @@ class FirebaseDatabasePlugin :
try {
val database = getDatabaseFromPigeonApp(app)
val reference = database.getReference(request.path)

// Apply query modifiers if any
var query: com.google.firebase.database.Query = reference
// Note: no hasOrderModifier needed — Android SDK defaults to PriorityIndex
// when no orderBy is specified, so cursors work without an explicit orderBy.

for (modifier in request.modifiers) {
when (modifier["type"] as String) {
"orderBy" -> {
when (modifier["name"] as String) {
"orderByChild" -> {
query = query.orderByChild(modifier["path"] as String)
}
"orderByKey" -> {
query = query.orderByKey()
}
"orderByValue" -> {
query = query.orderByValue()
}
"orderByPriority" -> {
query = query.orderByPriority()
}
}
}
"cursor" -> {
when (modifier["name"] as String) {
"startAt" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.startAt(value) else query.startAt(value, key)
is Number -> if (key == null) query.startAt(value.toDouble()) else query.startAt(value.toDouble(), key)
else -> if (key == null) query.startAt(value.toString()) else query.startAt(value.toString(), key)
}
}
"startAfter" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.startAfter(value) else query.startAfter(value, key)
is Number -> if (key == null) query.startAfter(value.toDouble()) else query.startAfter(value.toDouble(), key)
else -> if (key == null) query.startAfter(value.toString()) else query.startAfter(value.toString(), key)
}
}
"endAt" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.endAt(value) else query.endAt(value, key)
is Number -> if (key == null) query.endAt(value.toDouble()) else query.endAt(value.toDouble(), key)
else -> if (key == null) query.endAt(value.toString()) else query.endAt(value.toString(), key)
}
}
"endBefore" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.endBefore(value) else query.endBefore(value, key)
is Number -> if (key == null) query.endBefore(value.toDouble()) else query.endBefore(value.toDouble(), key)
else -> if (key == null) query.endBefore(value.toString()) else query.endBefore(value.toString(), key)
}
}
}
}
"limit" -> {
when (modifier["name"] as String) {
"limitToFirst" -> {
val value = (modifier["limit"] as Number).toInt()
query = query.limitToFirst(value)
}
"limitToLast" -> {
val value = (modifier["limit"] as Number).toInt()
query = query.limitToLast(value)
}
}
}
}
}
val query = queryFromModifiers(reference, request.modifiers)

// Add keepSynced to the query
query.keepSynced(request.value ?: false)
Expand All @@ -1038,92 +890,7 @@ class FirebaseDatabasePlugin :
try {
val database = getDatabaseFromPigeonApp(app)
val reference = database.getReference(request.path)

// Apply query modifiers if any
var query: com.google.firebase.database.Query = reference
// Note: no hasOrderModifier needed — Android SDK defaults to PriorityIndex
// when no orderBy is specified, so cursors work without an explicit orderBy.

for (modifier in request.modifiers) {
when (modifier["type"] as String) {
"orderBy" -> {
when (modifier["name"] as String) {
"orderByChild" -> {
query = query.orderByChild(modifier["path"] as String)
}
"orderByKey" -> {
query = query.orderByKey()
}
"orderByValue" -> {
query = query.orderByValue()
}
"orderByPriority" -> {
query = query.orderByPriority()
}
}
}
"cursor" -> {
when (modifier["name"] as String) {
"startAt" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.startAt(value) else query.startAt(value, key)
is Number -> if (key == null) query.startAt(value.toDouble()) else query.startAt(value.toDouble(), key)
else -> if (key == null) query.startAt(value.toString()) else query.startAt(value.toString(), key)
}
}
"startAfter" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.startAfter(value) else query.startAfter(value, key)
is Number -> if (key == null) query.startAfter(value.toDouble()) else query.startAfter(value.toDouble(), key)
else -> if (key == null) query.startAfter(value.toString()) else query.startAfter(value.toString(), key)
}
}
"endAt" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.endAt(value) else query.endAt(value, key)
is Number -> if (key == null) query.endAt(value.toDouble()) else query.endAt(value.toDouble(), key)
else -> if (key == null) query.endAt(value.toString()) else query.endAt(value.toString(), key)
}
}
"endBefore" -> {
val value = modifier["value"]
val key = modifier["key"] as String?
query = when (value) {
is Boolean -> if (key == null) query.endBefore(value) else query.endBefore(value, key)
is Number -> if (key == null) query.endBefore(value.toDouble()) else query.endBefore(value.toDouble(), key)
else -> if (key == null) query.endBefore(value.toString()) else query.endBefore(value.toString(), key)
}
}
}
}
"limit" -> {
when (modifier["name"] as String) {
"limitToFirst" -> {
val value = when (val limit = modifier["limit"]) {
is Int -> limit
is Number -> limit.toInt()
else -> throw IllegalArgumentException("Invalid limit value: $limit")
}
query = query.limitToFirst(value)
}
"limitToLast" -> {
val value = when (val limit = modifier["limit"]) {
is Int -> limit
is Number -> limit.toInt()
else -> throw IllegalArgumentException("Invalid limit value: $limit")
}
query = query.limitToLast(value)
}
}
}
}
}
val query = queryFromModifiers(reference, request.modifiers)

// Get the data
query.get().addOnCompleteListener { task ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@ package io.flutter.plugins.firebase.database
import androidx.annotation.NonNull
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.Query
import java.util.*

class QueryBuilder
@JvmOverloads
constructor(
@NonNull ref: DatabaseReference,
@NonNull private val modifiers: List<Map<String, Any>>,
@NonNull private val modifiers: List<Map<String, Any?>>,
) {
private var query: Query = ref

Expand All @@ -35,9 +34,14 @@ class QueryBuilder
return query
}

private fun limit(modifier: Map<String, Any>) {
private fun limit(modifier: Map<String, Any?>) {
val name = modifier["name"] as String
val value = modifier["limit"] as Int
val value =
when (val limit = modifier["limit"]) {
is Int -> limit
is Number -> limit.toInt()
else -> throw IllegalArgumentException("Invalid limit value: $limit")
}

query =
when (name) {
Expand All @@ -47,7 +51,7 @@ class QueryBuilder
}
}

private fun orderBy(modifier: Map<String, Any>) {
private fun orderBy(modifier: Map<String, Any?>) {
val name = modifier["name"] as String

query =
Expand All @@ -63,7 +67,7 @@ class QueryBuilder
}
}

private fun cursor(modifier: Map<String, Any>) {
private fun cursor(modifier: Map<String, Any?>) {
val name = modifier["name"] as String

when (name) {
Expand All @@ -74,51 +78,51 @@ class QueryBuilder
}
}

private fun startAt(modifier: Map<String, Any>) {
private fun startAt(modifier: Map<String, Any?>) {
val value = modifier["value"]
val key = modifier["key"] as String?

query =
when (value) {
is Boolean -> if (key == null) query.startAt(value) else query.startAt(value, key)
is Number -> if (key == null) query.startAt(value.toDouble()) else query.startAt(value.toDouble(), key)
else -> if (key == null) query.startAt(value as String) else query.startAt(value as String, key)
else -> if (key == null) query.startAt(value.toString()) else query.startAt(value.toString(), key)
}
}

private fun startAfter(modifier: Map<String, Any>) {
private fun startAfter(modifier: Map<String, Any?>) {
val value = modifier["value"]
val key = modifier["key"] as String?

query =
when (value) {
is Boolean -> if (key == null) query.startAfter(value) else query.startAfter(value, key)
is Number -> if (key == null) query.startAfter(value.toDouble()) else query.startAfter(value.toDouble(), key)
else -> if (key == null) query.startAfter(value as String) else query.startAfter(value as String, key)
else -> if (key == null) query.startAfter(value.toString()) else query.startAfter(value.toString(), key)
}
}

private fun endAt(modifier: Map<String, Any>) {
private fun endAt(modifier: Map<String, Any?>) {
val value = modifier["value"]
val key = modifier["key"] as String?

query =
when (value) {
is Boolean -> if (key == null) query.endAt(value) else query.endAt(value, key)
is Number -> if (key == null) query.endAt(value.toDouble()) else query.endAt(value.toDouble(), key)
else -> if (key == null) query.endAt(value as String) else query.endAt(value as String, key)
else -> if (key == null) query.endAt(value.toString()) else query.endAt(value.toString(), key)
}
}

private fun endBefore(modifier: Map<String, Any>) {
private fun endBefore(modifier: Map<String, Any?>) {
val value = modifier["value"]
val key = modifier["key"] as String?

query =
when (value) {
is Boolean -> if (key == null) query.endBefore(value) else query.endBefore(value, key)
is Number -> if (key == null) query.endBefore(value.toDouble()) else query.endBefore(value.toDouble(), key)
else -> if (key == null) query.endBefore(value as String) else query.endBefore(value as String, key)
else -> if (key == null) query.endBefore(value.toString()) else query.endBefore(value.toString(), key)
}
}
}
Loading