Skip to content

Commit 89a67be

Browse files
committed
Relaxing in restrictions.
1 parent fa0a7c0 commit 89a67be

File tree

3 files changed

+237
-60
lines changed

3 files changed

+237
-60
lines changed

packages/firestore/src/lite-api/query.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,20 +1076,14 @@ function conflictingOps(op: Operator): Operator[] {
10761076
case Operator.NOT_EQUAL:
10771077
return [Operator.NOT_EQUAL, Operator.NOT_IN];
10781078
case Operator.ARRAY_CONTAINS:
1079-
return [
1080-
Operator.ARRAY_CONTAINS,
1081-
Operator.ARRAY_CONTAINS_ANY,
1082-
Operator.NOT_IN
1083-
];
1084-
case Operator.IN:
1085-
return [Operator.ARRAY_CONTAINS_ANY, Operator.IN, Operator.NOT_IN];
10861079
case Operator.ARRAY_CONTAINS_ANY:
10871080
return [
10881081
Operator.ARRAY_CONTAINS,
10891082
Operator.ARRAY_CONTAINS_ANY,
1090-
Operator.IN,
10911083
Operator.NOT_IN
10921084
];
1085+
case Operator.IN:
1086+
return [Operator.NOT_IN];
10931087
case Operator.NOT_IN:
10941088
return [
10951089
Operator.ARRAY_CONTAINS,

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

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,6 +1614,241 @@ apiDescribe('Queries', (persistence: boolean) => {
16141614
});
16151615
});
16161616
});
1617+
1618+
// TODO(orquery): Enable this test when prod supports OR queries.
1619+
// eslint-disable-next-line no-restricted-properties
1620+
it.skip('supports multiple in ops', () => {
1621+
const testDocs = {
1622+
doc1: { a: 1, b: 0 },
1623+
doc2: { b: 1 },
1624+
doc3: { a: 3, b: 2 },
1625+
doc4: { a: 1, b: 3 },
1626+
doc5: { a: 1 },
1627+
doc6: { a: 2 }
1628+
};
1629+
1630+
return withTestCollection(persistence, testDocs, async coll => {
1631+
// Two IN operations on different fields with disjunction.
1632+
await checkOnlineAndOfflineResultsMatch(
1633+
query(
1634+
coll,
1635+
or(where('a', 'in', [2, 3]), where('b', 'in', [0, 2])),
1636+
orderBy('a')
1637+
),
1638+
'doc1',
1639+
'doc6',
1640+
'doc3'
1641+
);
1642+
1643+
// Two IN operations on different fields with conjunction.
1644+
await checkOnlineAndOfflineResultsMatch(
1645+
query(
1646+
coll,
1647+
and(where('a', 'in', [2, 3]), where('b', 'in', [0, 2])),
1648+
orderBy('a')
1649+
),
1650+
'doc3'
1651+
);
1652+
1653+
// a IN [2,3] && a IN [0,1,4] is never true and so the result should be an
1654+
// empty set.
1655+
await checkOnlineAndOfflineResultsMatch(
1656+
query(coll, and(where('a', 'in', [2, 3]), where('a', 'in', [0, 1, 4])))
1657+
);
1658+
1659+
// a IN [0,3] || a IN [0,2] should union them (similar to: a IN [0,2,3]).
1660+
await checkOnlineAndOfflineResultsMatch(
1661+
query(coll, or(where('a', 'in', [0, 3]), where('a', 'in', [0, 2]))),
1662+
'doc3',
1663+
'doc6'
1664+
);
1665+
1666+
// Nested composite filter on the same field.
1667+
await checkOnlineAndOfflineResultsMatch(
1668+
query(
1669+
coll,
1670+
and(
1671+
where('a', 'in', [1, 3]),
1672+
or(
1673+
where('a', 'in', [0, 2]),
1674+
and(where('b', '>=', 1), where('a', 'in', [1, 3]))
1675+
)
1676+
)
1677+
),
1678+
'doc3',
1679+
'doc4'
1680+
);
1681+
1682+
// Nested composite filter on the different fields.
1683+
await checkOnlineAndOfflineResultsMatch(
1684+
query(
1685+
coll,
1686+
and(
1687+
where('b', 'in', [0, 3]),
1688+
or(
1689+
where('b', 'in', [1]),
1690+
and(where('b', 'in', [2, 3]), where('a', 'in', [1, 3]))
1691+
)
1692+
)
1693+
),
1694+
'doc4'
1695+
);
1696+
});
1697+
});
1698+
1699+
// TODO(orquery): Enable this test when prod supports OR queries.
1700+
// eslint-disable-next-line no-restricted-properties
1701+
it.skip('supports using in with array contains any', () => {
1702+
const testDocs = {
1703+
doc1: { a: 1, b: [0] },
1704+
doc2: { b: [1] },
1705+
doc3: { a: 3, b: [2, 7], c: 10 },
1706+
doc4: { a: 1, b: [3, 7] },
1707+
doc5: { a: 1 },
1708+
doc6: { a: 2, c: 20 }
1709+
};
1710+
1711+
return withTestCollection(persistence, testDocs, async coll => {
1712+
await checkOnlineAndOfflineResultsMatch(
1713+
query(
1714+
coll,
1715+
or(where('a', 'in', [2, 3]), where('b', 'array-contains-any', [0, 7]))
1716+
),
1717+
'doc1',
1718+
'doc3',
1719+
'doc4',
1720+
'doc6'
1721+
);
1722+
});
1723+
1724+
return withTestCollection(persistence, testDocs, async coll => {
1725+
await checkOnlineAndOfflineResultsMatch(
1726+
query(
1727+
coll,
1728+
and(
1729+
where('a', 'in', [2, 3]),
1730+
where('b', 'array-contains-any', [0, 7])
1731+
)
1732+
),
1733+
'doc3'
1734+
);
1735+
});
1736+
1737+
return withTestCollection(persistence, testDocs, async coll => {
1738+
await checkOnlineAndOfflineResultsMatch(
1739+
query(
1740+
coll,
1741+
or(
1742+
where('a', 'in', [2, 3]),
1743+
where('c', '==', 10),
1744+
where('b', 'array-contains-any', [0, 7])
1745+
)
1746+
),
1747+
'doc1',
1748+
'doc3',
1749+
'doc4'
1750+
);
1751+
});
1752+
1753+
return withTestCollection(persistence, testDocs, async coll => {
1754+
await checkOnlineAndOfflineResultsMatch(
1755+
query(
1756+
coll,
1757+
and(
1758+
where('a', 'in', [2, 3]),
1759+
or(where('b', 'array-contains-any', [0, 7]), where('c', '==', 10))
1760+
)
1761+
),
1762+
'doc3',
1763+
'doc6'
1764+
);
1765+
});
1766+
});
1767+
1768+
// TODO(orquery): Enable this test when prod supports OR queries.
1769+
// eslint-disable-next-line no-restricted-properties
1770+
it.skip('supports using in with array contains', () => {
1771+
const testDocs = {
1772+
doc1: { a: 1, b: [0] },
1773+
doc2: { b: [1] },
1774+
doc3: { a: 3, b: [2, 7] },
1775+
doc4: { a: 1, b: [3, 7] },
1776+
doc5: { a: 1 },
1777+
doc6: { a: 2 }
1778+
};
1779+
1780+
return withTestCollection(persistence, testDocs, async coll => {
1781+
await checkOnlineAndOfflineResultsMatch(
1782+
query(
1783+
coll,
1784+
or(where('a', 'in', [2, 3]), where('b', 'array-contains', 3))
1785+
),
1786+
'doc3',
1787+
'doc4',
1788+
'doc6'
1789+
);
1790+
});
1791+
1792+
return withTestCollection(persistence, testDocs, async coll => {
1793+
await checkOnlineAndOfflineResultsMatch(
1794+
query(
1795+
coll,
1796+
and(where('a', 'in', [2, 3]), where('b', 'array-contains', 7))
1797+
),
1798+
'doc3'
1799+
);
1800+
});
1801+
1802+
return withTestCollection(persistence, testDocs, async coll => {
1803+
await checkOnlineAndOfflineResultsMatch(
1804+
query(
1805+
coll,
1806+
or(
1807+
where('a', 'in', [2, 3]),
1808+
and(where('b', 'array-contains', 3), where('b', '==', 1))
1809+
)
1810+
),
1811+
'doc3',
1812+
'doc4',
1813+
'doc6'
1814+
);
1815+
});
1816+
1817+
return withTestCollection(persistence, testDocs, async coll => {
1818+
await checkOnlineAndOfflineResultsMatch(
1819+
query(
1820+
coll,
1821+
and(
1822+
where('a', 'in', [2, 3]),
1823+
or(where('b', 'array-contains', 7), where('a', '==', 1))
1824+
)
1825+
),
1826+
'doc3'
1827+
);
1828+
});
1829+
});
1830+
1831+
// TODO(orquery): Enable this test when prod supports OR queries.
1832+
// eslint-disable-next-line no-restricted-properties
1833+
it.skip('supports order by equality', () => {
1834+
const testDocs = {
1835+
doc1: { a: 1, b: [0] },
1836+
doc2: { b: [1] },
1837+
doc3: { a: 3, b: [2, 7], c: 10 },
1838+
doc4: { a: 1, b: [3, 7] },
1839+
doc5: { a: 1 },
1840+
doc6: { a: 2, c: 20 }
1841+
};
1842+
1843+
return withTestCollection(persistence, testDocs, async coll => {
1844+
await checkOnlineAndOfflineResultsMatch(
1845+
query(coll, where('a', '==', 1), orderBy('a')),
1846+
'doc1',
1847+
'doc4',
1848+
'doc5'
1849+
);
1850+
});
1851+
});
16171852
});
16181853

