From a7b51c39da3e42a1a1bb7ccf0b0e68e217705e26 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 8 Sep 2015 17:34:14 +0200 Subject: [PATCH] added tests --- Documentation/Books/Users/Aql/Operations.mdpp | 50 ++++++++++++++++--- arangod/Aql/AqlValue.cpp | 6 ++- js/server/tests/aql-distinct.js | 23 +++++++++ 3 files changed, 72 insertions(+), 7 deletions(-) diff --git a/Documentation/Books/Users/Aql/Operations.mdpp b/Documentation/Books/Users/Aql/Operations.mdpp index 3eca8ccfb3..9d3a489c21 100644 --- a/Documentation/Books/Users/Aql/Operations.mdpp +++ b/Documentation/Books/Users/Aql/Operations.mdpp @@ -100,17 +100,55 @@ If the *DISTINCT* is applied on an expression that itself is an array or a subqu the *DISTINCT* will not make the values in each array or subquery result unique, but instead ensure that the result contains only distinct arrays or subquery results. To make the result of an array or a subquery unique, simply apply the *DISTINCT* for the -array of the subquery: +array or the subquery. + +For example, the following query will apply *DISTINCT* on its subquery results, +but not inside the subquery: ``` -FOR variable-name IN expression - RETURN ( - FOR sub IN expression - RETURN DISTINCT sub +FOR what IN 1..2 + RETURN DISTINCT ( + FOR i IN [ 1, 2, 3, 4, 1, 3 ] + RETURN i ) ``` -The order of results is undefined for *RETURN DISTINCT*. +Here we'll have a *FOR* loop with two iterations that each execute a subquery. The +*DISTINCT* here is applied on the two subquery results. Both subqueries return the +same result value (that is [ 1, 2, 3, 4, 1, 3 ]), so after *DISTINCT* there will +only be one occurrence of the value [ 1, 2, 3, 4, 1, 3 ] left: + +``` +[ + [ 1, 2, 3, 4, 1, 3 ] +] +``` + +If the goal is to apply the *DISTINCT* inside the subquery, it needs to be moved +there: + +``` +FOR what IN 1..2 + LET sub = ( + FOR i IN [ 1, 2, 3, 4, 1, 3 ] + RETURN DISTINCT i + ) + RETURN sub +``` + +In the above case, the *DISTINCT* will make the subquery results unique, so that +each subquery will return a unique array of values ([ 1, 2, 3, 4 ]). As the subquery +is executed twice and there is no *DISTINCT* on the top-level, that array will be +returned twice: + +``` +[ + [ 1, 2, 3, 4 ], + [ 1, 2, 3, 4 ] +] +``` + +Note: the order of results is undefined for *RETURN DISTINCT*. Note: *RETURN DISTINCT* is not allowed on the top-level of a query if there is no *FOR* loop in front of it. diff --git a/arangod/Aql/AqlValue.cpp b/arangod/Aql/AqlValue.cpp index 25db7df841..f56059eadd 100644 --- a/arangod/Aql/AqlValue.cpp +++ b/arangod/Aql/AqlValue.cpp @@ -360,10 +360,13 @@ triagens::basics::Json AqlValue::at (triagens::arango::AqlTransaction* trx, for (auto it = _vector->begin(); it != _vector->end(); ++it) { auto current = (*it); size_t const n = current->size(); + if (offset + i < n) { auto vecCollection = current->getDocumentCollection(0); + return current->getValue(i - offset, 0).toJson(trx, vecCollection, true); } + offset += (*it)->size(); } break; // fall-through to exception @@ -806,8 +809,9 @@ uint64_t AqlValue::hash (triagens::arango::AqlTransaction* trx, auto current = (*it); size_t const n = current->size(); auto vecCollection = current->getDocumentCollection(0); + for (size_t i = 0; i < n; ++i) { - json.add(current->getValue(i, 0).toJson(trx, vecCollection, false)); + json.add(current->getValueReference(i, 0).toJson(trx, vecCollection, true)); } } diff --git a/js/server/tests/aql-distinct.js b/js/server/tests/aql-distinct.js index 80d4197e28..6f019b421c 100644 --- a/js/server/tests/aql-distinct.js +++ b/js/server/tests/aql-distinct.js @@ -202,6 +202,29 @@ function ahuacatlDistinct () { }); assertEqual([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], result); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief distinct usage +//////////////////////////////////////////////////////////////////////////////// + + testDistinctWithArrays1 : function () { + var result = AQL_EXECUTE("FOR i IN 1..2 RETURN DISTINCT (FOR j IN [ 1, 2, 3, 4, 1, 3 ] RETURN j)").json; + + assertEqual(1, result.length); + assertEqual([ 1, 2, 3, 4, 1, 3 ], result[0]); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief distinct usage +//////////////////////////////////////////////////////////////////////////////// + + testDistinctWithArrays2 : function () { + var result = AQL_EXECUTE("FOR i IN 1..2 RETURN (FOR j IN [ 1, 2, 3, 4, 1, 3 ] RETURN DISTINCT j)").json; + + assertEqual(2, result.length); + assertEqual([ 1, 2, 3, 4 ], result[0].sort(function (l, r) { return l - r; })); + assertEqual([ 1, 2, 3, 4 ], result[1].sort(function (l, r) { return l - r; })); } };