|
18 | 18 | import { Firestore } from '../lite-api/database'; |
19 | 19 | import { |
20 | 20 | Constant, |
21 | | - Field, |
22 | 21 | BooleanExpr, |
23 | 22 | and, |
24 | 23 | or, |
25 | 24 | Ordering, |
26 | 25 | lt, |
27 | 26 | gt, |
28 | | - lte, |
29 | | - gte, |
30 | | - eq, |
31 | 27 | field |
32 | 28 | } from '../lite-api/expressions'; |
33 | 29 | import { Pipeline } from '../lite-api/pipeline'; |
@@ -254,36 +250,35 @@ function whereConditionsFromCursor( |
254 | 250 | orderings: Ordering[], |
255 | 251 | position: 'before' | 'after' |
256 | 252 | ): BooleanExpr { |
257 | | - const cursors = bound.position.map(value => Constant._fromProto(value)); |
| 253 | + // The filterFunc is either greater than or less than |
258 | 254 | const filterFunc = position === 'before' ? lt : gt; |
259 | | - const filterInclusiveFunc = position === 'before' ? lte : gte; |
260 | | - |
261 | | - const orConditions: BooleanExpr[] = []; |
262 | | - for (let i = 1; i <= orderings.length; i++) { |
263 | | - const cursorSubset = cursors.slice(0, i); |
| 255 | + const cursors = bound.position.map(value => Constant._fromProto(value)); |
| 256 | + const size = cursors.length; |
264 | 257 |
|
265 | | - const conditions: BooleanExpr[] = cursorSubset.map((cursor, index) => { |
266 | | - if (index < cursorSubset.length - 1) { |
267 | | - return eq(orderings[index].expr as Field, cursor); |
268 | | - } else if (bound.inclusive && i === orderings.length - 1) { |
269 | | - return filterInclusiveFunc(orderings[index].expr as Field, cursor); |
270 | | - } else { |
271 | | - return filterFunc(orderings[index].expr as Field, cursor); |
272 | | - } |
273 | | - }); |
| 258 | + let field = orderings[size-1].expr; |
| 259 | + let value = cursors[size-1]; |
274 | 260 |
|
275 | | - if (conditions.length === 1) { |
276 | | - orConditions.push(conditions[0]); |
277 | | - } else { |
278 | | - orConditions.push( |
279 | | - and(conditions[0], conditions[1], ...conditions.slice(2)) |
280 | | - ); |
281 | | - } |
| 261 | + // Add condition for last bound |
| 262 | + let condition: BooleanExpr = filterFunc(field, value); |
| 263 | + if (bound.inclusive) { |
| 264 | + // When the cursor bound is inclusive, then the last bound |
| 265 | + // can be equal to the value, otherwise it's not equal |
| 266 | + condition = or(condition, field.eq(value)); |
282 | 267 | } |
283 | 268 |
|
284 | | - if (orConditions.length === 1) { |
285 | | - return orConditions[0]; |
286 | | - } else { |
287 | | - return or(orConditions[0], orConditions[1], ...orConditions.slice(2)); |
| 269 | + // Iterate backwards over the remaining bounds, adding |
| 270 | + // a condition for each one |
| 271 | + for (let i = size - 2; i >= 0; i--) { |
| 272 | + field = orderings[i].expr; |
| 273 | + value = cursors[i]; |
| 274 | + |
| 275 | + // For each field in the orderings, the condition is either |
| 276 | + // a) lt|gt the cursor value, |
| 277 | + // b) or equal the cursor value and lt|gt the cursor values for other fields |
| 278 | + condition = or( |
| 279 | + filterFunc(field, value), |
| 280 | + and(field.eq(value), condition)); |
288 | 281 | } |
| 282 | + |
| 283 | + return condition; |
289 | 284 | } |
0 commit comments