Skip to content

Commit d5198ac

Browse files
authored
Performing IN expansion (#10410)
* Performing IN expansion * Add tests * change the implementation of GetDocumentsMatchingTarget
1 parent db6af01 commit d5198ac

File tree

6 files changed

+580
-56
lines changed

6 files changed

+580
-56
lines changed

Firestore/core/src/local/leveldb_index_manager.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,14 +536,13 @@ IndexManager::IndexType LevelDbIndexManager::GetIndexType(
536536

537537
absl::optional<std::vector<model::DocumentKey>>
538538
LevelDbIndexManager::GetDocumentsMatchingTarget(const core::Target& target) {
539-
std::unordered_map<core::Target, model::FieldIndex> indexes;
539+
std::vector<std::pair<core::Target, model::FieldIndex>> indexes;
540540
for (const auto& sub_target : GetSubTargets(target)) {
541541
auto index_opt = GetFieldIndex(sub_target);
542542
if (!index_opt.has_value()) {
543543
return absl::nullopt;
544544
}
545-
546-
indexes.insert({sub_target, index_opt.value()});
545+
indexes.emplace_back(sub_target, index_opt.value());
547546
}
548547

549548
std::vector<DocumentKey> result;

Firestore/core/src/util/logic_utils.cc

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
#include "Firestore/core/src/util/logic_utils.h"
1818

1919
#include <utility>
20+
#include <vector>
2021

2122
#include "Firestore/core/src/core/composite_filter.h"
2223
#include "Firestore/core/src/core/field_filter.h"
24+
#include "Firestore/core/src/nanopb/message.h"
2325
#include "Firestore/core/src/util/hard_assert.h"
2426

2527
namespace firebase {
@@ -254,13 +256,49 @@ Filter LogicUtils::ComputeDistributedNormalForm(const core::Filter& filter) {
254256
return running_result;
255257
}
256258

259+
Filter LogicUtils::ComputeInExpansion(const Filter& filter) {
260+
AssertFieldFilterOrCompositeFilter(filter);
261+
262+
std::vector<Filter> expanded_filters;
263+
264+
if (filter.IsAFieldFilter()) {
265+
if (filter.type() == Filter::Type::kInFilter) {
266+
// We have reached a field filter with `in` operator.
267+
FieldFilter in_filter(filter);
268+
for (pb_size_t i = 0; i < in_filter.value().array_value.values_count;
269+
++i) {
270+
expanded_filters.push_back(
271+
FieldFilter::Create(in_filter.field(), FieldFilter::Operator::Equal,
272+
nanopb::MakeSharedMessage(
273+
in_filter.value().array_value.values[i])));
274+
}
275+
return CompositeFilter::Create(std::move(expanded_filters),
276+
CompositeFilter::Operator::Or);
277+
} else {
278+
// We have reached other kinds of field filters.
279+
return filter;
280+
}
281+
}
282+
283+
// We have a composite filter.
284+
CompositeFilter composite_filter(filter);
285+
for (const auto& subfilter : composite_filter.filters()) {
286+
expanded_filters.push_back(ComputeInExpansion(subfilter));
287+
}
288+
return CompositeFilter::Create(std::move(expanded_filters),
289+
composite_filter.op());
290+
}
291+
257292
std::vector<core::Filter> LogicUtils::GetDnfTerms(
258293
const core::CompositeFilter& filter) {
259294
if (filter.IsEmpty()) {
260295
return {};
261296
}
262297

263-
Filter result = ComputeDistributedNormalForm(filter);
298+
// The `in` operator is a syntactic sugar over a disjunction of equalities.
299+
// We should first replace such filters with equality filters before running
300+
// the DNF transform.
301+
Filter result = ComputeDistributedNormalForm(ComputeInExpansion(filter));
264302

265303
HARD_ASSERT(
266304
IsDisjunctiveNormalForm(result),

Firestore/core/src/util/logic_utils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ class LogicUtils {
9090

9191
static core::Filter ComputeDistributedNormalForm(const core::Filter& filter);
9292

93+
/**
94+
* The `in` filter is only a syntactic sugar over a disjunction of equalities.
95+
* For instance: `a in [1,2,3]` is in fact `a==1 || a==2 || a==3`. This method
96+
* expands any `in` filter in the given input into a disjunction of equality
97+
* filters and returns the expanded filter.
98+
*/
99+
static core::Filter ComputeInExpansion(const core::Filter& filter);
100+
93101
private:
94102
/**
95103
* Asserts that the given filter is a FieldFilter or CompositeFilter.

0 commit comments

Comments
 (0)