aboutsummaryrefslogtreecommitdiff
path: root/icing/query
diff options
context:
space:
mode:
Diffstat (limited to 'icing/query')
-rw-r--r--icing/query/advanced_query_parser/parser.cc24
-rw-r--r--icing/query/advanced_query_parser/query-visitor.cc43
-rw-r--r--icing/query/advanced_query_parser/query-visitor.h14
-rw-r--r--icing/query/advanced_query_parser/query-visitor_test.cc1017
-rw-r--r--icing/query/query-features.h6
-rw-r--r--icing/query/query-processor.cc11
-rw-r--r--icing/query/query-processor_test.cc145
7 files changed, 843 insertions, 417 deletions
diff --git a/icing/query/advanced_query_parser/parser.cc b/icing/query/advanced_query_parser/parser.cc
index fd74561..82576a1 100644
--- a/icing/query/advanced_query_parser/parser.cc
+++ b/icing/query/advanced_query_parser/parser.cc
@@ -116,7 +116,7 @@ Parser::ConsumeMember() {
// Member could be either `TEXT (DOT TEXT)* (DOT function)?` or `TEXT STAR`
// at this point. So check for 'STAR' to differentiate the two cases.
if (Match(Lexer::TokenType::STAR)) {
- Consume(Lexer::TokenType::STAR);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::STAR));
std::string_view raw_text = text_node->raw_value();
std::string text = std::move(*text_node).value();
text_node = std::make_unique<TextNode>(std::move(text), raw_text,
@@ -125,7 +125,7 @@ Parser::ConsumeMember() {
} else {
children.push_back(std::move(text_node));
while (Match(Lexer::TokenType::DOT)) {
- Consume(Lexer::TokenType::DOT);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::DOT));
if (MatchFunction()) {
ICING_ASSIGN_OR_RETURN(std::unique_ptr<FunctionNode> function_node,
ConsumeFunction());
@@ -201,7 +201,7 @@ Parser::ConsumeArgs() {
ICING_ASSIGN_OR_RETURN(std::unique_ptr<Node> arg, ConsumeExpression());
args.push_back(std::move(arg));
while (Match(Lexer::TokenType::COMMA)) {
- Consume(Lexer::TokenType::COMMA);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::COMMA));
ICING_ASSIGN_OR_RETURN(arg, ConsumeExpression());
args.push_back(std::move(arg));
}
@@ -223,7 +223,7 @@ Parser::ConsumeRestriction() {
bool has_minus = Match(Lexer::TokenType::MINUS);
if (has_minus) {
- Consume(Lexer::TokenType::MINUS);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::MINUS));
}
std::unique_ptr<Node> arg;
@@ -276,10 +276,10 @@ libtextclassifier3::StatusOr<std::unique_ptr<Node>> Parser::ConsumeTerm() {
operator_text = "MINUS";
} else {
if (Match(Lexer::TokenType::NOT)) {
- Consume(Lexer::TokenType::NOT);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::NOT));
operator_text = "NOT";
} else {
- Consume(Lexer::TokenType::MINUS);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::MINUS));
operator_text = "MINUS";
}
}
@@ -296,7 +296,7 @@ libtextclassifier3::StatusOr<std::unique_ptr<Node>> Parser::ConsumeFactor() {
terms.push_back(std::move(term));
while (Match(Lexer::TokenType::OR)) {
- Consume(Lexer::TokenType::OR);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::OR));
ICING_ASSIGN_OR_RETURN(term, ConsumeTerm());
terms.push_back(std::move(term));
}
@@ -330,7 +330,7 @@ Parser::ConsumeQueryExpression() {
sequences.push_back(std::move(sequence));
while (Match(Lexer::TokenType::AND)) {
- Consume(Lexer::TokenType::AND);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::AND));
ICING_ASSIGN_OR_RETURN(sequence, ConsumeSequence());
sequences.push_back(std::move(sequence));
}
@@ -348,7 +348,7 @@ libtextclassifier3::StatusOr<std::unique_ptr<Node>> Parser::ConsumeMultExpr() {
while (Match(Lexer::TokenType::TIMES) || Match(Lexer::TokenType::DIV)) {
while (Match(Lexer::TokenType::TIMES)) {
- Consume(Lexer::TokenType::TIMES);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::TIMES));
ICING_ASSIGN_OR_RETURN(node, ConsumeTerm());
stack.push_back(std::move(node));
}
@@ -357,7 +357,7 @@ libtextclassifier3::StatusOr<std::unique_ptr<Node>> Parser::ConsumeMultExpr() {
stack.push_back(std::move(node));
while (Match(Lexer::TokenType::DIV)) {
- Consume(Lexer::TokenType::DIV);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::DIV));
ICING_ASSIGN_OR_RETURN(node, ConsumeTerm());
stack.push_back(std::move(node));
}
@@ -380,7 +380,7 @@ Parser::ConsumeScoringExpression() {
while (Match(Lexer::TokenType::PLUS) || Match(Lexer::TokenType::MINUS)) {
while (Match(Lexer::TokenType::PLUS)) {
- Consume(Lexer::TokenType::PLUS);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::PLUS));
ICING_ASSIGN_OR_RETURN(node, ConsumeMultExpr());
stack.push_back(std::move(node));
}
@@ -389,7 +389,7 @@ Parser::ConsumeScoringExpression() {
stack.push_back(std::move(node));
while (Match(Lexer::TokenType::MINUS)) {
- Consume(Lexer::TokenType::MINUS);
+ ICING_RETURN_IF_ERROR(Consume(Lexer::TokenType::MINUS));
ICING_ASSIGN_OR_RETURN(node, ConsumeMultExpr());
stack.push_back(std::move(node));
}
diff --git a/icing/query/advanced_query_parser/query-visitor.cc b/icing/query/advanced_query_parser/query-visitor.cc
index d75a550..31da959 100644
--- a/icing/query/advanced_query_parser/query-visitor.cc
+++ b/icing/query/advanced_query_parser/query-visitor.cc
@@ -33,9 +33,11 @@
#include "icing/index/iterator/doc-hit-info-iterator-none.h"
#include "icing/index/iterator/doc-hit-info-iterator-not.h"
#include "icing/index/iterator/doc-hit-info-iterator-or.h"
+#include "icing/index/iterator/doc-hit-info-iterator-property-in-document.h"
#include "icing/index/iterator/doc-hit-info-iterator-property-in-schema.h"
#include "icing/index/iterator/doc-hit-info-iterator-section-restrict.h"
#include "icing/index/iterator/doc-hit-info-iterator.h"
+#include "icing/index/property-existence-indexing-handler.h"
#include "icing/query/advanced_query_parser/lexer.h"
#include "icing/query/advanced_query_parser/param.h"
#include "icing/query/advanced_query_parser/parser.h"
@@ -222,13 +224,23 @@ void QueryVisitor::RegisterFunctions() {
auto property_defined = [this](std::vector<PendingValue>&& args) {
return this->PropertyDefinedFunction(std::move(args));
};
-
Function property_defined_function =
Function::Create(DataType::kDocumentIterator, "propertyDefined",
{Param(DataType::kString)}, std::move(property_defined))
.ValueOrDie();
registered_functions_.insert(
{property_defined_function.name(), std::move(property_defined_function)});
+
+ // DocHitInfoIterator hasProperty(std::string);
+ auto has_property = [this](std::vector<PendingValue>&& args) {
+ return this->HasPropertyFunction(std::move(args));
+ };
+ Function has_property_function =
+ Function::Create(DataType::kDocumentIterator, "hasProperty",
+ {Param(DataType::kString)}, std::move(has_property))
+ .ValueOrDie();
+ registered_functions_.insert(
+ {has_property_function.name(), std::move(has_property_function)});
}
libtextclassifier3::StatusOr<PendingValue> QueryVisitor::SearchFunction(
@@ -279,7 +291,7 @@ libtextclassifier3::StatusOr<PendingValue> QueryVisitor::SearchFunction(
// Update members based on results of processing the query.
if (args.size() == 2 &&
pending_property_restricts_.has_active_property_restricts()) {
- iterator = std::make_unique<DocHitInfoIteratorSectionRestrict>(
+ iterator = DocHitInfoIteratorSectionRestrict::ApplyRestrictions(
std::move(iterator), &document_store_, &schema_store_,
pending_property_restricts_.active_property_restricts(),
current_time_ms_);
@@ -322,6 +334,31 @@ QueryVisitor::PropertyDefinedFunction(std::vector<PendingValue>&& args) {
return PendingValue(std::move(property_in_schema_iterator));
}
+libtextclassifier3::StatusOr<PendingValue> QueryVisitor::HasPropertyFunction(
+ std::vector<PendingValue>&& args) {
+ // The first arg is guaranteed to be a STRING at this point. It should be safe
+ // to call ValueOrDie.
+ const std::string& property_path = args.at(0).string_val().ValueOrDie()->term;
+
+ // Perform an exact search for the property existence metadata token.
+ ICING_ASSIGN_OR_RETURN(
+ std::unique_ptr<DocHitInfoIterator> meta_hit_iterator,
+ index_.GetIterator(
+ absl_ports::StrCat(kPropertyExistenceTokenPrefix, property_path),
+ /*term_start_index=*/0,
+ /*unnormalized_term_length=*/0, kSectionIdMaskAll,
+ TermMatchType::EXACT_ONLY,
+ /*need_hit_term_frequency=*/false));
+
+ std::unique_ptr<DocHitInfoIterator> property_in_document_iterator =
+ std::make_unique<DocHitInfoIteratorPropertyInDocument>(
+ std::move(meta_hit_iterator));
+
+ features_.insert(kHasPropertyFunctionFeature);
+
+ return PendingValue(std::move(property_in_document_iterator));
+}
+
libtextclassifier3::StatusOr<int64_t> QueryVisitor::PopPendingIntValue() {
if (pending_values_.empty()) {
return absl_ports::InvalidArgumentError("Unable to retrieve int value.");
@@ -647,7 +684,7 @@ libtextclassifier3::Status QueryVisitor::ProcessHasOperator(
std::set<std::string> property_restricts = {std::move(text_value.term)};
pending_values_.push(
- PendingValue(std::make_unique<DocHitInfoIteratorSectionRestrict>(
+ PendingValue(DocHitInfoIteratorSectionRestrict::ApplyRestrictions(
std::move(delegate), &document_store_, &schema_store_,
std::move(property_restricts), current_time_ms_)));
return libtextclassifier3::Status::OK;
diff --git a/icing/query/advanced_query_parser/query-visitor.h b/icing/query/advanced_query_parser/query-visitor.h
index 38864f8..d090b3c 100644
--- a/icing/query/advanced_query_parser/query-visitor.h
+++ b/icing/query/advanced_query_parser/query-visitor.h
@@ -247,13 +247,23 @@ class QueryVisitor : public AbstractSyntaxTreeVisitor {
libtextclassifier3::StatusOr<PendingValue> SearchFunction(
std::vector<PendingValue>&& args);
- // Implementation of the propertyDefined(member) custom function.
+ // Implementation of the propertyDefined(property_path) custom function.
// Returns:
- // - a Pending Value holding a DocHitIterator to be implemented.
+ // - a Pending Value holding a DocHitIterator that returns hits for all
+ // documents whose schema types have defined the property specified by
+ // property_path.
// - any errors returned by Lexer::ExtractTokens
libtextclassifier3::StatusOr<PendingValue> PropertyDefinedFunction(
std::vector<PendingValue>&& args);
+ // Implementation of the hasProperty(property_path) custom function.
+ // Returns:
+ // - a Pending Value holding a DocHitIterator that returns hits for all
+ // documents that have the property specified by property_path.
+ // - any errors returned by Lexer::ExtractTokens
+ libtextclassifier3::StatusOr<PendingValue> HasPropertyFunction(
+ std::vector<PendingValue>&& args);
+
// Handles a NaryOperatorNode where the operator is HAS (':') and pushes an
// iterator with the proper section filter applied. If the current property
// restriction represented by pending_property_restricts and the first child
diff --git a/icing/query/advanced_query_parser/query-visitor_test.cc b/icing/query/advanced_query_parser/query-visitor_test.cc
index 59e924d..9455baa 100644
--- a/icing/query/advanced_query_parser/query-visitor_test.cc
+++ b/icing/query/advanced_query_parser/query-visitor_test.cc
@@ -17,17 +17,28 @@
#include <cstdint>
#include <limits>
#include <memory>
+#include <string>
#include <string_view>
+#include <unordered_map>
+#include <utility>
+#include <vector>
#include "icing/text_classifier/lib3/utils/base/status.h"
+#include "icing/text_classifier/lib3/utils/base/statusor.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "icing/absl_ports/str_cat.h"
#include "icing/document-builder.h"
+#include "icing/file/filesystem.h"
+#include "icing/file/portable-file-backed-proto-log.h"
+#include "icing/index/hit/hit.h"
#include "icing/index/index.h"
+#include "icing/index/iterator/doc-hit-info-iterator-filter.h"
#include "icing/index/iterator/doc-hit-info-iterator-test-util.h"
#include "icing/index/iterator/doc-hit-info-iterator.h"
#include "icing/index/numeric/dummy-numeric-index.h"
#include "icing/index/numeric/numeric-index.h"
+#include "icing/index/property-existence-indexing-handler.h"
#include "icing/jni/jni-cache.h"
#include "icing/legacy/index/icing-filesystem.h"
#include "icing/portable/platform.h"
@@ -35,7 +46,13 @@
#include "icing/query/advanced_query_parser/lexer.h"
#include "icing/query/advanced_query_parser/parser.h"
#include "icing/query/query-features.h"
+#include "icing/query/query-results.h"
#include "icing/schema-builder.h"
+#include "icing/schema/schema-store.h"
+#include "icing/schema/section.h"
+#include "icing/store/document-id.h"
+#include "icing/store/document-store.h"
+#include "icing/store/namespace-id.h"
#include "icing/testing/common-matchers.h"
#include "icing/testing/icu-data-file-helper.h"
#include "icing/testing/jni-test-helpers.h"
@@ -47,6 +64,8 @@
#include "icing/tokenization/tokenizer.h"
#include "icing/transform/normalizer-factory.h"
#include "icing/transform/normalizer.h"
+#include "icing/util/clock.h"
+#include "icing/util/status-macros.h"
#include "unicode/uloc.h"
namespace icing {
@@ -218,16 +237,16 @@ TEST_P(QueryVisitorTest, SimpleLessThan) {
// respectively.
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("price", kDocumentId0, kSectionId0);
- editor->BufferKey(0);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(0));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId1, kSectionId1);
- editor->BufferKey(1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId2, kSectionId2);
- editor->BufferKey(2);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(2));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("price < 2");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -261,16 +280,16 @@ TEST_P(QueryVisitorTest, SimpleLessThanEq) {
// respectively.
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("price", kDocumentId0, kSectionId0);
- editor->BufferKey(0);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(0));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId1, kSectionId1);
- editor->BufferKey(1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId2, kSectionId2);
- editor->BufferKey(2);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(2));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("price <= 1");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -304,16 +323,16 @@ TEST_P(QueryVisitorTest, SimpleEqual) {
// respectively.
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("price", kDocumentId0, kSectionId0);
- editor->BufferKey(0);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(0));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId1, kSectionId1);
- editor->BufferKey(1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId2, kSectionId2);
- editor->BufferKey(2);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(2));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("price == 2");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -347,16 +366,16 @@ TEST_P(QueryVisitorTest, SimpleGreaterThanEq) {
// respectively.
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("price", kDocumentId0, kSectionId0);
- editor->BufferKey(0);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(0));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId1, kSectionId1);
- editor->BufferKey(1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId2, kSectionId2);
- editor->BufferKey(2);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(2));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("price >= 1");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -390,16 +409,16 @@ TEST_P(QueryVisitorTest, SimpleGreaterThan) {
// respectively.
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("price", kDocumentId0, kSectionId0);
- editor->BufferKey(0);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(0));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId1, kSectionId1);
- editor->BufferKey(1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId2, kSectionId2);
- editor->BufferKey(2);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(2));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("price > 1");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -434,16 +453,16 @@ TEST_P(QueryVisitorTest, IntMinLessThanEqual) {
int64_t int_min = std::numeric_limits<int64_t>::min();
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("price", kDocumentId0, kSectionId0);
- editor->BufferKey(int_min);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(int_min));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId1, kSectionId1);
- editor->BufferKey(std::numeric_limits<int64_t>::max());
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(std::numeric_limits<int64_t>::max()));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId2, kSectionId2);
- editor->BufferKey(int_min + 1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(int_min + 1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("price <= " + std::to_string(int_min));
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -478,16 +497,16 @@ TEST_P(QueryVisitorTest, IntMaxGreaterThanEqual) {
int64_t int_max = std::numeric_limits<int64_t>::max();
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("price", kDocumentId0, kSectionId0);
- editor->BufferKey(std::numeric_limits<int64_t>::min());
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(std::numeric_limits<int64_t>::min()));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId1, kSectionId1);
- editor->BufferKey(int_max);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(int_max));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId2, kSectionId2);
- editor->BufferKey(int_max - 1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(int_max - 1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("price >= " + std::to_string(int_max));
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -521,18 +540,18 @@ TEST_P(QueryVisitorTest, NestedPropertyLessThan) {
// respectively.
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("subscription.price", kDocumentId0, kSectionId0);
- editor->BufferKey(0);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(0));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor =
numeric_index_->Edit("subscription.price", kDocumentId1, kSectionId1);
- editor->BufferKey(1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor =
numeric_index_->Edit("subscription.price", kDocumentId2, kSectionId2);
- editor->BufferKey(2);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(2));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("subscription.price < 2");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -594,18 +613,18 @@ TEST_P(QueryVisitorTest, LessThanTooManyOperandsInvalid) {
// respectively.
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("subscription.price", kDocumentId0, kSectionId0);
- editor->BufferKey(0);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(0));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor =
numeric_index_->Edit("subscription.price", kDocumentId1, kSectionId1);
- editor->BufferKey(1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor =
numeric_index_->Edit("subscription.price", kDocumentId2, kSectionId2);
- editor->BufferKey(2);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(2));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
// Create an invalid AST for the query '3 < subscription.price 25' where '<'
// has three operands
@@ -669,18 +688,18 @@ TEST_P(QueryVisitorTest, LessThanNonExistentPropertyNotFound) {
// respectively.
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("subscription.price", kDocumentId0, kSectionId0);
- editor->BufferKey(0);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(0));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor =
numeric_index_->Edit("subscription.price", kDocumentId1, kSectionId1);
- editor->BufferKey(1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor =
numeric_index_->Edit("subscription.price", kDocumentId2, kSectionId2);
- editor->BufferKey(2);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(2));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("time < 25");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -722,16 +741,16 @@ TEST_P(QueryVisitorTest, IntMinLessThanInvalid) {
int64_t int_min = std::numeric_limits<int64_t>::min();
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("price", kDocumentId0, kSectionId0);
- editor->BufferKey(int_min);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(int_min));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId1, kSectionId1);
- editor->BufferKey(std::numeric_limits<int64_t>::max());
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(std::numeric_limits<int64_t>::max()));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId2, kSectionId2);
- editor->BufferKey(int_min + 1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(int_min + 1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("price <" + std::to_string(int_min));
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -752,16 +771,16 @@ TEST_P(QueryVisitorTest, IntMaxGreaterThanInvalid) {
int64_t int_max = std::numeric_limits<int64_t>::max();
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("price", kDocumentId0, kSectionId0);
- editor->BufferKey(std::numeric_limits<int64_t>::min());
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(std::numeric_limits<int64_t>::min()));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId1, kSectionId1);
- editor->BufferKey(int_max);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(int_max));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
editor = numeric_index_->Edit("price", kDocumentId2, kSectionId2);
- editor->BufferKey(int_max - 1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(int_max - 1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
std::string query = CreateQuery("price >" + std::to_string(int_max));
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -807,34 +826,34 @@ TEST_P(QueryVisitorTest, NumericComparatorDoesntAffectLaterTerms) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
std::unique_ptr<NumericIndex<int64_t>::Editor> editor =
numeric_index_->Edit("price", kDocumentId0, kSectionId0);
- editor->BufferKey(-2);
- editor->BufferKey(-1);
- editor->BufferKey(1);
- editor->BufferKey(2);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(-2));
+ ICING_ASSERT_OK(editor->BufferKey(-1));
+ ICING_ASSERT_OK(editor->BufferKey(1));
+ ICING_ASSERT_OK(editor->BufferKey(2));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
Index::Editor term_editor = index_->Edit(
kDocumentId0, kSectionId1, TERM_MATCH_PREFIX, /*namespace_id=*/0);
- term_editor.BufferTerm("-2");
- term_editor.BufferTerm("-1");
- term_editor.BufferTerm("1");
- term_editor.BufferTerm("2");
- term_editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(term_editor.BufferTerm("-2"));
+ ICING_ASSERT_OK(term_editor.BufferTerm("-1"));
+ ICING_ASSERT_OK(term_editor.BufferTerm("1"));
+ ICING_ASSERT_OK(term_editor.BufferTerm("2"));
+ ICING_ASSERT_OK(term_editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = numeric_index_->Edit("price", kDocumentId1, kSectionId0);
- editor->BufferKey(-1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(-1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = numeric_index_->Edit("price", kDocumentId2, kSectionId0);
- editor->BufferKey(-1);
- std::move(*editor).IndexAllBufferedKeys();
+ ICING_ASSERT_OK(editor->BufferKey(-1));
+ ICING_ASSERT_OK(std::move(*editor).IndexAllBufferedKeys());
term_editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- term_editor.BufferTerm("2");
- term_editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(term_editor.BufferTerm("2"));
+ ICING_ASSERT_OK(term_editor.IndexAllBufferedTerms());
// Translating MINUS chars that are interpreted as NOTs, this query would be
// `price == -1 AND NOT 2`
@@ -872,18 +891,18 @@ TEST_P(QueryVisitorTest, SingleTermTermFrequencyEnabled) {
// "bar" respectively.
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("foo");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -924,18 +943,18 @@ TEST_P(QueryVisitorTest, SingleTermTermFrequencyDisabled) {
// "bar" respectively.
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("foo");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -975,18 +994,18 @@ TEST_P(QueryVisitorTest, SingleTermPrefix) {
// "bar" respectively.
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// An EXACT query for 'fo' won't match anything.
std::string query = CreateQuery("fo");
@@ -1071,21 +1090,21 @@ TEST_P(QueryVisitorTest, SegmentationWithPrefix) {
// ["foo", "ba"] and ["bar", "fo"] respectively.
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("ba");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("ba"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("ba");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("ba"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.BufferTerm("fo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.BufferTerm("fo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// An EXACT query for `ba?fo` will be lexed into a single TEXT token.
// The visitor will tokenize it into `ba` and `fo` (`?` is dropped because it
@@ -1138,18 +1157,18 @@ TEST_P(QueryVisitorTest, SingleVerbatimTerm) {
// "foo:bar(baz)" and "bar:baz(foo)" respectively.
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo:bar(baz)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo:bar(baz)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo:bar(baz)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo:bar(baz)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar:baz(foo)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar:baz(foo)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("\"foo:bar(baz)\"");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -1184,18 +1203,18 @@ TEST_P(QueryVisitorTest, SingleVerbatimTermPrefix) {
// "foo:bar(abc)" and "bar:baz(foo)" respectively.
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo:bar(baz)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo:bar(baz)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo:bar(abc)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo:bar(abc)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar:baz(foo)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar:baz(foo)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Query for `"foo:bar("*`. This should match docs 0 and 1.
std::string query = CreateQuery("\"foo:bar(\"*");
@@ -1236,18 +1255,18 @@ TEST_P(QueryVisitorTest, VerbatimTermEscapingQuote) {
// "foobar\" and "foobar"" respectively.
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_EXACT, /*namespace_id=*/0);
- editor.BufferTerm(R"(foobary)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobary)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_EXACT,
/*namespace_id=*/0);
- editor.BufferTerm(R"(foobar\)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobar\)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_EXACT,
/*namespace_id=*/0);
- editor.BufferTerm(R"(foobar")");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobar")"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// From the comment above, verbatim_term = `foobar"` and verbatim_query =
// `foobar\"`
@@ -1288,19 +1307,19 @@ TEST_P(QueryVisitorTest, VerbatimTermEscapingEscape) {
// "foobar\" and "foobar"" respectively.
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_EXACT, /*namespace_id=*/0);
- editor.BufferTerm(R"(foobary)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobary)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_EXACT,
/*namespace_id=*/0);
// From the comment above, verbatim_term = `foobar\`.
- editor.BufferTerm(R"(foobar\)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobar\)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_EXACT,
/*namespace_id=*/0);
- editor.BufferTerm(R"(foobar")");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobar")"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Issue a query for the verbatim token `foobar\`.
std::string query = CreateQuery(R"(("foobar\\"))");
@@ -1343,18 +1362,18 @@ TEST_P(QueryVisitorTest, VerbatimTermEscapingNonSpecialChar) {
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_EXACT, /*namespace_id=*/0);
// From the comment above, verbatim_term = `foobary`.
- editor.BufferTerm(R"(foobary)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobary)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_EXACT,
/*namespace_id=*/0);
- editor.BufferTerm(R"(foobar\)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobar\)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_EXACT,
/*namespace_id=*/0);
- editor.BufferTerm(R"(foobar\y)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobar\y)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Issue a query for the verbatim token `foobary`.
std::string query = CreateQuery(R"(("foobar\y"))");
@@ -1424,19 +1443,19 @@ TEST_P(QueryVisitorTest, VerbatimTermNewLine) {
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_EXACT, /*namespace_id=*/0);
// From the comment above, verbatim_term = `foobar` + '\n'.
- editor.BufferTerm("foobar\n");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foobar\n"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_EXACT,
/*namespace_id=*/0);
- editor.BufferTerm(R"(foobar\)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobar\)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_EXACT,
/*namespace_id=*/0);
// verbatim_term = `foobar\n`. This is distinct from the term added above.
- editor.BufferTerm(R"(foobar\n)");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foobar\n)"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Issue a query for the verbatim token `foobar` + '\n'.
std::string query = CreateQuery("\"foobar\n\"");
@@ -1498,20 +1517,20 @@ TEST_P(QueryVisitorTest, VerbatimTermEscapingComplex) {
// `foo\\\"bar\\nbaz\"` and `foo\\"bar\\nbaz"` respectively.
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_EXACT, /*namespace_id=*/0);
- editor.BufferTerm(R"(foo\"bar\nbaz")");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foo\"bar\nbaz")"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_EXACT,
/*namespace_id=*/0);
// Add the verbatim_term from doc 0 but with all of the escapes left in
- editor.BufferTerm(R"(foo\\\"bar\\nbaz\")");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foo\\\"bar\\nbaz\")"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_EXACT,
/*namespace_id=*/0);
// Add the verbatim_term from doc 0 but with the escapes for '\' chars left in
- editor.BufferTerm(R"(foo\\"bar\\nbaz")");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm(R"(foo\\"bar\\nbaz")"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Issue a query for the verbatim token `foo\"bar\nbaz"`.
std::string query = CreateQuery(R"(("foo\\\"bar\\nbaz\""))");
@@ -1556,22 +1575,22 @@ TEST_P(QueryVisitorTest, SingleMinusTerm) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("-foo");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -1610,22 +1629,22 @@ TEST_P(QueryVisitorTest, SingleNotTerm) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("NOT foo");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -1660,26 +1679,26 @@ TEST_P(QueryVisitorTest, NestedNotTerms) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("bar");
- editor.BufferTerm("baz");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.BufferTerm("baz"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("baz");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("baz"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.BufferTerm("baz");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.BufferTerm("baz"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Double negative could be rewritten as `(foo AND NOT bar) baz`
std::string query = CreateQuery("NOT (-foo OR bar) baz");
@@ -1718,26 +1737,26 @@ TEST_P(QueryVisitorTest, DeeplyNestedNotTerms) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("bar");
- editor.BufferTerm("baz");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.BufferTerm("baz"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("baz");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("baz"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.BufferTerm("baz");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.BufferTerm("baz"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Simplifying:
// NOT (-(NOT (foo -bar) baz) -bat) NOT bass
@@ -1776,19 +1795,19 @@ TEST_P(QueryVisitorTest, DeeplyNestedNotTerms) {
TEST_P(QueryVisitorTest, ImplicitAndTerms) {
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("foo bar");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -1819,19 +1838,19 @@ TEST_P(QueryVisitorTest, ImplicitAndTerms) {
TEST_P(QueryVisitorTest, ExplicitAndTerms) {
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("foo AND bar");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -1862,19 +1881,19 @@ TEST_P(QueryVisitorTest, ExplicitAndTerms) {
TEST_P(QueryVisitorTest, OrTerms) {
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("fo");
- editor.BufferTerm("ba");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("fo"));
+ ICING_ASSERT_OK(editor.BufferTerm("ba"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("foo OR bar");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -1905,20 +1924,20 @@ TEST_P(QueryVisitorTest, OrTerms) {
TEST_P(QueryVisitorTest, AndOrTermPrecedence) {
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("baz");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("baz"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Should be interpreted like `foo (bar OR baz)`
std::string query = CreateQuery("foo bar OR baz");
@@ -2012,24 +2031,24 @@ TEST_P(QueryVisitorTest, AndOrNotPrecedence) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("baz");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("baz"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Should be interpreted like `foo ((NOT bar) OR baz)`
std::string query = CreateQuery("foo NOT bar OR baz");
@@ -2100,22 +2119,22 @@ TEST_P(QueryVisitorTest, PropertyFilter) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, prop1_section_id,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, prop1_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, prop2_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("foo", /*property_restrict=*/"prop1");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -2176,22 +2195,22 @@ TEST_F(QueryVisitorTest, MultiPropertyFilter) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, prop1_section_id,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, prop2_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, prop3_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = R"(search("foo", createList("prop1", "prop2")))";
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -2275,22 +2294,22 @@ TEST_P(QueryVisitorTest, PropertyFilterNonNormalized) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, prop1_section_id,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, prop1_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, prop2_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("foo", /*property_restrict=*/"PROP1");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -2345,22 +2364,22 @@ TEST_P(QueryVisitorTest, PropertyFilterWithGrouping) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, prop1_section_id,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, prop1_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, prop2_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query =
CreateQuery("(foo OR bar)", /*property_restrict=*/"prop1");
@@ -2413,22 +2432,22 @@ TEST_P(QueryVisitorTest, ValidNestedPropertyFilter) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, prop1_section_id,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, prop1_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, prop2_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("(prop1:foo)", /*property_restrict=*/"prop1");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -2500,22 +2519,22 @@ TEST_P(QueryVisitorTest, InvalidNestedPropertyFilter) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, prop1_section_id,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, prop1_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, prop2_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("(prop2:foo)", /*property_restrict=*/"prop1");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -2583,22 +2602,22 @@ TEST_P(QueryVisitorTest, NotWithPropertyFilter) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, prop1_section_id,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, prop1_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, prop2_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Resulting queries:
// - kPlain: `-prop1:(foo OR bar)`
@@ -2667,30 +2686,43 @@ TEST_P(QueryVisitorTest, PropertyFilterWithNot) {
SectionId prop1_section_id = 0;
SectionId prop2_section_id = 1;
+ // Create documents as follows:
+ // Doc0:
+ // prop1: "bar"
+ // prop2: ""
+ // Doc1:
+ // prop1: "foo"
+ // prop2: ""
+ // Doc2:
+ // prop1: ""
+ // prop2: "foo"
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, prop1_section_id,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, prop1_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, prop2_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Resulting queries:
// - kPlain: `prop1:(-foo OR bar)`
// - kSearch: `search("-foo OR bar", createList("prop1"))`
+ //
+ // The query is equivalent to `-prop1:foo OR prop1:bar`, thus doc0 and doc2
+ // will be matched.
std::string query =
CreateQuery("(-foo OR bar)", /*property_restrict=*/"prop1");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -2712,11 +2744,14 @@ TEST_P(QueryVisitorTest, PropertyFilterWithNot) {
EXPECT_THAT(ExtractKeys(query_results.query_term_iterators),
UnorderedElementsAre("bar"));
EXPECT_THAT(GetDocumentIds(query_results.root_iterator.get()),
- ElementsAre(kDocumentId0));
+ ElementsAre(kDocumentId2, kDocumentId0));
// Resulting queries:
- // - kPlain: `prop1:(foo OR bar)`
- // - kSearch: `search("foo OR bar", createList("prop1"))`
+ // - kPlain: `prop1:(-foo OR bar)`
+ // - kSearch: `search("-foo OR bar", createList("prop1"))`
+ //
+ // The query is equivalent to `-prop1:foo OR prop1:bar`, thus doc0 and doc2
+ // will be matched.
query = CreateQuery("(NOT foo OR bar)", /*property_restrict=*/"prop1");
ICING_ASSERT_OK_AND_ASSIGN(root_node, ParseQueryHelper(query));
QueryVisitor query_visitor_two(
@@ -2735,7 +2770,7 @@ TEST_P(QueryVisitorTest, PropertyFilterWithNot) {
EXPECT_THAT(ExtractKeys(query_results.query_term_iterators),
UnorderedElementsAre("bar"));
EXPECT_THAT(GetDocumentIds(query_results.root_iterator.get()),
- ElementsAre(kDocumentId0));
+ ElementsAre(kDocumentId2, kDocumentId0));
}
TEST_P(QueryVisitorTest, SegmentationTest) {
@@ -2756,7 +2791,7 @@ TEST_P(QueryVisitorTest, SegmentationTest) {
.Build(),
/*ignore_errors_and_delete_documents=*/false,
/*allow_circular_schema_definitions=*/false));
-
+
// Section ids are assigned alphabetically.
SectionId prop1_section_id = 0;
SectionId prop2_section_id = 1;
@@ -2768,36 +2803,36 @@ TEST_P(QueryVisitorTest, SegmentationTest) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, prop1_section_id,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("上班");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("上班"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(kDocumentId0, prop2_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
if (IsCfStringTokenization()) {
- editor.BufferTerm("每");
- editor.BufferTerm("天");
+ ICING_ASSERT_OK(editor.BufferTerm("每"));
+ ICING_ASSERT_OK(editor.BufferTerm("天"));
} else {
- editor.BufferTerm("每天");
+ ICING_ASSERT_OK(editor.BufferTerm("每天"));
}
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, prop1_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("上班");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("上班"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, prop2_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
if (IsCfStringTokenization()) {
- editor.BufferTerm("每");
- editor.BufferTerm("天");
+ ICING_ASSERT_OK(editor.BufferTerm("每"));
+ ICING_ASSERT_OK(editor.BufferTerm("天"));
} else {
- editor.BufferTerm("每天");
+ ICING_ASSERT_OK(editor.BufferTerm("每天"));
}
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
ParseQueryHelper(query));
@@ -2862,55 +2897,55 @@ TEST_P(QueryVisitorTest, PropertyRestrictsPopCorrectly) {
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid0, document_store_->Put(doc));
Index::Editor editor =
index_->Edit(docid0, prop0_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val0");
- editor.BufferTerm("val1");
- editor.BufferTerm("val2");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val0"));
+ ICING_ASSERT_OK(editor.BufferTerm("val1"));
+ ICING_ASSERT_OK(editor.BufferTerm("val2"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// - Doc 1: Contains 'val0', 'val1', 'val2' in 'prop1'. Should match.
doc = DocumentBuilder(doc).SetUri("uri1").Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid1, document_store_->Put(doc));
editor = index_->Edit(docid1, prop1_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val0");
- editor.BufferTerm("val1");
- editor.BufferTerm("val2");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val0"));
+ ICING_ASSERT_OK(editor.BufferTerm("val1"));
+ ICING_ASSERT_OK(editor.BufferTerm("val2"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// - Doc 2: Contains 'val0', 'val1', 'val2' in 'prop2'. Shouldn't match.
doc = DocumentBuilder(doc).SetUri("uri2").Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid2, document_store_->Put(doc));
editor = index_->Edit(docid2, prop2_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val0");
- editor.BufferTerm("val1");
- editor.BufferTerm("val2");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val0"));
+ ICING_ASSERT_OK(editor.BufferTerm("val1"));
+ ICING_ASSERT_OK(editor.BufferTerm("val2"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// - Doc 3: Contains 'val0' in 'prop0', 'val1' in 'prop1' etc. Should match.
doc = DocumentBuilder(doc).SetUri("uri3").Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid3, document_store_->Put(doc));
editor = index_->Edit(docid3, prop0_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val0");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val0"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(docid3, prop1_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val1");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val1"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(docid3, prop2_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val2");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val2"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// - Doc 4: Contains 'val1' in 'prop0', 'val2' in 'prop1', 'val0' in 'prop2'.
// Shouldn't match.
doc = DocumentBuilder(doc).SetUri("uri4").Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid4, document_store_->Put(doc));
editor = index_->Edit(docid4, prop0_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val1");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val1"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(docid4, prop1_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val2");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val2"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(docid4, prop1_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val0");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val0"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Now issue a query with 'val1' restricted to 'prop1'. This should match only
// docs 1 and 3.
@@ -2977,55 +3012,55 @@ TEST_P(QueryVisitorTest, UnsatisfiablePropertyRestrictsPopCorrectly) {
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid0, document_store_->Put(doc));
Index::Editor editor =
index_->Edit(docid0, prop0_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val0");
- editor.BufferTerm("val1");
- editor.BufferTerm("val2");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val0"));
+ ICING_ASSERT_OK(editor.BufferTerm("val1"));
+ ICING_ASSERT_OK(editor.BufferTerm("val2"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// - Doc 1: Contains 'val0', 'val1', 'val2' in 'prop1'. Shouldn't match.
doc = DocumentBuilder(doc).SetUri("uri1").Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid1, document_store_->Put(doc));
editor = index_->Edit(docid1, prop1_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val0");
- editor.BufferTerm("val1");
- editor.BufferTerm("val2");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val0"));
+ ICING_ASSERT_OK(editor.BufferTerm("val1"));
+ ICING_ASSERT_OK(editor.BufferTerm("val2"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// - Doc 2: Contains 'val0', 'val1', 'val2' in 'prop2'. Should match.
doc = DocumentBuilder(doc).SetUri("uri2").Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid2, document_store_->Put(doc));
editor = index_->Edit(docid2, prop2_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val0");
- editor.BufferTerm("val1");
- editor.BufferTerm("val2");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val0"));
+ ICING_ASSERT_OK(editor.BufferTerm("val1"));
+ ICING_ASSERT_OK(editor.BufferTerm("val2"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// - Doc 3: Contains 'val0' in 'prop0', 'val1' in 'prop1' etc. Should match.
doc = DocumentBuilder(doc).SetUri("uri3").Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid3, document_store_->Put(doc));
editor = index_->Edit(docid3, prop0_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val0");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val0"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(docid3, prop1_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val1");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val1"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(docid3, prop2_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val2");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val2"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// - Doc 4: Contains 'val1' in 'prop0', 'val2' in 'prop1', 'val0' in 'prop2'.
// Shouldn't match.
doc = DocumentBuilder(doc).SetUri("uri4").Build();
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid4, document_store_->Put(doc));
editor = index_->Edit(docid4, prop0_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val1");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val1"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(docid4, prop1_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val2");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val2"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
editor = index_->Edit(docid4, prop1_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("val0");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("val0"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Now issue a query with 'val1' restricted to 'prop1'. This should match only
// docs 1 and 3.
@@ -3197,23 +3232,23 @@ TEST_F(QueryVisitorTest, SearchFunctionNestedFunctionCalls) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("type").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, prop1_section_id,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri1").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId1, prop1_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("type").Build()));
editor = index_->Edit(kDocumentId2, prop1_section_id, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// *If* nested function calls were allowed, then this would simplify as:
// `search("search(\"foo\") bar")` -> `search("foo bar")` -> `foo bar`
@@ -3335,57 +3370,57 @@ TEST_F(QueryVisitorTest, SearchFunctionNestedPropertyRestrictsNarrowing) {
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid0, document_store_->Put(doc));
Index::Editor editor =
index_->Edit(kDocumentId0, prop0_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid1,
document_store_->Put(DocumentBuilder(doc).SetUri("uri1").Build()));
editor = index_->Edit(docid1, prop1_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid2,
document_store_->Put(DocumentBuilder(doc).SetUri("uri2").Build()));
editor = index_->Edit(docid2, prop2_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid3,
document_store_->Put(DocumentBuilder(doc).SetUri("uri3").Build()));
editor = index_->Edit(docid3, prop3_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid4,
document_store_->Put(DocumentBuilder(doc).SetUri("uri4").Build()));
editor = index_->Edit(docid4, prop4_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid5,
document_store_->Put(DocumentBuilder(doc).SetUri("uri5").Build()));
editor = index_->Edit(docid5, prop5_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid6,
document_store_->Put(DocumentBuilder(doc).SetUri("uri6").Build()));
editor = index_->Edit(docid6, prop6_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid7,
document_store_->Put(DocumentBuilder(doc).SetUri("uri7").Build()));
editor = index_->Edit(docid7, prop7_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// *If* nested function calls were allowed, then this would simplify as:
// `search("search(\"foo\") bar")` -> `search("foo bar")` -> `foo bar`
@@ -3515,57 +3550,57 @@ TEST_F(QueryVisitorTest, SearchFunctionNestedPropertyRestrictsExpanding) {
ICING_ASSERT_OK_AND_ASSIGN(DocumentId docid0, document_store_->Put(doc));
Index::Editor editor =
index_->Edit(kDocumentId0, prop0_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid1,
document_store_->Put(DocumentBuilder(doc).SetUri("uri1").Build()));
editor = index_->Edit(docid1, prop1_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid2,
document_store_->Put(DocumentBuilder(doc).SetUri("uri2").Build()));
editor = index_->Edit(docid2, prop2_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid3,
document_store_->Put(DocumentBuilder(doc).SetUri("uri3").Build()));
editor = index_->Edit(docid3, prop3_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid4,
document_store_->Put(DocumentBuilder(doc).SetUri("uri4").Build()));
editor = index_->Edit(docid4, prop4_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid5,
document_store_->Put(DocumentBuilder(doc).SetUri("uri5").Build()));
editor = index_->Edit(docid5, prop5_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid6,
document_store_->Put(DocumentBuilder(doc).SetUri("uri6").Build()));
editor = index_->Edit(docid6, prop6_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
ICING_ASSERT_OK_AND_ASSIGN(
DocumentId docid7,
document_store_->Put(DocumentBuilder(doc).SetUri("uri7").Build()));
editor = index_->Edit(docid7, prop7_id, TERM_MATCH_PREFIX, ns_id);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// *If* nested function calls were allowed, then this would simplify as:
// `search("search(\"foo\") bar")` -> `search("foo bar")` -> `foo bar`
@@ -3726,8 +3761,8 @@ TEST_P(QueryVisitorTest, PropertyDefinedFunctionReturnsMatchingDocuments) {
DocumentBuilder().SetKey("ns", "uri0").SetSchema("typeWithUrl").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Document 1 has the term "foo" and its schema DOESN'T have the url property.
ICING_ASSERT_OK(document_store_->Put(DocumentBuilder()
@@ -3736,16 +3771,16 @@ TEST_P(QueryVisitorTest, PropertyDefinedFunctionReturnsMatchingDocuments) {
.Build()));
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Document 2 has the term "bar" and its schema has the url property.
ICING_ASSERT_OK(document_store_->Put(
DocumentBuilder().SetKey("ns", "uri2").SetSchema("typeWithUrl").Build()));
editor = index_->Edit(kDocumentId2, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("bar");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("foo propertyDefined(\"url\")");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -3786,8 +3821,8 @@ TEST_P(QueryVisitorTest,
DocumentBuilder().SetKey("ns", "uri0").SetSchema("typeWithUrl").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Document 1 has the term "foo" and its schema DOESN'T have the url property.
ICING_ASSERT_OK(document_store_->Put(DocumentBuilder()
@@ -3796,8 +3831,8 @@ TEST_P(QueryVisitorTest,
.Build()));
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Attempt to query a non-existent property.
std::string query = CreateQuery("propertyDefined(\"nonexistentproperty\")");
@@ -3838,8 +3873,8 @@ TEST_P(QueryVisitorTest,
DocumentBuilder().SetKey("ns", "uri0").SetSchema("typeWithUrl").Build()));
Index::Editor editor = index_->Edit(kDocumentId0, kSectionId1,
TERM_MATCH_PREFIX, /*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
// Document 1 has the term "foo" and its schema DOESN'T have the url property.
ICING_ASSERT_OK(document_store_->Put(DocumentBuilder()
@@ -3848,8 +3883,8 @@ TEST_P(QueryVisitorTest,
.Build()));
editor = index_->Edit(kDocumentId1, kSectionId1, TERM_MATCH_PREFIX,
/*namespace_id=*/0);
- editor.BufferTerm("foo");
- editor.IndexAllBufferedTerms();
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
std::string query = CreateQuery("foo AND NOT propertyDefined(\"url\")");
ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
@@ -3869,6 +3904,204 @@ TEST_P(QueryVisitorTest,
UnorderedElementsAre(kDocumentId1));
}
+TEST_F(QueryVisitorTest,
+ HasPropertyFunctionWithNoArgumentReturnsInvalidArgument) {
+ std::string query = "hasProperty()";
+ ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
+ ParseQueryHelper(query));
+ QueryVisitor query_visitor(
+ index_.get(), numeric_index_.get(), document_store_.get(),
+ schema_store_.get(), normalizer_.get(), tokenizer_.get(), query,
+ DocHitInfoIteratorFilter::Options(), TERM_MATCH_PREFIX,
+ /*needs_term_frequency_info=*/true, clock_.GetSystemTimeMilliseconds());
+ root_node->Accept(&query_visitor);
+ EXPECT_THAT(std::move(query_visitor).ConsumeResults(),
+ StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
+}
+
+TEST_F(QueryVisitorTest,
+ HasPropertyFunctionWithMoreThanOneStringArgumentReturnsInvalidArgument) {
+ std::string query = "hasProperty(\"foo\", \"bar\")";
+ ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
+ ParseQueryHelper(query));
+ QueryVisitor query_visitor(
+ index_.get(), numeric_index_.get(), document_store_.get(),
+ schema_store_.get(), normalizer_.get(), tokenizer_.get(), query,
+ DocHitInfoIteratorFilter::Options(), TERM_MATCH_PREFIX,
+ /*needs_term_frequency_info=*/true, clock_.GetSystemTimeMilliseconds());
+ root_node->Accept(&query_visitor);
+ EXPECT_THAT(std::move(query_visitor).ConsumeResults(),
+ StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
+}
+
+TEST_F(QueryVisitorTest,
+ HasPropertyFunctionWithTextArgumentReturnsInvalidArgument) {
+ // The argument type is TEXT, not STRING here.
+ std::string query = "hasProperty(foo)";
+ ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
+ ParseQueryHelper(query));
+ QueryVisitor query_visitor(
+ index_.get(), numeric_index_.get(), document_store_.get(),
+ schema_store_.get(), normalizer_.get(), tokenizer_.get(), query,
+ DocHitInfoIteratorFilter::Options(), TERM_MATCH_PREFIX,
+ /*needs_term_frequency_info=*/true, clock_.GetSystemTimeMilliseconds());
+ root_node->Accept(&query_visitor);
+ EXPECT_THAT(std::move(query_visitor).ConsumeResults(),
+ StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
+}
+
+TEST_F(QueryVisitorTest,
+ HasPropertyFunctionWithNonStringArgumentReturnsInvalidArgument) {
+ std::string query = "hasProperty(1 < 2)";
+ ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
+ ParseQueryHelper(query));
+ QueryVisitor query_visitor(
+ index_.get(), numeric_index_.get(), document_store_.get(),
+ schema_store_.get(), normalizer_.get(), tokenizer_.get(), query,
+ DocHitInfoIteratorFilter::Options(), TERM_MATCH_PREFIX,
+ /*needs_term_frequency_info=*/true, clock_.GetSystemTimeMilliseconds());
+ root_node->Accept(&query_visitor);
+ EXPECT_THAT(std::move(query_visitor).ConsumeResults(),
+ StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
+}
+
+TEST_P(QueryVisitorTest, HasPropertyFunctionReturnsMatchingDocuments) {
+ ICING_ASSERT_OK(schema_store_->SetSchema(
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType("Simple")
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("name")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("price")
+ .SetDataType(TYPE_INT64)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build(),
+ /*ignore_errors_and_delete_documents=*/false,
+ /*allow_circular_schema_definitions=*/false));
+
+ // Document 0 has the term "foo" and has the "price" property.
+ ICING_ASSERT_OK(document_store_->Put(
+ DocumentBuilder().SetKey("ns", "uri0").SetSchema("Simple").Build()));
+ Index::Editor editor = index_->Edit(kDocumentId0, kSectionId0,
+ TERM_MATCH_PREFIX, /*namespace_id=*/0);
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm(
+ absl_ports::StrCat(kPropertyExistenceTokenPrefix, "price").c_str()));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
+
+ // Document 1 has the term "foo" and doesn't have the "price" property.
+ ICING_ASSERT_OK(document_store_->Put(
+ DocumentBuilder().SetKey("ns", "uri1").SetSchema("Simple").Build()));
+ editor = index_->Edit(kDocumentId1, kSectionId0, TERM_MATCH_PREFIX,
+ /*namespace_id=*/0);
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
+
+ // Document 2 has the term "bar" and has the "price" property.
+ ICING_ASSERT_OK(document_store_->Put(
+ DocumentBuilder().SetKey("ns", "uri2").SetSchema("Simple").Build()));
+ editor = index_->Edit(kDocumentId2, kSectionId0, TERM_MATCH_PREFIX,
+ /*namespace_id=*/0);
+ ICING_ASSERT_OK(editor.BufferTerm("bar"));
+ ICING_ASSERT_OK(editor.BufferTerm(
+ absl_ports::StrCat(kPropertyExistenceTokenPrefix, "price").c_str()));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
+
+ // Test that `foo hasProperty("price")` matches document 0 only.
+ std::string query = CreateQuery("foo hasProperty(\"price\")");
+ ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
+ ParseQueryHelper(query));
+ QueryVisitor query_visitor1(
+ index_.get(), numeric_index_.get(), document_store_.get(),
+ schema_store_.get(), normalizer_.get(), tokenizer_.get(), query,
+ DocHitInfoIteratorFilter::Options(), TERM_MATCH_PREFIX,
+ /*needs_term_frequency_info=*/true, clock_.GetSystemTimeMilliseconds());
+ root_node->Accept(&query_visitor1);
+ ICING_ASSERT_OK_AND_ASSIGN(QueryResults query_results,
+ std::move(query_visitor1).ConsumeResults());
+ EXPECT_THAT(query_results.features_in_use,
+ UnorderedElementsAre(kHasPropertyFunctionFeature,
+ kListFilterQueryLanguageFeature));
+ EXPECT_THAT(GetDocumentIds(query_results.root_iterator.get()),
+ UnorderedElementsAre(kDocumentId0));
+
+ // Test that `bar OR NOT hasProperty("price")` matches document 1 and
+ // document 2.
+ query = CreateQuery("bar OR NOT hasProperty(\"price\")");
+ ICING_ASSERT_OK_AND_ASSIGN(root_node, ParseQueryHelper(query));
+ QueryVisitor query_visitor2(
+ index_.get(), numeric_index_.get(), document_store_.get(),
+ schema_store_.get(), normalizer_.get(), tokenizer_.get(), query,
+ DocHitInfoIteratorFilter::Options(), TERM_MATCH_PREFIX,
+ /*needs_term_frequency_info=*/true, clock_.GetSystemTimeMilliseconds());
+ root_node->Accept(&query_visitor2);
+ ICING_ASSERT_OK_AND_ASSIGN(query_results,
+ std::move(query_visitor2).ConsumeResults());
+ EXPECT_THAT(query_results.features_in_use,
+ UnorderedElementsAre(kHasPropertyFunctionFeature,
+ kListFilterQueryLanguageFeature));
+ EXPECT_THAT(GetDocumentIds(query_results.root_iterator.get()),
+ UnorderedElementsAre(kDocumentId1, kDocumentId2));
+}
+
+TEST_P(QueryVisitorTest,
+ HasPropertyFunctionReturnsNothingIfNoMatchingProperties) {
+ ICING_ASSERT_OK(schema_store_->SetSchema(
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType("Simple")
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("name")
+ .SetDataType(TYPE_STRING)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("price")
+ .SetDataType(TYPE_INT64)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build(),
+ /*ignore_errors_and_delete_documents=*/false,
+ /*allow_circular_schema_definitions=*/false));
+
+ // Document 0 has the term "foo" and has the "price" property.
+ ICING_ASSERT_OK(document_store_->Put(
+ DocumentBuilder().SetKey("ns", "uri0").SetSchema("Simple").Build()));
+ Index::Editor editor = index_->Edit(kDocumentId0, kSectionId0,
+ TERM_MATCH_PREFIX, /*namespace_id=*/0);
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.BufferTerm(
+ absl_ports::StrCat(kPropertyExistenceTokenPrefix, "price").c_str()));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
+
+ // Document 1 has the term "foo" and doesn't have the "price" property.
+ ICING_ASSERT_OK(document_store_->Put(
+ DocumentBuilder().SetKey("ns", "uri1").SetSchema("Simple").Build()));
+ editor = index_->Edit(kDocumentId1, kSectionId0, TERM_MATCH_PREFIX,
+ /*namespace_id=*/0);
+ ICING_ASSERT_OK(editor.BufferTerm("foo"));
+ ICING_ASSERT_OK(editor.IndexAllBufferedTerms());
+
+ // Attempt to query a non-existent property.
+ std::string query = CreateQuery("hasProperty(\"nonexistentproperty\")");
+ ICING_ASSERT_OK_AND_ASSIGN(std::unique_ptr<Node> root_node,
+ ParseQueryHelper(query));
+ QueryVisitor query_visitor(
+ index_.get(), numeric_index_.get(), document_store_.get(),
+ schema_store_.get(), normalizer_.get(), tokenizer_.get(), query,
+ DocHitInfoIteratorFilter::Options(), TERM_MATCH_PREFIX,
+ /*needs_term_frequency_info=*/true, clock_.GetSystemTimeMilliseconds());
+ root_node->Accept(&query_visitor);
+ ICING_ASSERT_OK_AND_ASSIGN(QueryResults query_results,
+ std::move(query_visitor).ConsumeResults());
+ EXPECT_THAT(query_results.features_in_use,
+ UnorderedElementsAre(kHasPropertyFunctionFeature,
+ kListFilterQueryLanguageFeature));
+
+ EXPECT_THAT(GetDocumentIds(query_results.root_iterator.get()), IsEmpty());
+}
+
INSTANTIATE_TEST_SUITE_P(QueryVisitorTest, QueryVisitorTest,
testing::Values(QueryType::kPlain,
QueryType::kSearch));
diff --git a/icing/query/query-features.h b/icing/query/query-features.h
index 158e13e..d829cd7 100644
--- a/icing/query/query-features.h
+++ b/icing/query/query-features.h
@@ -48,9 +48,13 @@ constexpr Feature kVerbatimSearchFeature =
constexpr Feature kListFilterQueryLanguageFeature =
"LIST_FILTER_QUERY_LANGUAGE"; // Features#LIST_FILTER_QUERY_LANGUAGE
+// This feature relates to the use of the "hasProperty(property_path)" function.
+constexpr Feature kHasPropertyFunctionFeature =
+ "HAS_PROPERTY_FUNCTION"; // Features#HAS_PROPERTY_FUNCTION
+
inline std::unordered_set<Feature> GetQueryFeaturesSet() {
return {kNumericSearchFeature, kVerbatimSearchFeature,
- kListFilterQueryLanguageFeature};
+ kListFilterQueryLanguageFeature, kHasPropertyFunctionFeature};
}
} // namespace lib
diff --git a/icing/query/query-processor.cc b/icing/query/query-processor.cc
index 3e43ad9..bbfbf3c 100644
--- a/icing/query/query-processor.cc
+++ b/icing/query/query-processor.cc
@@ -176,12 +176,11 @@ libtextclassifier3::StatusOr<QueryResults> QueryProcessor::ParseSearch(
results.root_iterator = std::make_unique<DocHitInfoIteratorFilter>(
std::move(results.root_iterator), &document_store_, &schema_store_,
options, current_time_ms);
- // TODO(b/294114230): Move this SectionRestrict filter from root level to
- // lower levels if that would improve performance.
if (!search_spec.type_property_filters().empty()) {
- results.root_iterator = std::make_unique<DocHitInfoIteratorSectionRestrict>(
- std::move(results.root_iterator), &document_store_, &schema_store_,
- search_spec, current_time_ms);
+ results.root_iterator =
+ DocHitInfoIteratorSectionRestrict::ApplyRestrictions(
+ std::move(results.root_iterator), &document_store_, &schema_store_,
+ search_spec, current_time_ms);
}
return results;
}
@@ -406,7 +405,7 @@ libtextclassifier3::StatusOr<QueryResults> QueryProcessor::ParseRawQuery(
// the section restrict
std::set<std::string> section_restricts;
section_restricts.insert(std::move(frames.top().section_restrict));
- result_iterator = std::make_unique<DocHitInfoIteratorSectionRestrict>(
+ result_iterator = DocHitInfoIteratorSectionRestrict::ApplyRestrictions(
std::move(result_iterator), &document_store_, &schema_store_,
std::move(section_restricts), current_time_ms);
diff --git a/icing/query/query-processor_test.cc b/icing/query/query-processor_test.cc
index e64de32..53e3035 100644
--- a/icing/query/query-processor_test.cc
+++ b/icing/query/query-processor_test.cc
@@ -17,6 +17,7 @@
#include <cstdint>
#include <memory>
#include <string>
+#include <vector>
#include "icing/text_classifier/lib3/utils/base/status.h"
#include "gmock/gmock.h"
@@ -36,6 +37,7 @@
#include "icing/proto/search.pb.h"
#include "icing/proto/term.pb.h"
#include "icing/query/query-features.h"
+#include "icing/query/query-results.h"
#include "icing/schema-builder.h"
#include "icing/schema/schema-store.h"
#include "icing/schema/section.h"
@@ -1099,7 +1101,7 @@ TEST_P(QueryProcessorTest, CombinedAndOrTerms) {
IsOk());
EXPECT_THAT(AddTokenToIndex(document_id1, section_id, term_match_type, "dog"),
IsOk());
- index_->Merge();
+ ICING_ASSERT_OK(index_->Merge());
// Document 2 has content "animal kitten cat"
EXPECT_THAT(
@@ -3177,6 +3179,147 @@ TEST_P(QueryProcessorTest, NumericFilterWithoutEnablingFeatureFails) {
StatusIs(libtextclassifier3::StatusCode::INVALID_ARGUMENT));
}
+TEST_P(QueryProcessorTest, GroupingInSectionRestriction) {
+ if (GetParam() !=
+ SearchSpecProto::SearchType::EXPERIMENTAL_ICING_ADVANCED_QUERY) {
+ GTEST_SKIP() << "Grouping in section restriction is only supported in "
+ "advanced query.";
+ }
+
+ // Create the schema and document store
+ SchemaProto schema =
+ SchemaBuilder()
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType("email")
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("prop1")
+ .SetDataTypeString(TERM_MATCH_EXACT,
+ TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+ .AddProperty(PropertyConfigBuilder()
+ .SetName("prop2")
+ .SetDataTypeString(TERM_MATCH_EXACT,
+ TOKENIZER_PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
+ .Build();
+ ASSERT_THAT(schema_store_->SetSchema(
+ schema, /*ignore_errors_and_delete_documents=*/false,
+ /*allow_circular_schema_definitions=*/false),
+ IsOk());
+
+ SectionId prop1_section_id = 0;
+ SectionId prop2_section_id = 1;
+ TermMatchType::Code term_match_type = TermMatchType::EXACT_ONLY;
+
+ // Create documents as follows:
+ // Doc0:
+ // prop1: "foo"
+ // prop2: "bar"
+ // Doc1:
+ // prop1: "bar"
+ // prop2: "foo"
+ // Doc2:
+ // prop1: "foo bar"
+ // prop2: ""
+ ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id0,
+ document_store_->Put(DocumentBuilder()
+ .SetKey("namespace", "0")
+ .SetSchema("email")
+ .Build()));
+ EXPECT_THAT(
+ AddTokenToIndex(document_id0, prop1_section_id, term_match_type, "foo"),
+ IsOk());
+ EXPECT_THAT(
+ AddTokenToIndex(document_id0, prop2_section_id, term_match_type, "bar"),
+ IsOk());
+
+ ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id1,
+ document_store_->Put(DocumentBuilder()
+ .SetKey("namespace", "1")
+ .SetSchema("email")
+ .Build()));
+ EXPECT_THAT(
+ AddTokenToIndex(document_id1, prop1_section_id, term_match_type, "bar"),
+ IsOk());
+ EXPECT_THAT(
+ AddTokenToIndex(document_id1, prop2_section_id, term_match_type, "foo"),
+ IsOk());
+
+ ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id2,
+ document_store_->Put(DocumentBuilder()
+ .SetKey("namespace", "2")
+ .SetSchema("email")
+ .Build()));
+ EXPECT_THAT(
+ AddTokenToIndex(document_id2, prop1_section_id, term_match_type, "foo"),
+ IsOk());
+ EXPECT_THAT(
+ AddTokenToIndex(document_id2, prop1_section_id, term_match_type, "bar"),
+ IsOk());
+
+ // prop1:(foo bar) <=> prop1:foo AND prop1:bar, which matches doc2.
+ SearchSpecProto search_spec;
+ search_spec.set_query("prop1:(foo bar)");
+ search_spec.set_term_match_type(term_match_type);
+ search_spec.set_search_type(GetParam());
+ search_spec.add_enabled_features(
+ std::string(kListFilterQueryLanguageFeature));
+ ICING_ASSERT_OK_AND_ASSIGN(
+ QueryResults results,
+ query_processor_->ParseSearch(search_spec,
+ ScoringSpecProto::RankingStrategy::NONE,
+ fake_clock_.GetSystemTimeMilliseconds()));
+ EXPECT_THAT(GetDocHitInfos(results.root_iterator.get()),
+ ElementsAre(EqualsDocHitInfo(
+ document_id2, std::vector<SectionId>{prop1_section_id})));
+
+ // prop2:(foo bar) <=> prop2:foo AND prop2:bar, which matches nothing.
+ search_spec.set_query("prop2:(foo bar)");
+ ICING_ASSERT_OK_AND_ASSIGN(
+ results, query_processor_->ParseSearch(
+ search_spec, ScoringSpecProto::RankingStrategy::NONE,
+ fake_clock_.GetSystemTimeMilliseconds()));
+ EXPECT_THAT(GetDocHitInfos(results.root_iterator.get()), IsEmpty());
+
+ // prop1:(foo -bar) <=> prop1:foo AND -prop1:bar, which matches doc0.
+ search_spec.set_query("prop1:(foo -bar)");
+ ICING_ASSERT_OK_AND_ASSIGN(
+ results, query_processor_->ParseSearch(
+ search_spec, ScoringSpecProto::RankingStrategy::NONE,
+ fake_clock_.GetSystemTimeMilliseconds()));
+ EXPECT_THAT(GetDocHitInfos(results.root_iterator.get()),
+ ElementsAre(EqualsDocHitInfo(
+ document_id0, std::vector<SectionId>{prop1_section_id})));
+
+ // prop2:(-foo OR bar) <=> -prop2:foo OR prop2:bar, which matches doc0 and
+ // doc2.
+ search_spec.set_query("prop2:(-foo OR bar)");
+ ICING_ASSERT_OK_AND_ASSIGN(
+ results, query_processor_->ParseSearch(
+ search_spec, ScoringSpecProto::RankingStrategy::NONE,
+ fake_clock_.GetSystemTimeMilliseconds()));
+ EXPECT_THAT(
+ GetDocHitInfos(results.root_iterator.get()),
+ ElementsAre(EqualsDocHitInfo(document_id2, std::vector<SectionId>{}),
+ EqualsDocHitInfo(document_id0,
+ std::vector<SectionId>{prop2_section_id})));
+
+ // prop1:((foo AND bar) OR (foo AND -baz))
+ // <=> ((prop1:foo AND prop1:bar) OR (prop1:foo AND -prop1:baz)), which
+ // matches doc0 and doc2.
+ search_spec.set_query("prop1:((foo AND bar) OR (foo AND -baz))");
+ ICING_ASSERT_OK_AND_ASSIGN(
+ results, query_processor_->ParseSearch(
+ search_spec, ScoringSpecProto::RankingStrategy::NONE,
+ fake_clock_.GetSystemTimeMilliseconds()));
+ EXPECT_THAT(
+ GetDocHitInfos(results.root_iterator.get()),
+ ElementsAre(EqualsDocHitInfo(document_id2,
+ std::vector<SectionId>{prop1_section_id}),
+ EqualsDocHitInfo(document_id0,
+ std::vector<SectionId>{prop1_section_id})));
+}
+
INSTANTIATE_TEST_SUITE_P(
QueryProcessorTest, QueryProcessorTest,
testing::Values(