Skip to content

Commit 04c9c3a

Browse files
authored
b/79432277: Limit Queries to only a single array-contains clause. (#835)
1 parent 2e5aa28 commit 04c9c3a

File tree

3 files changed

+52
-14
lines changed

3 files changed

+52
-14
lines changed

packages/firestore/src/api/database.ts

+27-14
Original file line numberDiff line numberDiff line change
@@ -1735,21 +1735,34 @@ export class Query implements firestore.Query {
17351735
}
17361736

17371737
private validateNewFilter(filter: Filter): void {
1738-
if (filter instanceof RelationFilter && filter.isInequality()) {
1739-
const existingField = this._query.getInequalityFilterField();
1740-
if (existingField !== null && !existingField.isEqual(filter.field)) {
1741-
throw new FirestoreError(
1742-
Code.INVALID_ARGUMENT,
1743-
'Invalid query. All where filters with an inequality' +
1744-
' (<, <=, >, or >=) must be on the same field. But you have' +
1745-
` inequality filters on '${existingField.toString()}'` +
1746-
` and '${filter.field.toString()}'`
1747-
);
1748-
}
1738+
if (filter instanceof RelationFilter) {
1739+
if (filter.isInequality()) {
1740+
const existingField = this._query.getInequalityFilterField();
1741+
if (existingField !== null && !existingField.isEqual(filter.field)) {
1742+
throw new FirestoreError(
1743+
Code.INVALID_ARGUMENT,
1744+
'Invalid query. All where filters with an inequality' +
1745+
' (<, <=, >, or >=) must be on the same field. But you have' +
1746+
` inequality filters on '${existingField.toString()}'` +
1747+
` and '${filter.field.toString()}'`
1748+
);
1749+
}
17491750

1750-
const firstOrderByField = this._query.getFirstOrderByField();
1751-
if (firstOrderByField !== null) {
1752-
this.validateOrderByAndInequalityMatch(filter.field, firstOrderByField);
1751+
const firstOrderByField = this._query.getFirstOrderByField();
1752+
if (firstOrderByField !== null) {
1753+
this.validateOrderByAndInequalityMatch(
1754+
filter.field,
1755+
firstOrderByField
1756+
);
1757+
}
1758+
} else if (filter.op === RelationOp.ARRAY_CONTAINS) {
1759+
if (this._query.hasArrayContainsFilter()) {
1760+
throw new FirestoreError(
1761+
Code.INVALID_ARGUMENT,
1762+
'Invalid query. Queries only support a single array-contains ' +
1763+
'filter.'
1764+
);
1765+
}
17531766
}
17541767
}
17551768
}

packages/firestore/src/core/query.ts

+10
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,16 @@ export class Query {
316316
return null;
317317
}
318318

319+
hasArrayContainsFilter(): boolean {
320+
return (
321+
this.filters.find(
322+
filter =>
323+
filter instanceof RelationFilter &&
324+
filter.op === RelationOp.ARRAY_CONTAINS
325+
) !== undefined
326+
);
327+
}
328+
319329
isDocumentQuery(): boolean {
320330
return DocumentKey.isDocumentKey(this.path) && this.filters.length === 0;
321331
}

packages/firestore/test/integration/api/validation.test.ts

+15
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,21 @@ apiDescribe('Validation:', persistence => {
790790
}
791791
);
792792

793+
validationIt(
794+
persistence,
795+
'with multiple array-contains filters fail.',
796+
db => {
797+
expect(() =>
798+
db
799+
.collection('test')
800+
.where('foo', arrayContainsOp, 1)
801+
.where('foo', arrayContainsOp, 2)
802+
).to.throw(
803+
'Invalid query. Queries only support a single array-contains filter.'
804+
);
805+
}
806+
);
807+
793808
validationIt(
794809
persistence,
795810
'must not specify starting or ending point after orderBy',

0 commit comments

Comments
 (0)