@@ -129,16 +129,32 @@ private Object[] getDocumentValues(
129
129
List <Object > data = new ArrayList <>();
130
130
if (orderBy != null ) {
131
131
for (List <Object > order : orderBy ) {
132
- String orderByFieldName = (String ) order .get (0 );
133
- if (orderByFieldName .contains ("." )) {
134
- String [] fieldNameParts = orderByFieldName .split ("\\ ." );
135
- Map <String , Object > current = (Map <String , Object >) documentData .get (fieldNameParts [0 ]);
136
- for (int i = 1 ; i < fieldNameParts .length - 1 ; i ++) {
137
- current = (Map <String , Object >) current .get (fieldNameParts [i ]);
132
+ final Object field = order .get (0 );
133
+
134
+ if (field instanceof FieldPath ) {
135
+ if (field == FieldPath .documentId ()) {
136
+ // This is also checked by an assertion on the Dart side.
137
+ throw new IllegalArgumentException (
138
+ "You cannot order by the document id when using"
139
+ + "{start/end}{At/After/Before}Document as the library will order by the document"
140
+ + " id implicitly in order to to add other fields to the order clause." );
141
+ } else {
142
+ // Unsupported type.
143
+ }
144
+ } else if (field instanceof String ) {
145
+ String orderByFieldName = (String ) field ;
146
+ if (orderByFieldName .contains ("." )) {
147
+ String [] fieldNameParts = orderByFieldName .split ("\\ ." );
148
+ Map <String , Object > current = (Map <String , Object >) documentData .get (fieldNameParts [0 ]);
149
+ for (int i = 1 ; i < fieldNameParts .length - 1 ; i ++) {
150
+ current = (Map <String , Object >) current .get (fieldNameParts [i ]);
151
+ }
152
+ data .add (current .get (fieldNameParts [fieldNameParts .length - 1 ]));
153
+ } else {
154
+ data .add (documentData .get (orderByFieldName ));
138
155
}
139
- data .add (current .get (fieldNameParts [fieldNameParts .length - 1 ]));
140
156
} else {
141
- data . add ( documentData . get ( orderByFieldName ));
157
+ // Invalid type.
142
158
}
143
159
}
144
160
}
@@ -213,21 +229,67 @@ private Query getQuery(Map<String, Object> arguments) {
213
229
@ SuppressWarnings ("unchecked" )
214
230
List <List <Object >> whereConditions = (List <List <Object >>) parameters .get ("where" );
215
231
for (List <Object > condition : whereConditions ) {
216
- String fieldName = (String ) condition .get (0 );
232
+ String fieldName = null ;
233
+ FieldPath fieldPath = null ;
234
+ final Object field = condition .get (0 );
235
+ if (field instanceof String ) {
236
+ fieldName = (String ) field ;
237
+ } else if (field instanceof FieldPath ) {
238
+ fieldPath = (FieldPath ) field ;
239
+ } else {
240
+ // Invalid type.
241
+ }
242
+
217
243
String operator = (String ) condition .get (1 );
218
244
Object value = condition .get (2 );
219
245
if ("==" .equals (operator )) {
220
- query = query .whereEqualTo (fieldName , value );
246
+ if (fieldName != null ) {
247
+ query = query .whereEqualTo (fieldName , value );
248
+ } else if (fieldPath != null ) {
249
+ query = query .whereEqualTo (fieldPath , value );
250
+ } else {
251
+ // Invalid type.
252
+ }
221
253
} else if ("<" .equals (operator )) {
222
- query = query .whereLessThan (fieldName , value );
254
+ if (fieldName != null ) {
255
+ query = query .whereLessThan (fieldName , value );
256
+ } else if (fieldPath != null ) {
257
+ query = query .whereLessThan (fieldPath , value );
258
+ } else {
259
+ // Invalid type.
260
+ }
223
261
} else if ("<=" .equals (operator )) {
224
- query = query .whereLessThanOrEqualTo (fieldName , value );
262
+ if (fieldName != null ) {
263
+ query = query .whereLessThanOrEqualTo (fieldName , value );
264
+ } else if (fieldPath != null ) {
265
+ query = query .whereLessThanOrEqualTo (fieldPath , value );
266
+ } else {
267
+ // Invalid type.
268
+ }
225
269
} else if (">" .equals (operator )) {
226
- query = query .whereGreaterThan (fieldName , value );
270
+ if (fieldName != null ) {
271
+ query = query .whereGreaterThan (fieldName , value );
272
+ } else if (fieldPath != null ) {
273
+ query = query .whereGreaterThan (fieldPath , value );
274
+ } else {
275
+ // Invalid type.
276
+ }
227
277
} else if (">=" .equals (operator )) {
228
- query = query .whereGreaterThanOrEqualTo (fieldName , value );
278
+ if (fieldName != null ) {
279
+ query = query .whereGreaterThanOrEqualTo (fieldName , value );
280
+ } else if (fieldPath != null ) {
281
+ query = query .whereGreaterThanOrEqualTo (fieldPath , value );
282
+ } else {
283
+ // Invalid type.
284
+ }
229
285
} else if ("array-contains" .equals (operator )) {
230
- query = query .whereArrayContains (fieldName , value );
286
+ if (fieldName != null ) {
287
+ query = query .whereArrayContains (fieldName , value );
288
+ } else if (fieldPath != null ) {
289
+ query = query .whereArrayContains (fieldPath , value );
290
+ } else {
291
+ // Invalid type.
292
+ }
231
293
} else {
232
294
// Invalid operator.
233
295
}
@@ -239,11 +301,28 @@ private Query getQuery(Map<String, Object> arguments) {
239
301
List <List <Object >> orderBy = (List <List <Object >>) parameters .get ("orderBy" );
240
302
if (orderBy == null ) return query ;
241
303
for (List <Object > order : orderBy ) {
242
- String orderByFieldName = (String ) order .get (0 );
304
+ String fieldName = null ;
305
+ FieldPath fieldPath = null ;
306
+ final Object field = order .get (0 );
307
+ if (field instanceof String ) {
308
+ fieldName = (String ) field ;
309
+ } else if (field instanceof FieldPath ) {
310
+ fieldPath = (FieldPath ) field ;
311
+ } else {
312
+ // Invalid type.
313
+ }
314
+
243
315
boolean descending = (boolean ) order .get (1 );
244
316
Query .Direction direction =
245
317
descending ? Query .Direction .DESCENDING : Query .Direction .ASCENDING ;
246
- query = query .orderBy (orderByFieldName , direction );
318
+
319
+ if (fieldName != null ) {
320
+ query = query .orderBy (fieldName , direction );
321
+ } else if (fieldPath != null ) {
322
+ query = query .orderBy (fieldPath , direction );
323
+ } else {
324
+ // Invalid type.
325
+ }
247
326
}
248
327
@ SuppressWarnings ("unchecked" )
249
328
Map <String , Object > startAtDocument = (Map <String , Object >) parameters .get ("startAtDocument" );
@@ -259,6 +338,11 @@ private Query getQuery(Map<String, Object> arguments) {
259
338
|| startAfterDocument != null
260
339
|| endAtDocument != null
261
340
|| endBeforeDocument != null ) {
341
+ if (orderBy .isEmpty ()) {
342
+ throw new IllegalStateException (
343
+ "You need to order by at least one field when using "
344
+ + "{start/end}{At/After/Before}Document as you need some value to e.g. start after." );
345
+ }
262
346
boolean descending = (boolean ) orderBy .get (orderBy .size () - 1 ).get (1 );
263
347
Query .Direction direction =
264
348
descending ? Query .Direction .DESCENDING : Query .Direction .ASCENDING ;
@@ -859,6 +943,7 @@ final class FirestoreMessageCodec extends StandardMessageCodec {
859
943
private static final byte TIMESTAMP = (byte ) 136 ;
860
944
private static final byte INCREMENT_DOUBLE = (byte ) 137 ;
861
945
private static final byte INCREMENT_INTEGER = (byte ) 138 ;
946
+ private static final byte DOCUMENT_ID = (byte ) 139 ;
862
947
863
948
@ Override
864
949
protected void writeValue (ByteArrayOutputStream stream , Object value ) {
@@ -922,6 +1007,8 @@ protected Object readValueOfType(byte type, ByteBuffer buffer) {
922
1007
case INCREMENT_DOUBLE :
923
1008
final Number doubleIncrementValue = (Number ) readValue (buffer );
924
1009
return FieldValue .increment (doubleIncrementValue .doubleValue ());
1010
+ case DOCUMENT_ID :
1011
+ return FieldPath .documentId ();
925
1012
default :
926
1013
return super .readValueOfType (type , buffer );
927
1014
}
0 commit comments