Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 25 additions & 30 deletions packages/firestore/src/core/pipeline-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,12 @@
import { Firestore } from '../lite-api/database';
import {
Constant,
Field,
BooleanExpr,
and,
or,
Ordering,
lt,
gt,
lte,
gte,
eq,
field
} from '../lite-api/expressions';
import { Pipeline } from '../lite-api/pipeline';
Expand Down Expand Up @@ -254,36 +250,35 @@ function whereConditionsFromCursor(
orderings: Ordering[],
position: 'before' | 'after'
): BooleanExpr {
const cursors = bound.position.map(value => Constant._fromProto(value));
// The filterFunc is either greater than or less than
const filterFunc = position === 'before' ? lt : gt;
const filterInclusiveFunc = position === 'before' ? lte : gte;

const orConditions: BooleanExpr[] = [];
for (let i = 1; i <= orderings.length; i++) {
const cursorSubset = cursors.slice(0, i);
const cursors = bound.position.map(value => Constant._fromProto(value));
const size = cursors.length;

const conditions: BooleanExpr[] = cursorSubset.map((cursor, index) => {
if (index < cursorSubset.length - 1) {
return eq(orderings[index].expr as Field, cursor);
} else if (bound.inclusive && i === orderings.length - 1) {
return filterInclusiveFunc(orderings[index].expr as Field, cursor);
} else {
return filterFunc(orderings[index].expr as Field, cursor);
}
});
let field = orderings[size-1].expr;
let value = cursors[size-1];

if (conditions.length === 1) {
orConditions.push(conditions[0]);
} else {
orConditions.push(
and(conditions[0], conditions[1], ...conditions.slice(2))
);
}
// Add condition for last bound
let condition: BooleanExpr = filterFunc(field, value);
if (bound.inclusive) {
// When the cursor bound is inclusive, then the last bound
// can be equal to the value, otherwise it's not equal
condition = or(condition, field.eq(value));
}

if (orConditions.length === 1) {
return orConditions[0];
} else {
return or(orConditions[0], orConditions[1], ...orConditions.slice(2));
// Iterate backwards over the remaining bounds, adding
// a condition for each one
for (let i = size - 2; i >= 0; i--) {
field = orderings[i].expr;
value = cursors[i];

// For each field in the orderings, the condition is either
// a) lt|gt the cursor value,
// b) or equal the cursor value and lt|gt the cursor values for other fields
condition = or(
filterFunc(field, value),
and(field.eq(value), condition));
}

return condition;
}
Loading