aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/core/src/firebase
diff options
context:
space:
mode:
Diffstat (limited to 'Firestore/core/src/firebase')
-rw-r--r--Firestore/core/src/firebase/firestore/core/CMakeLists.txt4
-rw-r--r--Firestore/core/src/firebase/firestore/core/filter.cc41
-rw-r--r--Firestore/core/src/firebase/firestore/core/filter.h70
-rw-r--r--Firestore/core/src/firebase/firestore/core/query.cc24
-rw-r--r--Firestore/core/src/firebase/firestore/core/query.h28
-rw-r--r--Firestore/core/src/firebase/firestore/core/relation_filter.cc77
-rw-r--r--Firestore/core/src/firebase/firestore/core/relation_filter.h59
-rw-r--r--Firestore/core/src/firebase/firestore/model/field_value.cc34
-rw-r--r--Firestore/core/src/firebase/firestore/model/field_value.h9
9 files changed, 319 insertions, 27 deletions
diff --git a/Firestore/core/src/firebase/firestore/core/CMakeLists.txt b/Firestore/core/src/firebase/firestore/core/CMakeLists.txt
index 1aab09a..c1557b2 100644
--- a/Firestore/core/src/firebase/firestore/core/CMakeLists.txt
+++ b/Firestore/core/src/firebase/firestore/core/CMakeLists.txt
@@ -17,10 +17,14 @@ cc_library(
SOURCES
database_info.cc
database_info.h
+ filter.cc
+ filter.h
target_id_generator.cc
target_id_generator.h
query.cc
query.h
+ relation_filter.cc
+ relation_filter.h
DEPENDS
absl_strings
firebase_firestore_model
diff --git a/Firestore/core/src/firebase/firestore/core/filter.cc b/Firestore/core/src/firebase/firestore/core/filter.cc
new file mode 100644
index 0000000..4c27f27
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/core/filter.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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.
+ */
+
+#include "Firestore/core/src/firebase/firestore/core/filter.h"
+
+#include <utility>
+
+#include "Firestore/core/src/firebase/firestore/core/relation_filter.h"
+
+namespace firebase {
+namespace firestore {
+namespace core {
+
+using model::FieldPath;
+using model::FieldValue;
+
+std::shared_ptr<Filter> Filter::Create(FieldPath path,
+ Operator op,
+ FieldValue value) {
+ // TODO(rsgowman): Java performs a number of checks here, and then invokes the
+ // ctor of the relevant Filter subclass. Port those checks here.
+ return std::make_shared<RelationFilter>(std::move(path), op,
+ std::move(value));
+}
+
+} // namespace core
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/src/firebase/firestore/core/filter.h b/Firestore/core/src/firebase/firestore/core/filter.h
new file mode 100644
index 0000000..9f25a39
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/core/filter.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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.
+ */
+
+#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_CORE_FILTER_H_
+#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_CORE_FILTER_H_
+
+#include <memory>
+#include <string>
+
+#include "Firestore/core/src/firebase/firestore/model/document.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/model/field_value.h"
+
+namespace firebase {
+namespace firestore {
+namespace core {
+
+/** Interface used for all query filters. All filters are immutable. */
+class Filter {
+ public:
+ enum class Operator {
+ LessThan,
+ LessThanOrEqual,
+ Equal,
+ GreaterThan,
+ GreaterThanOrEqual,
+ };
+
+ /**
+ * Creates a Filter instance for the provided path, operator, and value.
+ *
+ * Note that if the relational operator is Equal and the value is NullValue or
+ * NaN, then this will return the appropriate NullFilter or NaNFilter class
+ * instead of a RelationFilter.
+ */
+ static std::shared_ptr<Filter> Create(model::FieldPath path,
+ Operator op,
+ model::FieldValue value);
+
+ virtual ~Filter() {
+ }
+
+ /** Returns the field the Filter operates over. */
+ virtual const model::FieldPath& field() const = 0;
+
+ /** Returns true if a document matches the filter. */
+ virtual bool Matches(const model::Document& doc) const = 0;
+
+ /** A unique ID identifying the filter; used when serializing queries. */
+ virtual std::string CanonicalId() const = 0;
+};
+
+} // namespace core
+} // namespace firestore
+} // namespace firebase
+
+#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_CORE_FILTER_H_
diff --git a/Firestore/core/src/firebase/firestore/core/query.cc b/Firestore/core/src/firebase/firestore/core/query.cc
index ad0f7a3..0c0a0fd 100644
--- a/Firestore/core/src/firebase/firestore/core/query.cc
+++ b/Firestore/core/src/firebase/firestore/core/query.cc
@@ -16,8 +16,12 @@
#include "Firestore/core/src/firebase/firestore/core/query.h"
+#include <algorithm>
+
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
+#include "Firestore/core/src/firebase/firestore/util/hard_assert.h"
namespace firebase {
namespace firestore {
@@ -41,9 +45,11 @@ bool Query::MatchesPath(const Document& doc) const {
}
}
-bool Query::MatchesFilters(const Document&) const {
- // TODO(rsgowman): Implement this correctly.
- return true;
+bool Query::MatchesFilters(const Document& doc) const {
+ return std::all_of(filters_.begin(), filters_.end(),
+ [&](const std::shared_ptr<core::Filter>& filter) {
+ return filter->Matches(doc);
+ });
}
bool Query::MatchesOrderBy(const Document&) const {
@@ -56,6 +62,18 @@ bool Query::MatchesBounds(const Document&) const {
return true;
}
+Query Query::Filter(std::shared_ptr<core::Filter> filter) const {
+ HARD_ASSERT(!DocumentKey::IsDocumentKey(path_),
+ "No filter is allowed for document query");
+
+ // TODO(rsgowman): ensure only one inequality field
+ // TODO(rsgowman): ensure first orderby must match inequality field
+
+ std::vector<std::shared_ptr<core::Filter>> updated_filters = filters_;
+ updated_filters.push_back(std::move(filter));
+ return Query(path_, std::move(updated_filters));
+}
+
} // namespace core
} // namespace firestore
} // namespace firebase
diff --git a/Firestore/core/src/firebase/firestore/core/query.h b/Firestore/core/src/firebase/firestore/core/query.h
index 84d645d..3df1d25 100644
--- a/Firestore/core/src/firebase/firestore/core/query.h
+++ b/Firestore/core/src/firebase/firestore/core/query.h
@@ -17,8 +17,11 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_CORE_QUERY_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_CORE_QUERY_H_
+#include <memory>
#include <utility>
+#include <vector>
+#include "Firestore/core/src/firebase/firestore/core/filter.h"
#include "Firestore/core/src/firebase/firestore/model/document.h"
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
@@ -26,7 +29,10 @@ namespace firebase {
namespace firestore {
namespace core {
-/** Represents the internal structure of a Firestore Query. */
+/**
+ * Represents the internal structure of a Firestore Query. Query instances are
+ * immutable.
+ */
class Query {
public:
/**
@@ -36,14 +42,17 @@ class Query {
* @return A new instance of Query.
*/
static Query AtPath(model::ResourcePath path) {
- return Query(std::move(path));
+ return Query(std::move(path), {});
}
/** Initializes a query with all of its components directly. */
- explicit Query(model::ResourcePath path /* TODO(rsgowman): other params */)
- : path_(std::move(path)) {
+ Query(model::ResourcePath path,
+ std::vector<std::shared_ptr<core::Filter>>
+ filters /* TODO(rsgowman): other params */)
+ : path_(std::move(path)), filters_(std::move(filters)) {
}
+ /** The base path of the query. */
const model::ResourcePath& path() const {
return path_;
}
@@ -51,6 +60,11 @@ class Query {
/** Returns true if the document matches the constraints of this query. */
bool Matches(const model::Document& doc) const;
+ /**
+ * Returns a copy of this Query object with the additional specified filter.
+ */
+ Query Filter(std::shared_ptr<core::Filter> filter) const;
+
private:
bool MatchesPath(const model::Document& doc) const;
bool MatchesFilters(const model::Document& doc) const;
@@ -58,6 +72,12 @@ class Query {
bool MatchesBounds(const model::Document& doc) const;
const model::ResourcePath path_;
+
+ // Filters are shared across related Query instance. i.e. when you call
+ // Query::Filter(f), a new Query instance is created that contains all of the
+ // existing filters, plus the new one. (Both Query and Filter objects are
+ // immutable.) Filters are not shared across unrelated Query instances.
+ const std::vector<std::shared_ptr<core::Filter>> filters_;
};
} // namespace core
diff --git a/Firestore/core/src/firebase/firestore/core/relation_filter.cc b/Firestore/core/src/firebase/firestore/core/relation_filter.cc
new file mode 100644
index 0000000..a6ae916
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/core/relation_filter.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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.
+ */
+
+#include "Firestore/core/src/firebase/firestore/core/relation_filter.h"
+
+#include <utility>
+
+#include "absl/types/optional.h"
+
+namespace firebase {
+namespace firestore {
+namespace core {
+
+using model::FieldPath;
+using model::FieldValue;
+
+RelationFilter::RelationFilter(FieldPath field, Operator op, FieldValue value)
+ : field_(std::move(field)), op_(op), value_(std::move(value)) {
+}
+
+const FieldPath& RelationFilter::field() const {
+ return field_;
+}
+
+bool RelationFilter::Matches(const model::Document& doc) const {
+ if (field_.IsKeyFieldPath()) {
+ // TODO(rsgowman): Port this case
+ abort();
+ } else {
+ absl::optional<FieldValue> doc_field_value = doc.field(field_);
+ return doc_field_value && MatchesValue(doc_field_value.value());
+ }
+}
+
+bool RelationFilter::MatchesValue(const FieldValue& other) const {
+ // Only compare types with matching backend order (such as double and int).
+ return FieldValue::Comparable(value_.type(), other.type()) &&
+ MatchesComparison(other);
+}
+
+bool RelationFilter::MatchesComparison(const FieldValue& other) const {
+ switch (op_) {
+ case Operator::LessThan:
+ return value_ < other;
+ case Operator::LessThanOrEqual:
+ return value_ <= other;
+ case Operator::Equal:
+ return value_ == other;
+ case Operator::GreaterThan:
+ return value_ > other;
+ case Operator::GreaterThanOrEqual:
+ return value_ >= other;
+ }
+ UNREACHABLE();
+}
+
+std::string RelationFilter::CanonicalId() const {
+ // TODO(rsgowman): Port this
+ abort();
+}
+
+} // namespace core
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/src/firebase/firestore/core/relation_filter.h b/Firestore/core/src/firebase/firestore/core/relation_filter.h
new file mode 100644
index 0000000..94da208
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/core/relation_filter.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2018 Google
+ *
+ * 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.
+ */
+
+#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_CORE_RELATION_FILTER_H_
+#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_CORE_RELATION_FILTER_H_
+
+#include <string>
+
+#include "Firestore/core/src/firebase/firestore/core/filter.h"
+#include "Firestore/core/src/firebase/firestore/model/document.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/model/field_value.h"
+
+namespace firebase {
+namespace firestore {
+namespace core {
+
+/** Represents a filter to be applied to the query. */
+class RelationFilter : public Filter {
+ public:
+ /**
+ * Creates a new filter that compares fields and values. Only intended to be
+ * called from Filter::Create().
+ */
+ RelationFilter(model::FieldPath field, Operator op, model::FieldValue value);
+
+ const model::FieldPath& field() const override;
+
+ bool Matches(const model::Document& doc) const override;
+
+ std::string CanonicalId() const override;
+
+ private:
+ bool MatchesValue(const model::FieldValue& other) const;
+ bool MatchesComparison(const model::FieldValue& other) const;
+
+ const model::FieldPath field_;
+ const Operator op_;
+ const model::FieldValue value_;
+};
+
+} // namespace core
+} // namespace firestore
+} // namespace firebase
+
+#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_CORE_RELATION_FILTER_H_
diff --git a/Firestore/core/src/firebase/firestore/model/field_value.cc b/Firestore/core/src/firebase/firestore/model/field_value.cc
index 4f92c8b..d2fadc8 100644
--- a/Firestore/core/src/firebase/firestore/model/field_value.cc
+++ b/Firestore/core/src/firebase/firestore/model/field_value.cc
@@ -35,25 +35,6 @@ using Type = FieldValue::Type;
using firebase::firestore::util::ComparisonResult;
namespace {
-/**
- * This deviates from the other platforms that define TypeOrder. Since
- * we already define Type for union types, we use it together with this
- * function to achieve the equivalent order of types i.e.
- * i) if two types are comparable, then they are of equal order;
- * ii) otherwise, their order is the same as the order of their Type.
- */
-bool Comparable(Type lhs, Type rhs) {
- switch (lhs) {
- case Type::Integer:
- case Type::Double:
- return rhs == Type::Integer || rhs == Type::Double;
- case Type::Timestamp:
- case Type::ServerTimestamp:
- return rhs == Type::Timestamp || rhs == Type::ServerTimestamp;
- default:
- return lhs == rhs;
- }
-}
// Makes a copy excluding the specified child, which is expected to be assigned
// different value afterwards.
@@ -165,6 +146,19 @@ FieldValue& FieldValue::operator=(FieldValue&& value) {
}
}
+bool FieldValue::Comparable(Type lhs, Type rhs) {
+ switch (lhs) {
+ case Type::Integer:
+ case Type::Double:
+ return rhs == Type::Integer || rhs == Type::Double;
+ case Type::Timestamp:
+ case Type::ServerTimestamp:
+ return rhs == Type::Timestamp || rhs == Type::ServerTimestamp;
+ default:
+ return lhs == rhs;
+ }
+}
+
FieldValue FieldValue::Set(const FieldPath& field_path,
FieldValue value) const {
HARD_ASSERT(type() == Type::Object,
@@ -379,7 +373,7 @@ FieldValue FieldValue::ObjectValueFromMap(ObjectValue::Map&& value) {
}
bool operator<(const FieldValue& lhs, const FieldValue& rhs) {
- if (!Comparable(lhs.type(), rhs.type())) {
+ if (!FieldValue::Comparable(lhs.type(), rhs.type())) {
return lhs.type() < rhs.type();
}
diff --git a/Firestore/core/src/firebase/firestore/model/field_value.h b/Firestore/core/src/firebase/firestore/model/field_value.h
index 09c8531..697d5b3 100644
--- a/Firestore/core/src/firebase/firestore/model/field_value.h
+++ b/Firestore/core/src/firebase/firestore/model/field_value.h
@@ -108,6 +108,15 @@ class FieldValue {
return tag_;
}
+ /**
+ * PORTING NOTE: This deviates from the other platforms that define TypeOrder.
+ * Since we already define Type for union types, we use it together with this
+ * function to achieve the equivalent order of types i.e.
+ * i) if two types are comparable, then they are of equal order;
+ * ii) otherwise, their order is the same as the order of their Type.
+ */
+ static bool Comparable(Type lhs, Type rhs);
+
bool boolean_value() const {
HARD_ASSERT(tag_ == Type::Boolean);
return boolean_value_;