16
16
17
17
import static com .google .firebase .firestore .model .Values .max ;
18
18
import static com .google .firebase .firestore .model .Values .min ;
19
+ import static com .google .firebase .firestore .util .Assert .fail ;
19
20
20
21
import androidx .annotation .Nullable ;
21
- import com .google .firebase .firestore .core .OrderBy .Direction ;
22
22
import com .google .firebase .firestore .model .DocumentKey ;
23
23
import com .google .firebase .firestore .model .FieldIndex ;
24
24
import com .google .firebase .firestore .model .ResourcePath ;
25
25
import com .google .firebase .firestore .model .Values ;
26
- import com .google .firestore .v1 .ArrayValue ;
27
26
import com .google .firestore .v1 .Value ;
28
27
import java .util .ArrayList ;
28
+ import java .util .Collections ;
29
29
import java .util .List ;
30
30
31
31
/**
@@ -115,6 +115,27 @@ public boolean hasLimit() {
115
115
return endAt ;
116
116
}
117
117
118
+ /** Returns the list of values that are used in ARRAY_CONTAINS and ARRAY_CONTAINS_ANY filter. */
119
+ public List <Value > getArrayValues (FieldIndex fieldIndex ) {
120
+ for (FieldIndex .Segment segment : fieldIndex .getArraySegments ()) {
121
+ for (Filter filter : filters ) {
122
+ if (filter .getField ().equals (segment .getFieldPath ())) {
123
+ FieldFilter fieldFilter = (FieldFilter ) filter ;
124
+ switch (fieldFilter .getOperator ()) {
125
+ case ARRAY_CONTAINS_ANY :
126
+ return fieldFilter .getValue ().getArrayValue ().getValuesList ();
127
+ case ARRAY_CONTAINS :
128
+ return Collections .singletonList (fieldFilter .getValue ());
129
+ default :
130
+ // Remaining filters cannot be used as array filters.
131
+ }
132
+ }
133
+ }
134
+ }
135
+
136
+ return Collections .emptyList ();
137
+ }
138
+
118
139
/**
119
140
* Returns a lower bound of field values that can be used as a starting point to scan the index
120
141
* defined by {@code fieldIndex}.
@@ -127,7 +148,7 @@ public Bound getLowerBound(FieldIndex fieldIndex) {
127
148
boolean inclusive = true ;
128
149
129
150
// Go through all filters to find a value for the current field segment
130
- for (FieldIndex .Segment segment : fieldIndex ) {
151
+ for (FieldIndex .Segment segment : fieldIndex . getDirectionalSegments () ) {
131
152
Value segmentValue = Values .NULL_VALUE ;
132
153
boolean segmentInclusive = true ;
133
154
@@ -142,26 +163,17 @@ public Bound getLowerBound(FieldIndex fieldIndex) {
142
163
case LESS_THAN_OR_EQUAL :
143
164
filterValue = Values .getLowerBound (fieldFilter .getValue ().getValueTypeCase ());
144
165
break ;
145
- case NOT_EQUAL :
146
- filterValue = Values .NULL_VALUE ;
147
- break ;
148
- case NOT_IN :
149
- filterValue =
150
- Value .newBuilder ()
151
- .setArrayValue (ArrayValue .newBuilder ().addValues (Values .NULL_VALUE ))
152
- .build ();
153
- break ;
154
166
case EQUAL :
155
167
case IN :
156
- case ARRAY_CONTAINS_ANY :
157
- case ARRAY_CONTAINS :
158
168
case GREATER_THAN_OR_EQUAL :
159
169
filterValue = fieldFilter .getValue ();
160
170
break ;
161
171
case GREATER_THAN :
162
172
filterValue = fieldFilter .getValue ();
163
173
filterInclusive = false ;
164
174
break ;
175
+ default :
176
+ // Remaining filters cannot be used as upper bounds.
165
177
}
166
178
167
179
if (max (segmentValue , filterValue ) == filterValue ) {
@@ -206,7 +218,7 @@ public Bound getLowerBound(FieldIndex fieldIndex) {
206
218
List <Value > values = new ArrayList <>();
207
219
boolean inclusive = true ;
208
220
209
- for (FieldIndex .Segment segment : fieldIndex ) {
221
+ for (FieldIndex .Segment segment : fieldIndex . getDirectionalSegments () ) {
210
222
@ Nullable Value segmentValue = null ;
211
223
boolean segmentInclusive = true ;
212
224
@@ -218,26 +230,22 @@ public Bound getLowerBound(FieldIndex fieldIndex) {
218
230
boolean filterInclusive = true ;
219
231
220
232
switch (fieldFilter .getOperator ()) {
221
- case NOT_IN :
222
- case NOT_EQUAL :
223
- // These filters cannot be used as an upper bound. Skip.
224
- break ;
225
233
case GREATER_THAN_OR_EQUAL :
226
234
case GREATER_THAN :
227
235
filterValue = Values .getUpperBound (fieldFilter .getValue ().getValueTypeCase ());
228
236
filterInclusive = false ;
229
237
break ;
230
238
case EQUAL :
231
239
case IN :
232
- case ARRAY_CONTAINS_ANY :
233
- case ARRAY_CONTAINS :
234
240
case LESS_THAN_OR_EQUAL :
235
241
filterValue = fieldFilter .getValue ();
236
242
break ;
237
243
case LESS_THAN :
238
244
filterValue = fieldFilter .getValue ();
239
245
filterInclusive = false ;
240
246
break ;
247
+ default :
248
+ // Remaining filters cannot be used as upper bounds.
241
249
}
242
250
243
251
if (min (segmentValue , filterValue ) == filterValue ) {
@@ -283,6 +291,11 @@ public List<OrderBy> getOrderBy() {
283
291
return this .orderBys ;
284
292
}
285
293
294
+ /** Returns the first order by (which always exists). */
295
+ public OrderBy getFirstOrderBy () {
296
+ return this .orderBys .get (0 );
297
+ }
298
+
286
299
/** Returns a canonical string representing this target. */
287
300
public String getCanonicalId () {
288
301
if (memoizedCannonicalId != null ) {
@@ -307,7 +320,7 @@ public String getCanonicalId() {
307
320
builder .append ("|ob:" );
308
321
for (OrderBy orderBy : getOrderBy ()) {
309
322
builder .append (orderBy .getField ().canonicalString ());
310
- builder .append (orderBy .getDirection ().equals ( Direction . ASCENDING ) ? "asc" : "desc" );
323
+ builder .append (orderBy .getDirection ().canonicalString () );
311
324
}
312
325
313
326
// Add limit.
0 commit comments