Skip to content

Refactor core/target.ts, extracting classes Bound, OrderBy, and Filter #6557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
effced9
Add composite filters. Port of https://github.com/firebase/firebase-a…
MarkDuckworth Jun 24, 2022
eba3b84
Cleanup: lint
MarkDuckworth Jun 24, 2022
33a0896
Support encoding and decoding Composite Filters
MarkDuckworth Jun 29, 2022
9f6e216
Formatting
MarkDuckworth Jun 30, 2022
6556240
Merge remote-tracking branch 'origin/markduckworth/or-queries' into m…
MarkDuckworth Jul 26, 2022
78a8900
Fix issue with readonly array.
MarkDuckworth Jul 26, 2022
80fc05d
WIP: serving results from index.
MarkDuckworth Aug 5, 2022
8b6f05f
Perform DNF transform
MarkDuckworth Aug 10, 2022
152fc18
Cleanup and tests from https://github.com/firebase/firebase-android-s…
MarkDuckworth Aug 10, 2022
8b0bfbd
Merge branch 'markduckworth/or-queries' of github.com:firebase/fireba…
MarkDuckworth Aug 12, 2022
1c948cb
use index if we have composite filters
MarkDuckworth Aug 12, 2022
2cad46c
Merge branch 'markduckworth/or-queries' into markduckworth/or-queries…
MarkDuckworth Aug 12, 2022
266f7f6
Fix bad import
MarkDuckworth Aug 12, 2022
c2d7cd2
Update the orderBy filtering mechanism for OR queries and steps to se…
MarkDuckworth Aug 15, 2022
41d0e29
Adding tests
MarkDuckworth Aug 15, 2022
90f7c50
Test for DNF computation.
MarkDuckworth Aug 16, 2022
ff52ecc
Fix implementation of isFlatConjunction
MarkDuckworth Aug 16, 2022
dfda9f8
Adding integration tests for validation of composite queries.
MarkDuckworth Aug 17, 2022
9bc3336
IndexDb manager tests for partial and full index.
MarkDuckworth Aug 17, 2022
d66abd4
Test query does not include documents with missing fields
MarkDuckworth Aug 17, 2022
e33263d
Run prettier
MarkDuckworth Aug 17, 2022
01c3487
Add missing awaits
MarkDuckworth Aug 17, 2022
7d56b57
Fixing argument validation for and . Updating tests for asserted err…
MarkDuckworth Aug 17, 2022
d01ff74
Prettier
MarkDuckworth Aug 18, 2022
186fd92
Removing duplicate test cases.
MarkDuckworth Aug 18, 2022
409b19c
Update proto with OR operator.
MarkDuckworth Aug 22, 2022
131f4be
Update protos with OR operator.
MarkDuckworth Aug 23, 2022
a514358
Testing query with indexes
MarkDuckworth Aug 23, 2022
0ab215b
Add compile.sh to compile proto updates.
MarkDuckworth Aug 23, 2022
638b0ad
Adding new script to run browser tests against the emulator.
MarkDuckworth Aug 23, 2022
86c9057
Update stringifyFilter to support CompositeFilters
MarkDuckworth Aug 23, 2022
3501135
Lint and formatting
MarkDuckworth Aug 23, 2022
4adf98d
Refactor core/target.ts, extracting classes Bound, OrderBy, and Filte…
MarkDuckworth Aug 24, 2022
60f4276
Formatting
MarkDuckworth Aug 24, 2022
e0bdb55
Revert a test back to
MarkDuckworth Oct 25, 2022
69fd0d4
Merge branch 'markduckworth/or-queries' of github.com:firebase/fireba…
MarkDuckworth Oct 26, 2022
960d158
Code cleanup - prettier
MarkDuckworth Oct 26, 2022
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
131 changes: 131 additions & 0 deletions packages/firestore/src/core/bound.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* @license
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Document } from '../model/document';
import { DocumentKey } from '../model/document_key';
import { isReferenceValue, valueCompare, valueEquals } from '../model/values';
import { Value as ProtoValue } from '../protos/firestore_proto_api';
import { debugAssert } from '../util/assert';

import { Direction, OrderBy } from './order_by';

/**
* Represents a bound of a query.
*
* The bound is specified with the given components representing a position and
* whether it's just before or just after the position (relative to whatever the
* query order is).
*
* The position represents a logical index position for a query. It's a prefix
* of values for the (potentially implicit) order by clauses of a query.
*
* Bound provides a function to determine whether a document comes before or
* after a bound. This is influenced by whether the position is just before or
* just after the provided values.
*/
export class Bound {
constructor(readonly position: ProtoValue[], readonly inclusive: boolean) {}
}

function boundCompareToDocument(
bound: Bound,
orderBy: OrderBy[],
doc: Document
): number {
debugAssert(
bound.position.length <= orderBy.length,
"Bound has more components than query's orderBy"
);
let comparison = 0;
for (let i = 0; i < bound.position.length; i++) {
const orderByComponent = orderBy[i];
const component = bound.position[i];
if (orderByComponent.field.isKeyField()) {
debugAssert(
isReferenceValue(component),
'Bound has a non-key value where the key path is being used.'
);
comparison = DocumentKey.comparator(
DocumentKey.fromName(component.referenceValue),
doc.key
);
} else {
const docValue = doc.data.field(orderByComponent.field);
debugAssert(
docValue !== null,
'Field should exist since document matched the orderBy already.'
);
comparison = valueCompare(component, docValue);
}
if (orderByComponent.dir === Direction.DESCENDING) {
comparison = comparison * -1;
}
if (comparison !== 0) {
break;
}
}
return comparison;
}

/**
* Returns true if a document sorts after a bound using the provided sort
* order.
*/
export function boundSortsAfterDocument(
bound: Bound,
orderBy: OrderBy[],
doc: Document
): boolean {
const comparison = boundCompareToDocument(bound, orderBy, doc);
return bound.inclusive ? comparison >= 0 : comparison > 0;
}

/**
* Returns true if a document sorts before a bound using the provided sort
* order.
*/
export function boundSortsBeforeDocument(
bound: Bound,
orderBy: OrderBy[],
doc: Document
): boolean {
const comparison = boundCompareToDocument(bound, orderBy, doc);
return bound.inclusive ? comparison <= 0 : comparison < 0;
}

export function boundEquals(left: Bound | null, right: Bound | null): boolean {
if (left === null) {
return right === null;
} else if (right === null) {
return false;
}

if (
left.inclusive !== right.inclusive ||
left.position.length !== right.position.length
) {
return false;
}
for (let i = 0; i < left.position.length; i++) {
const leftPosition = left.position[i];
const rightPosition = right.position[i];
if (!valueEquals(leftPosition, rightPosition)) {
return false;
}
}
return true;
}
Loading