Skip to content

Commit 6c72df4

Browse files
committed
Moving to new Query builder
1 parent e277eb3 commit 6c72df4

File tree

8 files changed

+325
-212
lines changed

8 files changed

+325
-212
lines changed

firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import kotlinx.serialization.SerializationStrategy
1818

1919
import com.google.firebase.firestore.Query as AndroidQuery
2020
import com.google.firebase.firestore.FieldPath as AndroidFieldPath
21+
import com.google.firebase.firestore.Filter as AndroidFilter
2122

2223
actual val Firebase.firestore get() =
2324
FirebaseFirestore(com.google.firebase.firestore.FirebaseFirestore.getInstance())
@@ -308,69 +309,72 @@ actual open class Query(open val android: AndroidQuery) {
308309
awaitClose { listener.remove() }
309310
}
310311

311-
internal actual fun where(field: String, vararg clauses: WhereClause) = Query(
312-
clauses.fold(android) { query, clause ->
313-
when (clause) {
314-
is WhereClause.ForNullableObject -> {
315-
val modifier: AndroidQuery.(String, Any?) -> AndroidQuery = when (clause) {
316-
is WhereClause.EqualTo -> AndroidQuery::whereEqualTo
317-
is WhereClause.NotEqualTo -> AndroidQuery::whereNotEqualTo
312+
internal actual fun where(filter: Filter) = Query(
313+
android.where(filter.toAndroidFilter())
314+
)
315+
316+
private fun Filter.toAndroidFilter(): AndroidFilter = when (this) {
317+
is Filter.And -> AndroidFilter.and(*filters.map { it.toAndroidFilter() }.toTypedArray())
318+
is Filter.Or -> AndroidFilter.or(*filters.map { it.toAndroidFilter() }.toTypedArray())
319+
is Filter.Field -> {
320+
when (constraint) {
321+
is WhereConstraint.ForNullableObject -> {
322+
val modifier: (String, Any?) -> AndroidFilter = when (constraint) {
323+
is WhereConstraint.EqualTo -> AndroidFilter::equalTo
324+
is WhereConstraint.NotEqualTo -> AndroidFilter::notEqualTo
318325
}
319-
modifier.invoke(query, field, clause.safeValue)
326+
modifier.invoke(field, constraint.safeValue)
320327
}
321-
is WhereClause.ForObject -> {
322-
val modifier: AndroidQuery.(String, Any) -> AndroidQuery = when (clause) {
323-
is WhereClause.LessThan -> AndroidQuery::whereLessThan
324-
is WhereClause.GreaterThan -> AndroidQuery::whereGreaterThan
325-
is WhereClause.LessThanOrEqualTo -> AndroidQuery::whereLessThanOrEqualTo
326-
is WhereClause.GreaterThanOrEqualTo -> AndroidQuery::whereGreaterThanOrEqualTo
327-
is WhereClause.ArrayContains -> AndroidQuery::whereArrayContains
328+
is WhereConstraint.ForObject -> {
329+
val modifier: (String, Any) -> AndroidFilter = when (constraint) {
330+
is WhereConstraint.LessThan -> AndroidFilter::lessThan
331+
is WhereConstraint.GreaterThan -> AndroidFilter::greaterThan
332+
is WhereConstraint.LessThanOrEqualTo -> AndroidFilter::lessThanOrEqualTo
333+
is WhereConstraint.GreaterThanOrEqualTo -> AndroidFilter::greaterThanOrEqualTo
334+
is WhereConstraint.ArrayContains -> AndroidFilter::arrayContains
328335
}
329-
modifier.invoke(query, field, clause.safeValue)
336+
modifier.invoke(field, constraint.safeValue)
330337
}
331-
is WhereClause.ForArray -> {
332-
val modifier: AndroidQuery.(String, List<Any>) -> AndroidQuery = when (clause) {
333-
is WhereClause.InArray -> AndroidQuery::whereIn
334-
is WhereClause.ArrayContainsAny -> AndroidQuery::whereArrayContainsAny
335-
is WhereClause.NotInArray -> AndroidQuery::whereNotIn
338+
is WhereConstraint.ForArray -> {
339+
val modifier: (String, List<Any>) -> AndroidFilter = when (constraint) {
340+
is WhereConstraint.InArray -> AndroidFilter::inArray
341+
is WhereConstraint.ArrayContainsAny -> AndroidFilter::arrayContainsAny
342+
is WhereConstraint.NotInArray -> AndroidFilter::notInArray
336343
}
337-
modifier.invoke(query, field, clause.safeValues)
344+
modifier.invoke(field, constraint.safeValues)
338345
}
339346
}
340347
}
341-
)
342-
343-
internal actual fun where(path: FieldPath, vararg clauses: WhereClause) = Query(
344-
clauses.fold(android) { query, clause ->
345-
when (clause) {
346-
is WhereClause.ForNullableObject -> {
347-
val modifier: AndroidQuery.(AndroidFieldPath, Any?) -> AndroidQuery = when (clause) {
348-
is WhereClause.EqualTo -> AndroidQuery::whereEqualTo
349-
is WhereClause.NotEqualTo -> AndroidQuery::whereNotEqualTo
348+
is Filter.Path -> {
349+
when (constraint) {
350+
is WhereConstraint.ForNullableObject -> {
351+
val modifier: (AndroidFieldPath, Any?) -> AndroidFilter = when (constraint) {
352+
is WhereConstraint.EqualTo -> AndroidFilter::equalTo
353+
is WhereConstraint.NotEqualTo -> AndroidFilter::notEqualTo
350354
}
351-
modifier.invoke(query, path.android, clause.safeValue)
355+
modifier.invoke(path.android, constraint.safeValue)
352356
}
353-
is WhereClause.ForObject -> {
354-
val modifier: AndroidQuery.(AndroidFieldPath, Any) -> AndroidQuery = when (clause) {
355-
is WhereClause.LessThan -> AndroidQuery::whereLessThan
356-
is WhereClause.GreaterThan -> AndroidQuery::whereGreaterThan
357-
is WhereClause.LessThanOrEqualTo -> AndroidQuery::whereLessThanOrEqualTo
358-
is WhereClause.GreaterThanOrEqualTo -> AndroidQuery::whereGreaterThanOrEqualTo
359-
is WhereClause.ArrayContains -> AndroidQuery::whereArrayContains
357+
is WhereConstraint.ForObject -> {
358+
val modifier: (AndroidFieldPath, Any) -> AndroidFilter = when (constraint) {
359+
is WhereConstraint.LessThan -> AndroidFilter::lessThan
360+
is WhereConstraint.GreaterThan -> AndroidFilter::greaterThan
361+
is WhereConstraint.LessThanOrEqualTo -> AndroidFilter::lessThanOrEqualTo
362+
is WhereConstraint.GreaterThanOrEqualTo -> AndroidFilter::greaterThanOrEqualTo
363+
is WhereConstraint.ArrayContains -> AndroidFilter::arrayContains
360364
}
361-
modifier.invoke(query, path.android, clause.safeValue)
365+
modifier.invoke(path.android, constraint.safeValue)
362366
}
363-
is WhereClause.ForArray -> {
364-
val modifier: AndroidQuery.(AndroidFieldPath, List<Any>) -> AndroidQuery = when (clause) {
365-
is WhereClause.InArray -> AndroidQuery::whereIn
366-
is WhereClause.ArrayContainsAny -> AndroidQuery::whereArrayContainsAny
367-
is WhereClause.NotInArray -> AndroidQuery::whereNotIn
367+
is WhereConstraint.ForArray -> {
368+
val modifier: (AndroidFieldPath, List<Any>) -> AndroidFilter = when (constraint) {
369+
is WhereConstraint.InArray -> AndroidFilter::inArray
370+
is WhereConstraint.ArrayContainsAny -> AndroidFilter::arrayContainsAny
371+
is WhereConstraint.NotInArray -> AndroidFilter::notInArray
368372
}
369-
modifier.invoke(query, path.android, clause.safeValues)
373+
modifier.invoke(path.android, constraint.safeValues)
370374
}
371375
}
372376
}
373-
)
377+
}
374378

375379
internal actual fun _orderBy(field: String, direction: Direction) = Query(android.orderBy(field, direction))
376380
internal actual fun _orderBy(field: FieldPath, direction: Direction) = Query(android.orderBy(field.android, direction))
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package dev.gitlive.firebase.firestore
2+
3+
sealed interface WhereConstraint {
4+
5+
sealed interface ForNullableObject : WhereConstraint {
6+
val value: Any?
7+
val safeValue get() = value?.safeValue
8+
}
9+
10+
sealed interface ForObject : WhereConstraint {
11+
val value: Any
12+
val safeValue get() = value.safeValue
13+
}
14+
sealed interface ForArray : WhereConstraint {
15+
val values: List<Any>
16+
val safeValues get() = values.map { it.safeValue }
17+
}
18+
19+
data class EqualTo internal constructor(override val value: Any?) : ForNullableObject
20+
data class NotEqualTo internal constructor(override val value: Any?) : ForNullableObject
21+
data class LessThan internal constructor(override val value: Any) : ForObject
22+
data class GreaterThan internal constructor(override val value: Any) : ForObject
23+
data class LessThanOrEqualTo internal constructor(override val value: Any) : ForObject
24+
data class GreaterThanOrEqualTo internal constructor(override val value: Any) : ForObject
25+
data class ArrayContains internal constructor(override val value: Any) : ForObject
26+
data class ArrayContainsAny internal constructor(override val values: List<Any>) : ForArray
27+
data class InArray internal constructor(override val values: List<Any>) : ForArray
28+
data class NotInArray internal constructor(override val values: List<Any>) : ForArray
29+
}
30+
31+
sealed class Filter {
32+
data class And internal constructor(val filters: List<Filter>) : Filter()
33+
data class Or internal constructor(val filters: List<Filter>) : Filter()
34+
sealed class WithConstraint : Filter() {
35+
abstract val constraint: WhereConstraint
36+
}
37+
38+
data class Field internal constructor(val field: String, override val constraint: WhereConstraint) : WithConstraint()
39+
data class Path internal constructor(val path: FieldPath, override val constraint: WhereConstraint) : WithConstraint()
40+
}
41+
42+
class FilterBuilder internal constructor() {
43+
44+
infix fun String.equalTo(value: Any?): Filter.WithConstraint {
45+
return Filter.Field(this, WhereConstraint.EqualTo(value))
46+
}
47+
48+
infix fun FieldPath.equalTo(value: Any?): Filter.WithConstraint {
49+
return Filter.Path(this, WhereConstraint.EqualTo(value))
50+
}
51+
52+
infix fun String.notEqualTo(value: Any?): Filter.WithConstraint {
53+
return Filter.Field(this, WhereConstraint.NotEqualTo(value))
54+
}
55+
56+
infix fun FieldPath.notEqualTo(value: Any?): Filter.WithConstraint {
57+
return Filter.Path(this, WhereConstraint.NotEqualTo(value))
58+
}
59+
60+
infix fun String.lessThan(value: Any): Filter.WithConstraint {
61+
return Filter.Field(this, WhereConstraint.LessThan(value))
62+
}
63+
64+
infix fun FieldPath.lessThan(value: Any): Filter.WithConstraint {
65+
return Filter.Path(this, WhereConstraint.LessThan(value))
66+
}
67+
68+
infix fun String.greaterThan(value: Any): Filter.WithConstraint {
69+
return Filter.Field(this, WhereConstraint.GreaterThan(value))
70+
}
71+
72+
infix fun FieldPath.greaterThan(value: Any): Filter.WithConstraint {
73+
return Filter.Path(this, WhereConstraint.GreaterThan(value))
74+
}
75+
76+
infix fun String.lessThanOrEqualTo(value: Any): Filter.WithConstraint {
77+
return Filter.Field(this, WhereConstraint.LessThanOrEqualTo(value))
78+
}
79+
80+
infix fun FieldPath.lessThanOrEqualTo(value: Any): Filter.WithConstraint {
81+
return Filter.Path(this, WhereConstraint.LessThanOrEqualTo(value))
82+
}
83+
84+
infix fun String.greaterThanOrEqualTo(value: Any): Filter.WithConstraint {
85+
return Filter.Field(this, WhereConstraint.GreaterThanOrEqualTo(value))
86+
}
87+
88+
infix fun FieldPath.greaterThanOrEqualTo(value: Any): Filter.WithConstraint {
89+
return Filter.Path(this, WhereConstraint.GreaterThanOrEqualTo(value))
90+
}
91+
92+
infix fun String.contains(value: Any): Filter.WithConstraint {
93+
return Filter.Field(this, WhereConstraint.ArrayContains(value))
94+
}
95+
96+
infix fun FieldPath.contains(value: Any): Filter.WithConstraint {
97+
return Filter.Path(this, WhereConstraint.ArrayContains(value))
98+
}
99+
100+
infix fun String.containsAny(values: List<Any>): Filter.WithConstraint {
101+
return Filter.Field(this, WhereConstraint.ArrayContainsAny(values))
102+
}
103+
104+
infix fun FieldPath.containsAny(values: List<Any>): Filter.WithConstraint {
105+
return Filter.Path(this, WhereConstraint.ArrayContainsAny(values))
106+
}
107+
108+
infix fun String.`in`(values: List<Any>): Filter.WithConstraint {
109+
return Filter.Field(this, WhereConstraint.InArray(values))
110+
}
111+
112+
infix fun FieldPath.`in`(values: List<Any>): Filter.WithConstraint {
113+
return Filter.Path(this, WhereConstraint.InArray(values))
114+
}
115+
116+
infix fun String.notIn(values: List<Any>): Filter.WithConstraint {
117+
return Filter.Field(this, WhereConstraint.NotInArray(values))
118+
}
119+
120+
infix fun FieldPath.notIn(values: List<Any>): Filter.WithConstraint {
121+
return Filter.Path(this, WhereConstraint.NotInArray(values))
122+
}
123+
124+
infix fun Filter.and(right: Filter): Filter.And {
125+
val leftList = when (this) {
126+
is Filter.And -> filters
127+
else -> listOf(this)
128+
}
129+
val rightList = when (right) {
130+
is Filter.And -> right.filters
131+
else -> listOf(right)
132+
}
133+
return Filter.And(leftList + rightList)
134+
}
135+
136+
infix fun Filter.or(right: Filter): Filter.Or {
137+
val leftList = when (this) {
138+
is Filter.Or -> filters
139+
else -> listOf(this)
140+
}
141+
val rightList = when (right) {
142+
is Filter.Or -> right.filters
143+
else -> listOf(right)
144+
}
145+
return Filter.Or(leftList + rightList)
146+
}
147+
}

0 commit comments

Comments
 (0)