Skip to content

Commit 6cc2ee6

Browse files
Port improved whereConditionsFromCursor from Android (#8867)
1 parent d18310a commit 6cc2ee6

File tree

1 file changed

+25
-30
lines changed

1 file changed

+25
-30
lines changed

packages/firestore/src/core/pipeline-util.ts

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,12 @@
1818
import { Firestore } from '../lite-api/database';
1919
import {
2020
Constant,
21-
Field,
2221
BooleanExpr,
2322
and,
2423
or,
2524
Ordering,
2625
lt,
2726
gt,
28-
lte,
29-
gte,
30-
eq,
3127
field
3228
} from '../lite-api/expressions';
3329
import { Pipeline } from '../lite-api/pipeline';
@@ -254,36 +250,35 @@ function whereConditionsFromCursor(
254250
orderings: Ordering[],
255251
position: 'before' | 'after'
256252
): BooleanExpr {
257-
const cursors = bound.position.map(value => Constant._fromProto(value));
253+
// The filterFunc is either greater than or less than
258254
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;
264257

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];
274260

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));
282267
}
283268

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));
288281
}
282+
283+
return condition;
289284
}

0 commit comments

Comments
 (0)