|
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