16191854
function verifyDocumentChange<T>(

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

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -962,14 +962,6 @@ apiDescribe('Validation:', (persistence: boolean) => {
962962
});
963963

964964
validationIt(persistence, 'with multiple disjunctive filters fail', db => {
965-
expect(() =>
966-
query(
967-
collection(db, 'test'),
968-
where('foo', 'in', [1, 2]),
969-
where('foo', 'in', [2, 3])
970-
)
971-
).to.throw("Invalid query. You cannot use more than one 'in' filter.");
972-
973965
expect(() =>
974966
query(
975967
collection(db, 'test'),
@@ -991,28 +983,6 @@ apiDescribe('Validation:', (persistence: boolean) => {
991983
' filter.'
992984
);
993985

994-
expect(() =>
995-
query(
996-
collection(db, 'test'),
997-
where('foo', 'array-contains-any', [2, 3]),
998-
where('foo', 'in', [2, 3])
999-
)
1000-
).to.throw(
1001-
"Invalid query. You cannot use 'in' filters with " +
1002-
"'array-contains-any' filters."
1003-
);
1004-
1005-
expect(() =>
1006-
query(
1007-
collection(db, 'test'),
1008-
where('foo', 'in', [2, 3]),
1009-
where('foo', 'array-contains-any', [2, 3])
1010-
)
1011-
).to.throw(
1012-
"Invalid query. You cannot use 'array-contains-any' filters with " +
1013-
"'in' filters."
1014-
);
1015-
1016986
expect(() =>
1017987
query(
1018988
collection(db, 'test'),
@@ -1055,19 +1025,6 @@ apiDescribe('Validation:', (persistence: boolean) => {
10551025
"Invalid query. You cannot use 'not-in' filters with 'in' filters."
10561026
);
10571027

1058-
// This is redundant with the above tests, but makes sure our validation
1059-
// doesn't get confused.
1060-
expect(() =>
1061-
query(
1062-
collection(db, 'test'),
1063-
where('foo', 'in', [2, 3]),
1064-
where('foo', 'array-contains', 1),
1065-
where('foo', 'array-contains-any', [2])
1066-
)
1067-
).to.throw(
1068-
"Invalid query. You cannot use 'array-contains-any' filters with 'in' filters."
1069-
);
1070-
10711028
expect(() =>
10721029
query(
10731030
collection(db, 'test'),
@@ -1135,15 +1092,6 @@ apiDescribe('Validation:', (persistence: boolean) => {
11351092
).to.throw(
11361093
"Invalid query. You cannot use more than one 'array-contains' filter."
11371094
);
1138-
1139-
expect(() =>
1140-
query(
1141-
collection(db, 'test'),
1142-
where('foo', 'array-contains', 1),
1143-
where('foo', 'in', [2, 3]),
1144-
where('foo', 'in', [2, 3])
1145-
)
1146-
).to.throw("Invalid query. You cannot use more than one 'in' filter.");
11471095
}
11481096
);
11491097

0 commit comments

Comments
 (0)