From 1eef617a07605a01aa639db65d794840603627de Mon Sep 17 00:00:00 2001 From: Dronplane Date: Wed, 28 Aug 2019 18:38:02 +0300 Subject: [PATCH] Fixed issue #9795 Fixed NOT IN clause in ArangoSearch (#9836) * Fixed issue #9795 Fixed NOT IN clause in ArangoSearch * Update CHANGELOG --- CHANGELOG | 3 + arangod/IResearch/IResearchFilterFactory.cpp | 4 +- tests/IResearch/IResearchFilterIn-test.cpp | 124 +-- tests/IResearch/IResearchQueryIn-test.cpp | 455 +++++++--- .../IResearch/IResearchQueryInRange-test.cpp | 809 ++++++++++++------ .../aql/aql-view-arangosearch-cluster.inc | 137 ++- .../aql/aql-view-arangosearch-noncluster.js | 56 +- 7 files changed, 1101 insertions(+), 487 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 765771d6f5..2b2d1a0e6d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,9 @@ v3.5.1 (XXXX-XX-XX) ------------------- +* Fixed issue #9795: fix AQL `NOT IN` clause in SEARCH operations for ArangoSearch + views. + * Make minimum timeout for synchronous replication configurable via parameter (--cluster.synchronous-replication-timeout-minimum) and increase default value to prevent dropping followers unnecessarily. diff --git a/arangod/IResearch/IResearchFilterFactory.cpp b/arangod/IResearch/IResearchFilterFactory.cpp index 0cd7bfb493..7fac6d970f 100644 --- a/arangod/IResearch/IResearchFilterFactory.cpp +++ b/arangod/IResearch/IResearchFilterFactory.cpp @@ -793,7 +793,7 @@ arangodb::Result fromInArray(irs::boolean_filter* filter, QueryContext const& ct if (filter) { filter = arangodb::aql::NODE_TYPE_OPERATOR_BINARY_NIN == node.type ? &static_cast( - filter->add().filter()) + filter->add().filter()) : &static_cast(filter->add()); filter->boost(filterCtx.boost); } @@ -934,7 +934,7 @@ arangodb::Result fromIn(irs::boolean_filter* filter, QueryContext const& ctx, filter = arangodb::aql::NODE_TYPE_OPERATOR_BINARY_NIN == node.type ? &static_cast( - filter->add().filter()) + filter->add().filter()) : &static_cast(filter->add()); filter->boost(filterCtx.boost); diff --git a/tests/IResearch/IResearchFilterIn-test.cpp b/tests/IResearch/IResearchFilterIn-test.cpp index 77d37aa4cb..5cfa26f589 100644 --- a/tests/IResearch/IResearchFilterIn-test.cpp +++ b/tests/IResearch/IResearchFilterIn-test.cpp @@ -2563,7 +2563,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // simple attribute { irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add().field(mangleStringIdentity("a")).term("1"); root.add().field(mangleStringIdentity("a")).term("2"); root.add().field(mangleStringIdentity("a")).term("3"); @@ -2577,7 +2577,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // simple offset { irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add().field(mangleStringIdentity("[1]")).term("1"); root.add().field(mangleStringIdentity("[1]")).term("2"); root.add().field(mangleStringIdentity("[1]")).term("3"); @@ -2589,7 +2589,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // complex attribute name { irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add().field(mangleStringIdentity("a.b.c.e.f")).term("1"); root.add().field(mangleStringIdentity("a.b.c.e.f")).term("2"); root.add().field(mangleStringIdentity("a.b.c.e.f")).term("3"); @@ -2609,7 +2609,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // complex attribute name, offset { irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add() .field(mangleStringIdentity("a.b.c[323].e.f")) .term("1"); @@ -2637,7 +2637,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // complex attribute name, offset { irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.boost(1.5); root.add() .field(mangleStringIdentity("a.b.c[323].e.f")) @@ -2666,7 +2666,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // complex attribute name, offset, analyzer { irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add() .field(mangleString("a.b.c[323].e.f", "test_analyzer")) .term("1"); @@ -2694,7 +2694,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // complex attribute name, offset, analyzer, boost { irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.boost(2.5); root.add() .field(mangleString("a.b.c[323].e.f", "test_analyzer")) @@ -2723,7 +2723,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // heterogeneous array values { irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add() .field(mangleStringIdentity("quick.brown.fox")) .term("1"); @@ -2755,7 +2755,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // heterogeneous array values, analyzer { irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add() .field(mangleString("quick.brown.fox", "test_analyzer")) .term("1"); @@ -2783,7 +2783,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // heterogeneous array values, analyzer, boost { irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.boost(1.5); root.add() .field(mangleString("quick.brown.fox", "test_analyzer")) @@ -2829,7 +2829,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { arangodb::aql::AqlValueHintDouble{5.6}))); irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add() .field(mangleStringIdentity("a.b.c.e[4].f[5].g[3].g.a")) .term("1"); @@ -2915,7 +2915,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { ctx.vars.emplace("x", value); irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add().field(mangleStringIdentity("a.b.c.e.f")).term("1"); root.add().field(mangleNumeric("a.b.c.e.f")).term(term->value()); root.add().field(mangleStringIdentity("a.b.c.e.f")).term("3"); @@ -2945,7 +2945,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { ctx.vars.emplace("x", value); irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add() .field(mangleString("a.b.c.e.f", "test_analyzer")) .term("1"); @@ -2975,7 +2975,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { ctx.vars.emplace("x", value); irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.boost(3.5); root.add() .field(mangleString("a.b.c.e.f", "test_analyzer")) @@ -3010,7 +3010,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { ctx.vars.emplace(var.name, value); irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add().field(mangleStringIdentity("a.b.c.e.f")).term("1"); root.add().field(mangleNumeric("a.b.c.e.f")).term(term->value()); root.add().field(mangleStringIdentity("a.b.c.e.f")).term("3"); @@ -3039,7 +3039,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { ctx.vars.emplace(var.name, value); irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add() .field(mangleString("a.b.c.e.f", "test_analyzer")) .term("1"); @@ -3072,7 +3072,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { ctx.vars.emplace(var.name, value); irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.boost(1.5); root.add() .field(mangleString("a.b.c.e.f", "test_analyzer")) @@ -3172,12 +3172,12 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { auto& notNode = dynamic_cast(*actual.begin()); EXPECT_TRUE(irs::Not::type() == notNode.type()); - auto const* andNode = dynamic_cast(notNode.filter()); - EXPECT_TRUE(andNode); - EXPECT_TRUE(irs::And::type() == andNode->type()); - EXPECT_TRUE(3 == andNode->size()); + auto const* orNode = dynamic_cast(notNode.filter()); + EXPECT_TRUE(orNode); + EXPECT_TRUE(irs::Or::type() == orNode->type()); + EXPECT_TRUE(3 == orNode->size()); - auto begin = andNode->begin(); + auto begin = orNode->begin(); // 1st filter { @@ -3202,7 +3202,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { EXPECT_TRUE(expected == *begin); } - EXPECT_TRUE(andNode->end() == ++begin); + EXPECT_TRUE(orNode->end() == ++begin); } } } @@ -3282,12 +3282,12 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { auto& notNode = dynamic_cast(*actual.begin()); EXPECT_TRUE(irs::Not::type() == notNode.type()); - auto const* andNode = dynamic_cast(notNode.filter()); - EXPECT_TRUE(andNode); - EXPECT_TRUE(irs::And::type() == andNode->type()); - EXPECT_TRUE(3 == andNode->size()); + auto const* orNode = dynamic_cast(notNode.filter()); + EXPECT_TRUE(orNode); + EXPECT_TRUE(irs::Or::type() == orNode->type()); + EXPECT_TRUE(3 == orNode->size()); - auto begin = andNode->begin(); + auto begin = orNode->begin(); // 1st filter { @@ -3312,7 +3312,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { EXPECT_TRUE(expected == *begin); } - EXPECT_TRUE(andNode->end() == ++begin); + EXPECT_TRUE(orNode->end() == ++begin); } } } @@ -3392,12 +3392,12 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { auto& notNode = dynamic_cast(*actual.begin()); EXPECT_TRUE(irs::Not::type() == notNode.type()); - auto const* andNode = dynamic_cast(notNode.filter()); - EXPECT_TRUE(andNode); - EXPECT_TRUE(irs::And::type() == andNode->type()); - EXPECT_TRUE(3 == andNode->size()); + auto const* orNode = dynamic_cast(notNode.filter()); + EXPECT_TRUE(orNode); + EXPECT_TRUE(irs::Or::type() == orNode->type()); + EXPECT_TRUE(3 == orNode->size()); - auto begin = andNode->begin(); + auto begin = orNode->begin(); // 1st filter { @@ -3422,7 +3422,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { EXPECT_TRUE(expected == *begin); } - EXPECT_TRUE(andNode->end() == ++begin); + EXPECT_TRUE(orNode->end() == ++begin); } } } @@ -3502,13 +3502,13 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { auto& notNode = dynamic_cast(*actual.begin()); EXPECT_TRUE(irs::Not::type() == notNode.type()); - auto const* andNode = dynamic_cast(notNode.filter()); - EXPECT_TRUE(andNode); - EXPECT_TRUE(irs::And::type() == andNode->type()); - EXPECT_TRUE(3 == andNode->size()); - EXPECT_TRUE(1.5f == andNode->boost()); + auto const* orNode = dynamic_cast(notNode.filter()); + EXPECT_TRUE(orNode); + EXPECT_TRUE(irs::Or::type() == orNode->type()); + EXPECT_TRUE(3 == orNode->size()); + EXPECT_TRUE(1.5f == orNode->boost()); - auto begin = andNode->begin(); + auto begin = orNode->begin(); // 1st filter { @@ -3533,7 +3533,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { EXPECT_TRUE(expected == *begin); } - EXPECT_TRUE(andNode->end() == ++begin); + EXPECT_TRUE(orNode->end() == ++begin); } } } @@ -3613,12 +3613,12 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { auto& notNode = dynamic_cast(*actual.begin()); EXPECT_TRUE(irs::Not::type() == notNode.type()); - auto const* andNode = dynamic_cast(notNode.filter()); - EXPECT_TRUE(andNode); - EXPECT_TRUE(irs::And::type() == andNode->type()); - EXPECT_TRUE(3 == andNode->size()); + auto const* orNode = dynamic_cast(notNode.filter()); + EXPECT_TRUE(orNode); + EXPECT_TRUE(irs::Or::type() == orNode->type()); + EXPECT_TRUE(3 == orNode->size()); - auto begin = andNode->begin(); + auto begin = orNode->begin(); // 1st filter { @@ -3643,7 +3643,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { dynamic_cast(&*begin)); } - EXPECT_TRUE(andNode->end() == ++begin); + EXPECT_TRUE(orNode->end() == ++begin); } } } @@ -3721,11 +3721,11 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { EXPECT_TRUE(1 == actual.size()); auto& notNode = dynamic_cast(*actual.begin()); EXPECT_TRUE(irs::Not::type() == notNode.type()); - auto const* andNode = dynamic_cast(notNode.filter()); - EXPECT_TRUE(andNode); - EXPECT_TRUE(irs::And::type() == andNode->type()); - EXPECT_TRUE(3 == andNode->size()); - auto begin = andNode->begin(); + auto const* orNode = dynamic_cast(notNode.filter()); + EXPECT_TRUE(orNode); + EXPECT_TRUE(irs::Or::type() == orNode->type()); + EXPECT_TRUE(3 == orNode->size()); + auto begin = orNode->begin(); // 1st filter { EXPECT_TRUE(irs::empty() == *begin); } @@ -3741,7 +3741,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // 3rd filter { EXPECT_TRUE(irs::all() == *++begin); } - EXPECT_TRUE(andNode->end() == ++begin); + EXPECT_TRUE(orNode->end() == ++begin); } } } @@ -3820,12 +3820,12 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { auto& notNode = dynamic_cast(*actual.begin()); EXPECT_TRUE(irs::Not::type() == notNode.type()); - auto const* andNode = dynamic_cast(notNode.filter()); - EXPECT_TRUE(andNode); - EXPECT_TRUE(irs::And::type() == andNode->type()); - EXPECT_TRUE(3 == andNode->size()); + auto const* orNode = dynamic_cast(notNode.filter()); + EXPECT_TRUE(orNode); + EXPECT_TRUE(irs::Or::type() == orNode->type()); + EXPECT_TRUE(3 == orNode->size()); - auto begin = andNode->begin(); + auto begin = orNode->begin(); // 1st filter { EXPECT_TRUE(irs::empty() == *begin); } @@ -3845,7 +3845,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { // 3rd filter { EXPECT_TRUE(irs::all() == *++begin); } - EXPECT_TRUE(andNode->end() == ++begin); + EXPECT_TRUE(orNode->end() == ++begin); } } } @@ -3868,7 +3868,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { auto& term = stream.attributes().get(); irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.add().field(mangleStringIdentity("a.b.c.e.f")).term("1"); root.add() .field(mangleStringIdentity("a.b.c.e.f")) @@ -3902,7 +3902,7 @@ TEST_F(IResearchFilterInTest, BinaryNotIn) { auto& term = stream.attributes().get(); irs::Or expected; - auto& root = expected.add().filter(); + auto& root = expected.add().filter(); root.boost(2.5); root.add().field(mangleStringIdentity("a.b.c.e.f")).term("1"); root.add() diff --git a/tests/IResearch/IResearchQueryIn-test.cpp b/tests/IResearch/IResearchQueryIn-test.cpp index b40396c0c0..09ad32cfab 100644 --- a/tests/IResearch/IResearchQueryIn-test.cpp +++ b/tests/IResearch/IResearchQueryIn-test.cpp @@ -311,23 +311,43 @@ TEST_F(IResearchQueryInTest, test) { std::vector expected = { insertedDocs[1].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH d.value IN [ true ] SORT BM25(d) ASC, " - "TFIDF(d) DESC, d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d.value IN [ true ] SORT BM25(d) ASC, " + "TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true))); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d.value NOT IN [ true ] SORT BM25(d) ASC, " + "TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // test bool via [] @@ -335,23 +355,43 @@ TEST_F(IResearchQueryInTest, test) { std::vector expected = { insertedDocs[1].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH d['value'] IN [ true, false ] SORT BM25(d) " - "ASC, TFIDF(d) DESC, d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d['value'] IN [ true, false ] SORT BM25(d) " + "ASC, TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d['value'] NOT IN [ true, false ] SORT BM25(d) " + "ASC, TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // test numeric @@ -361,23 +401,43 @@ TEST_F(IResearchQueryInTest, test) { insertedDocs[11].slice(), insertedDocs[13].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH d.value IN [ 123, 1234 ] SORT BM25(d) ASC, " - "TFIDF(d) DESC, d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d.value IN [ 123, 1234 ] SORT BM25(d) ASC, " + "TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d.value NOT IN [ 123, 1234 ] SORT BM25(d) ASC, " + "TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // test numeric, limit 2 @@ -386,23 +446,45 @@ TEST_F(IResearchQueryInTest, test) { insertedDocs[8].slice(), insertedDocs[11].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH d.value IN [ 123, 1234 ] SORT BM25(d) ASC, " - "TFIDF(d) DESC, d.seq LIMIT 2 RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d.value IN [ 123, 1234 ] SORT BM25(d) ASC, " + "TFIDF(d) DESC, d.seq LIMIT 2 RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d.value NOT IN [ 123, 1234 ] SORT BM25(d) ASC, " + "TFIDF(d) DESC, d.seq LIMIT 2 RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + // this also must not be there (it is not in expected due to LIMIT clause) + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(insertedDocs[13].slice(), resolved, true)); + ++i; + } + EXPECT_EQ(i, 2); } - - EXPECT_TRUE((i == expected.size())); } // test numeric via [] @@ -412,23 +494,43 @@ TEST_F(IResearchQueryInTest, test) { insertedDocs[11].slice(), insertedDocs[13].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH d['value'] IN [ 123, 1234 ] SORT BM25(d) " - "ASC, TFIDF(d) DESC, d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d['value'] IN [ 123, 1234 ] SORT BM25(d) " + "ASC, TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d['value'] NOT IN [ 123, 1234 ] SORT BM25(d) " + "ASC, TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // test null @@ -436,23 +538,43 @@ TEST_F(IResearchQueryInTest, test) { std::vector expected = { insertedDocs[0].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH d.value IN [ null ] SORT BM25(d) ASC, " - "TFIDF(d) DESC, d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d.value IN [ null ] SORT BM25(d) ASC, " + "TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d.value NOT IN [ null ] SORT BM25(d) ASC, " + "TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // test null via [] @@ -460,23 +582,44 @@ TEST_F(IResearchQueryInTest, test) { std::vector expected = { insertedDocs[0].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH d['value'] IN [ null, null ] SORT BM25(d) " - "ASC, TFIDF(d) DESC, d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d['value'] IN [ null, null ] SORT BM25(d) " + "ASC, TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d['value'] NOT IN [ null, null ] SORT BM25(d) " + "ASC, TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // test object @@ -508,23 +651,44 @@ TEST_F(IResearchQueryInTest, test) { std::vector expected = { insertedDocs[2].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH d.value IN [ \"abc\", \"xyz\" ] SORT BM25(d) " - "ASC, TFIDF(d) DESC, d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d.value IN [ \"abc\", \"xyz\" ] SORT BM25(d) " + "ASC, TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d.value NOT IN [ \"abc\", \"xyz\" ] SORT BM25(d) " + "ASC, TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // test string via [] @@ -532,22 +696,43 @@ TEST_F(IResearchQueryInTest, test) { std::vector expected = { insertedDocs[2].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH d['value'] IN [ \"abc\", \"xyz\" ] SORT " - "BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d['value'] IN [ \"abc\", \"xyz\" ] SORT " + "BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH d['value'] NOT IN [ \"abc\", \"xyz\" ] SORT " + "BM25(d) ASC, TFIDF(d) DESC, d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } } diff --git a/tests/IResearch/IResearchQueryInRange-test.cpp b/tests/IResearch/IResearchQueryInRange-test.cpp index 5a495d9db2..0b94b2c13b 100644 --- a/tests/IResearch/IResearchQueryInRange-test.cpp +++ b/tests/IResearch/IResearchQueryInRange-test.cpp @@ -326,24 +326,44 @@ TEST_F(IResearchQueryInRangeTest, test) { std::vector expected = { insertedDocs[1].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.value, false, true, false, true) " - "SORT d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.value, false, true, false, true) " + "SORT d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.value, false, true, false, true)) " + "SORT d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.value >= null && d.value <= null @@ -351,47 +371,85 @@ TEST_F(IResearchQueryInRangeTest, test) { std::vector expected = { insertedDocs[0].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.value, null, null, true, true) " - "SORT d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.value, null, null, true, true) " + "SORT d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.value, null, null, true, true)) " + "SORT d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.value > null && d.value <= null { std::vector expected = {}; - auto result = arangodb::tests::executeQuery( + { + auto result = arangodb::tests::executeQuery( vocbase, "FOR d IN testView SEARCH IN_RANGE(d.value, null, null, false, true) " "SORT d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.value, null, null, false, true)) " + "SORT d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.name >= 'A' && d.name <= 'A' @@ -399,47 +457,85 @@ TEST_F(IResearchQueryInRangeTest, test) { std::vector expected = { insertedDocs[6].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.name, 'A', 'A', true, true) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.name, 'A', 'A', true, true) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.name, 'A', 'A', true, true)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.name >= 'B' && d.name <= 'A' { std::vector expected = {}; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.name, 'B', 'A', true, true) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.name, 'B', 'A', true, true) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.name, 'B', 'A', true, true)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.name >= 'A' && d.name <= 'E' @@ -449,24 +545,43 @@ TEST_F(IResearchQueryInRangeTest, test) { insertedDocs[8].slice(), insertedDocs[9].slice(), insertedDocs[10].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.name, 'A', 'E', true, true) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.name, 'A', 'E', true, true) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.name, 'A', 'E', true, true)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.name >= 'A' && d.name < 'E' @@ -477,24 +592,43 @@ TEST_F(IResearchQueryInRangeTest, test) { insertedDocs[8].slice(), insertedDocs[9].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.name, 'A', 'E', true, false) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.name, 'A', 'E', true, false) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.name, 'A', 'E', true, false)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.name > 'A' && d.name <= 'E' @@ -505,24 +639,43 @@ TEST_F(IResearchQueryInRangeTest, test) { insertedDocs[9].slice(), insertedDocs[10].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.name, 'A', 'E', false, true) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.name, 'A', 'E', false, true) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.name, 'A', 'E', false, true)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.name > 'A' && d.name < 'E' @@ -532,47 +685,85 @@ TEST_F(IResearchQueryInRangeTest, test) { insertedDocs[8].slice(), insertedDocs[9].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.name, 'A', 'E', false, false) " - "SORT d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.name, 'A', 'E', false, false) " + "SORT d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.name, 'A', 'E', false, false)) " + "SORT d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.seq >= 5 && d.seq <= -1 { std::vector expected = {}; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.seq, 5, -1, true, true) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.seq, 5, -1, true, true) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.seq, 5, -1, true, true)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.seq >= 1 && d.seq <= 5 @@ -582,24 +773,43 @@ TEST_F(IResearchQueryInRangeTest, test) { insertedDocs[9].slice(), insertedDocs[10].slice(), insertedDocs[11].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.seq, 1, 5, true, true) SORT d.seq " - "RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.seq, 1, 5, true, true) SORT d.seq " + "RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.seq, 1, 5, true, true)) SORT d.seq " + "RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.seq > -2 && d.seq <= 5 @@ -610,24 +820,43 @@ TEST_F(IResearchQueryInRangeTest, test) { insertedDocs[9].slice(), insertedDocs[10].slice(), insertedDocs[11].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.seq, -2, 5, false, true) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.seq, -2, 5, false, true) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.seq, -2, 5, false, true)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.seq > 1 && d.seq < 5 @@ -637,24 +866,43 @@ TEST_F(IResearchQueryInRangeTest, test) { insertedDocs[9].slice(), insertedDocs[10].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.seq, 1, 5, false, false) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.seq, 1, 5, false, false) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.seq, 1, 5, false, false)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.seq >= 1 && d.seq < 5 @@ -665,24 +913,43 @@ TEST_F(IResearchQueryInRangeTest, test) { insertedDocs[9].slice(), insertedDocs[10].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.seq, 1, 5, true, false) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.seq, 1, 5, true, false) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.seq, 1, 5, true, false)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.value > 3 && d.value < 4 @@ -690,24 +957,43 @@ TEST_F(IResearchQueryInRangeTest, test) { std::vector expected = { insertedDocs[3].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.value, 3, 4, false, false) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.value, 3, 4, false, false) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.value, 3, 4, false, false)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } // d.value > -4 && d.value < -3 @@ -715,23 +1001,42 @@ TEST_F(IResearchQueryInRangeTest, test) { std::vector expected = { insertedDocs[3].slice(), }; - auto result = arangodb::tests::executeQuery( - vocbase, - "FOR d IN testView SEARCH IN_RANGE(d.value, -4, -3, false, false) SORT " - "d.seq RETURN d"); - ASSERT_TRUE(result.result.ok()); - auto slice = result.data->slice(); - EXPECT_TRUE(slice.isArray()); - size_t i = 0; + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH IN_RANGE(d.value, -4, -3, false, false) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; - for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { - auto const resolved = itr.value().resolveExternals(); - - EXPECT_TRUE((i < expected.size())); - EXPECT_TRUE((0 == arangodb::basics::VelocyPackHelper::compare(expected[i++], - resolved, true))); + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + EXPECT_LT(i, expected.size()); + EXPECT_EQ(0, arangodb::basics::VelocyPackHelper::compare(expected[i++], + resolved, true)); + } + EXPECT_EQ(i, expected.size()); + } + //NOT + { + auto result = arangodb::tests::executeQuery( + vocbase, + "FOR d IN testView SEARCH NOT(IN_RANGE(d.value, -4, -3, false, false)) SORT " + "d.seq RETURN d"); + ASSERT_TRUE(result.result.ok()); + auto slice = result.data->slice(); + EXPECT_TRUE(slice.isArray()); + size_t i = 0; + for (arangodb::velocypack::ArrayIterator itr(slice); itr.valid(); ++itr) { + auto const resolved = itr.value().resolveExternals(); + for (const auto& u : expected) { + EXPECT_NE(0, arangodb::basics::VelocyPackHelper::compare(u, resolved, true)); + } + ++i; + } + EXPECT_EQ(i, (insertedDocs.size() - expected.size())); } - - EXPECT_TRUE((i == expected.size())); } } diff --git a/tests/js/common/aql/aql-view-arangosearch-cluster.inc b/tests/js/common/aql/aql-view-arangosearch-cluster.inc index e6809e08c0..ea63bc5c43 100644 --- a/tests/js/common/aql/aql-view-arangosearch-cluster.inc +++ b/tests/js/common/aql/aql-view-arangosearch-cluster.inc @@ -158,7 +158,7 @@ } }, - testViewCollectionOptions : function() { + testViewCollectionOptions : function() { var result = db._query("FOR doc IN CompoundView SEARCH doc.a == 'foo' OPTIONS { waitForSync: true, collections : [ 'UnitTestsCollection' ] } RETURN doc").toArray(); assertEqual(result.length, 10); @@ -255,7 +255,7 @@ }); }, - testAttributeEqualityFilter : function () { + testAttributeEqualityFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.a == 'foo' OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 10); @@ -264,7 +264,7 @@ }); }, - testMultipleAttributeEqualityFilter : function () { + testMultipleAttributeEqualityFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.a == 'foo' && doc.b == 'bar' OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 5); @@ -274,7 +274,7 @@ }); }, - testMultipleAttributeEqualityFilterSortAttribute : function () { + testMultipleAttributeEqualityFilterSortAttribute : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.a == 'foo' && doc.b == 'bar' OPTIONS { waitForSync: true } SORT doc.c RETURN doc").toArray(); assertEqual(result.length, 5); @@ -287,7 +287,7 @@ }); }, - testMultipleAttributeEqualityFilterSortAttributeDesc : function () { + testMultipleAttributeEqualityFilterSortAttributeDesc : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.a == 'foo' AND doc.b == 'bar' OPTIONS { waitForSync: true } SORT doc.c DESC RETURN doc").toArray(); assertEqual(result.length, 5); @@ -300,7 +300,7 @@ }); }, - testAttributeLessFilter : function () { + testAttributeLessFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c < 2 OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 8); @@ -309,7 +309,7 @@ }); }, - testAttributeLeqFilter : function () { + testAttributeLeqFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c <= 2 OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 12); @@ -318,7 +318,7 @@ }); }, - testAttributeGeqFilter : function () { + testAttributeGeqFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c >= 2 OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 12); @@ -327,7 +327,7 @@ }); }, - testAttributeGreaterFilter : function () { + testAttributeGreaterFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c > 2 OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 8); @@ -336,7 +336,7 @@ }); }, - testAttributeOpenIntervalFilter : function () { + testAttributeOpenIntervalFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c > 1 AND doc.c < 3 OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 4); @@ -345,7 +345,7 @@ }); }, - testAttributeClosedIntervalFilter : function () { + testAttributeClosedIntervalFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c >= 1 AND doc.c <= 3 OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 12); @@ -354,7 +354,7 @@ }); }, - testAttributeIntervalExclusionFilter : function () { + testAttributeIntervalExclusionFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c < 1 OR doc.c > 3 OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 8); @@ -363,7 +363,7 @@ }); }, - testAttributeNeqFilter : function () { + testAttributeNeqFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH doc.a != 'foo' OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 18); // include documents without attribute 'a' @@ -372,7 +372,7 @@ }); }, - testStartsWithFilter : function () { + testStartsWithFilter : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH STARTS_WITH(doc.a, 'fo') OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 10); @@ -381,7 +381,7 @@ }); }, - testStartsWithFilter2 : function () { + testStartsWithFilter2 : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH STARTS_WITH(doc.b, 'ba') OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 10); @@ -390,7 +390,7 @@ }); }, - testStartsWithFilterSort : function () { + testStartsWithFilterSort : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH STARTS_WITH(doc.b, 'ba') && doc.c == 0 OPTIONS { waitForSync: true } SORT doc.b RETURN doc").toArray(); assertEqual(result.length, 2); @@ -400,7 +400,7 @@ assertEqual(result[1].c, 0); }, - testPhraseFilter : function () { + testPhraseFilter : function () { var result0 = db._query("FOR doc IN UnitTestsView SEARCH PHRASE(doc.text, 'quick brown fox jumps', 'text_en') OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result0.length, 1); @@ -422,7 +422,7 @@ assertEqual(result3[0].name, 'full'); }, - testExistsFilter : function () { + testExistsFilter : function () { var expected = new Set(); expected.add("full"); expected.add("half"); @@ -438,7 +438,7 @@ assertEqual(expected.size, 0); }, - testExistsFilterByAnalyzer: function () { + testExistsFilterByAnalyzer: function () { var expected = new Set(); expected.add("full"); expected.add("half"); @@ -454,13 +454,13 @@ assertEqual(expected.size, 0); }, - testExistsFilterByIdentityAnalyzer: function () { + testExistsFilterByIdentityAnalyzer: function () { var result = db._query("FOR doc IN UnitTestsView SEARCH EXISTS(doc.text, 'analyzer') OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(0, result.length); }, - testExistsFilterByContextAnalyzer: function () { + testExistsFilterByContextAnalyzer: function () { var expected = new Set(); expected.add("full"); expected.add("half"); @@ -476,7 +476,7 @@ assertEqual(expected.size, 0); }, - testExistsFilterByString: function () { + testExistsFilterByString: function () { var expected = new Set(); expected.add("full"); expected.add("half"); @@ -492,13 +492,13 @@ assertEqual(expected.size, 0); }, - testExistsFilterByType : function () { + testExistsFilterByType : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH EXISTS(doc.text, 'type') OPTIONS { waitForSync: true } RETURN doc").toArray(); assertEqual(result.length, 0); }, - testExistsFilterByTypeNull : function () { + testExistsFilterByTypeNull : function () { var expected = new Set(); expected.add("null"); @@ -511,7 +511,7 @@ assertEqual(expected.size, 0); }, - testExistsFilterByTypeBool : function () { + testExistsFilterByTypeBool : function () { var expected = new Set(); expected.add("bool"); @@ -524,7 +524,7 @@ assertEqual(expected.size, 0); }, - testExistsFilterByTypeNumeric : function () { + testExistsFilterByTypeNumeric : function () { var expected = new Set(); expected.add("numeric"); @@ -537,7 +537,7 @@ assertEqual(expected.size, 0); }, - testViewInInnerLoop : function() { + testViewInInnerLoop : function() { var expected = new Set(); // FIXME is there a better way to compare objects in js? expected.add(JSON.stringify({ a: "foo", b: "bar", c: 0 })); expected.add(JSON.stringify({ a: "foo", b: "baz", c: 0 })); @@ -558,7 +558,7 @@ assertEqual(expected.size, 0); }, - testViewInInnerLoopMultipleFilters : function() { + testViewInInnerLoopMultipleFilters : function() { var expected = new Set(); // FIXME is there a better way to compare objects in js? expected.add(JSON.stringify({ a: "foo", b: "bar", c: 0 })); expected.add(JSON.stringify({ a: "foo", b: "baz", c: 0 })); @@ -577,7 +577,7 @@ assertEqual(expected.size, 0); }, - testViewInInnerLoopSortByAttribute : function() { + testViewInInnerLoopSortByAttribute : function() { var expected = []; expected.push({ a: "bar", b: "foo", c: 1 }); expected.push({ a: "baz", b: "foo", c: 1 }); @@ -601,7 +601,7 @@ }); }, - testJoinTwoViewsSortByAttribute : function() { + testJoinTwoViewsSortByAttribute : function() { var expected = []; expected.push({ a: "bar", b: "foo", c: 1 }); expected.push({ a: "baz", b: "foo", c: 1 }); @@ -630,7 +630,7 @@ }); }, - testWithKeywordForViewInGraph : function() { + testWithKeywordForViewInGraph : function() { var results = []; results[0] = db._query( @@ -660,7 +660,7 @@ }); }, - testViewInSubquery : function() { + testViewInSubquery : function() { var entitiesData = [ { "_key": "person1", @@ -834,7 +834,7 @@ links.drop(); }, - testAttributeInRangeOpenInterval : function () { + testAttributeInRangeOpenInterval : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH IN_RANGE(doc.c, 1, 3, false, false) OPTIONS { waitForSync : true } RETURN doc").toArray(); assertEqual(result.length, 4); @@ -843,7 +843,7 @@ }); }, - testAttributeInRangeClosedInterval : function () { + testAttributeInRangeClosedInterval : function () { var result = db._query("FOR doc IN UnitTestsView SEARCH IN_RANGE(doc.c, 1, 3, true, true) OPTIONS { waitForSync : true } RETURN doc").toArray(); assertEqual(result.length, 12); @@ -867,8 +867,75 @@ assertEqual(res.a, "foo"); assertTrue(res.score > 1 && res.score < 2); }); - } + }, + testAttributeNotInRangeOpenInterval : function () { + var result = db._query("FOR doc IN UnitTestsView SEARCH NOT(IN_RANGE(doc.c, 1, 3, false, false)) OPTIONS { waitForSync : true } RETURN doc").toArray(); + assertEqual(result.length, 24); + result.forEach(function(res) { + assertTrue(res.c === undefined || res.c <= 1 || res.c >= 3); + }); + }, + testAttributeNotInRangeClosedInterval : function () { + var result = db._query("FOR doc IN UnitTestsView SEARCH NOT(IN_RANGE(doc.c, 1, 3, true, true)) OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 16); + result.forEach(function(res) { + assertTrue(res.c === undefined || res.c < 1 || res.c > 3); + }); + }, + testAttributeInRange : function () { + var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c IN 1..3 OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 12); + result.forEach(function(res) { + assertTrue(res.c >= 1 || res.c <= 3); + }); + }, + testAttributeNotInRange : function () { + var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c NOT IN 1..3 OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 16); + result.forEach(function(res) { + assertTrue(res.c === undefined || res.c < 1 || res.c > 3); + }); + }, + testAttributeInArray : function () { + var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c IN [ 1, 3 ] OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 8); + result.forEach(function(res) { + assertTrue(res.c === 1 || res.c === 3); + }); + }, + testAttributeNotInArray : function () { + var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c NOT IN [ 1, 3 ] OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 20); + result.forEach(function(res) { + assertTrue(res.c === undefined || res.c !== 1 && res.c !== 3); + }); + }, + testAttributeInExpression : function () { + var result = db._query("FOR c IN [[[1, 3]]] FOR doc IN UnitTestsView SEARCH 1 IN FLATTEN(c) OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, db.UnitTestsCollection.toArray().length); + }, + testAttributeNotInExpression: function () { + var result = db._query("FOR c IN [[[1, 3]]] FOR doc IN UnitTestsView SEARCH 1 NOT IN FLATTEN(c) OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 0); + }, + testAttributeInExpressionNonDet : function () { + var result = db._query("FOR c IN [[[1, 3]]] FOR doc IN UnitTestsView SEARCH 1 IN NOOPT(FLATTEN(c)) OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, db.UnitTestsCollection.toArray().length); + }, + testAttributeNotInExpressionNonDet: function () { + var result = db._query("FOR c IN [[[1, 3]]] FOR doc IN UnitTestsView SEARCH 1 NOT IN NOOPT(FLATTEN(c)) OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 0); + } }; } }()); diff --git a/tests/js/common/aql/aql-view-arangosearch-noncluster.js b/tests/js/common/aql/aql-view-arangosearch-noncluster.js index 93b421f7d7..2e929bef97 100644 --- a/tests/js/common/aql/aql-view-arangosearch-noncluster.js +++ b/tests/js/common/aql/aql-view-arangosearch-noncluster.js @@ -672,7 +672,7 @@ function iResearchAqlTestSuite () { var result = db._query("LET outer = (FOR out1 IN UnitTestsCollection FILTER out1.a == 'foo' && out1.c == 0 RETURN out1) FOR a IN outer FOR d IN UnitTestsView SEARCH d.a == a.a && d.c == a.c && d.b == a.b OPTIONS {waitForSync: true} SORT d.b ASC RETURN d").toArray(); - assertEqual(result.length, expected.length); + assertEqual(result.length, expected.length); var i = 0; result.forEach(function(res) { var doc = expected[i++]; @@ -905,6 +905,60 @@ function iResearchAqlTestSuite () { assertEqual(res.a, "foo"); assertTrue(res.score > 1 && res.score < 2); }); + }, + testAttributeInRange : function () { + var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c IN 1..3 OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 12); + result.forEach(function(res) { + assertTrue(res.c >= 1 || res.c <= 3); + }); + }, + testAttributeNotInRange : function () { + var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c NOT IN 1..3 OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 16); + result.forEach(function(res) { + assertTrue(res.c === undefined || res.c < 1 || res.c > 3); + }); + }, + testAttributeInArray : function () { + var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c IN [ 1, 3 ] OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 8); + result.forEach(function(res) { + assertTrue(res.c === 1 || res.c === 3); + }); + }, + testAttributeNotInArray : function () { + var result = db._query("FOR doc IN UnitTestsView SEARCH doc.c NOT IN [ 1, 3 ] OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 20); + result.forEach(function(res) { + assertTrue(res.c === undefined || res.c !== 1 && res.c !== 3); + }); + }, + testAttributeInExpression : function () { + var result = db._query("FOR c IN [[[1, 3]]] FOR doc IN UnitTestsView SEARCH 1 IN FLATTEN(c) OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, db.UnitTestsCollection.toArray().length); + + }, + testAttributeNotInExpression: function () { + var result = db._query("FOR c IN [[[1, 3]]] FOR doc IN UnitTestsView SEARCH 1 NOT IN FLATTEN(c) OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 0); + }, + testAttributeInExpressionNonDet : function () { + var result = db._query("FOR c IN [[[1, 3]]] FOR doc IN UnitTestsView SEARCH 1 IN NOOPT(FLATTEN(c)) OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, db.UnitTestsCollection.toArray().length); + + }, + testAttributeNotInExpressionNonDet: function () { + var result = db._query("FOR c IN [[[1, 3]]] FOR doc IN UnitTestsView SEARCH 1 NOT IN NOOPT(FLATTEN(c)) OPTIONS { waitForSync : true } RETURN doc").toArray(); + + assertEqual(result.length, 0); } };