|
17 | 17 | #include "Firestore/core/src/util/logic_utils.h"
|
18 | 18 |
|
19 | 19 | #include <utility>
|
| 20 | +#include <vector> |
20 | 21 |
|
21 | 22 | #include "Firestore/core/src/core/composite_filter.h"
|
22 | 23 | #include "Firestore/core/src/core/field_filter.h"
|
| 24 | +#include "Firestore/core/src/nanopb/message.h" |
23 | 25 | #include "Firestore/core/src/util/hard_assert.h"
|
24 | 26 |
|
25 | 27 | namespace firebase {
|
@@ -254,13 +256,49 @@ Filter LogicUtils::ComputeDistributedNormalForm(const core::Filter& filter) {
|
254 | 256 | return running_result;
|
255 | 257 | }
|
256 | 258 |
|
| 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 | + |
257 | 292 | std::vector<core::Filter> LogicUtils::GetDnfTerms(
|
258 | 293 | const core::CompositeFilter& filter) {
|
259 | 294 | if (filter.IsEmpty()) {
|
260 | 295 | return {};
|
261 | 296 | }
|
262 | 297 |
|
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)); |
264 | 302 |
|
265 | 303 | HARD_ASSERT(
|
266 | 304 | IsDisjunctiveNormalForm(result),
|
|
0 commit comments