1
0
Fork 0

added `SORTED` and `SORTED_UNIQUE` AQL functions (#4157)

This commit is contained in:
Jan 2018-01-05 14:50:27 +01:00 committed by GitHub
parent 6cb79b164e
commit 7018d003cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 144 additions and 1 deletions

View File

@ -6,6 +6,12 @@ devel
* added C++ implementation for AQL function `SHA512()`
* add AQL functions `SORTED` and `SORTED_UNIQUE`
`SORTED` will return a sorted version of the input array using AQL's internal
comparison order
`SORTED_UNIQUE` will do the same, but additionally removes duplicates.
* Added C++ implementation for the AQL TRANSLATE function
* renamed arangoimp to arangoimport for consistency

View File

@ -331,6 +331,29 @@ SLICE( [ 1, 2, 3, 4, 5 ], 0, -2 ) // [ 1, 2, 3 ]
SLICE( [ 1, 2, 3, 4, 5 ], -3, 2 ) // [ 3, 4 ]
```
### SORTED()
`SORTED(anyArray) → newArray`
Sort all elements in *anyArray*. The function will use the default comparison
order for AQL value types.
- **anyArray** (array): array with elements of arbitrary type
- returns **newArray** (array): *anyArray*, with elements sorted
### SORTED_UNIQUE()
`SORTED_UNIQUE(anyArray) → newArray`
Sort all elements in *anyArray*. The function will use the default comparison
order for AQL value types. Additionally, the values in the result array will
be made unique.
- **anyArray** (array): array with elements of arbitrary type
- returns **newArray** (array): *anyArray*, with elements sorted and duplicates
removed
### UNION()
`UNION(array1, array2, ... arrayN) → newArray`

View File

@ -350,6 +350,8 @@ void AqlFunctionFeature::addListFunctions() {
&Functions::Unique});
add({"SORTED_UNIQUE", ".", true, false, true, true,
&Functions::SortedUnique});
add({"SORTED", ".", true, false, true, true,
&Functions::Sorted});
add({"SLICE", ".,.|.", true, false, true, true,
&Functions::Slice});
add({"REVERSE", ".", true, false, true,

View File

@ -2028,7 +2028,6 @@ AqlValue Functions::SortedUnique(arangodb::aql::Query* query,
if (!value.isArray()) {
// not an array
// this is an internal function - do NOT issue a warning here
return AqlValue(AqlValueHintNull());
}
@ -2052,6 +2051,43 @@ AqlValue Functions::SortedUnique(arangodb::aql::Query* query,
return AqlValue(builder.get());
}
/// @brief function SORTED
AqlValue Functions::Sorted(arangodb::aql::Query* query,
transaction::Methods* trx,
VPackFunctionParameters const& parameters) {
ValidateParameters(parameters, "SORTED", 1, 1);
AqlValue value = ExtractFunctionParameterValue(trx, parameters, 0);
if (!value.isArray()) {
// not an array
return AqlValue(AqlValueHintNull());
}
AqlValueMaterializer materializer(trx);
VPackSlice slice = materializer.slice(value, false);
arangodb::basics::VelocyPackHelper::VPackLess<true> less(trx->transactionContext()->getVPackOptions(), &slice, &slice);
std::map<VPackSlice, size_t, arangodb::basics::VelocyPackHelper::VPackLess<true>> values(less);
for (auto const& it : VPackArrayIterator(slice)) {
if (!it.isNone()) {
auto f = values.emplace(it, 1);
if (!f.second) {
++(*f.first).second;
}
}
}
transaction::BuilderLeaser builder(trx);
builder->openArray();
for (auto const& it : values) {
for (size_t i = 0; i < it.second; ++i) {
builder->add(it.first);
}
}
builder->close();
return AqlValue(builder.get());
}
/// @brief function UNION
AqlValue Functions::Union(arangodb::aql::Query* query,
transaction::Methods* trx,

View File

@ -208,6 +208,8 @@ struct Functions {
VPackFunctionParameters const&);
static AqlValue SortedUnique(arangodb::aql::Query*, transaction::Methods*,
VPackFunctionParameters const&);
static AqlValue Sorted(arangodb::aql::Query*, transaction::Methods*,
VPackFunctionParameters const&);
static AqlValue Union(arangodb::aql::Query*, transaction::Methods*,
VPackFunctionParameters const&);
static AqlValue UnionDistinct(arangodb::aql::Query*, transaction::Methods*,

View File

@ -3225,6 +3225,21 @@ function AQL_SORTED_UNIQUE (values) {
return unique;
}
// //////////////////////////////////////////////////////////////////////////////
// / @brief return a sorted list of elements
// //////////////////////////////////////////////////////////////////////////////
function AQL_SORTED (values) {
'use strict';
if (TYPEWEIGHT(values) !== TYPEWEIGHT_ARRAY) {
return null;
}
values.sort(RELATIONAL_CMP);
return values;
}
// //////////////////////////////////////////////////////////////////////////////
// / @brief create the union (all) of all arguments
// //////////////////////////////////////////////////////////////////////////////
@ -5687,6 +5702,7 @@ exports.AQL_REVERSE = AQL_REVERSE;
exports.AQL_RANGE = AQL_RANGE;
exports.AQL_UNIQUE = AQL_UNIQUE;
exports.AQL_SORTED_UNIQUE = AQL_SORTED_UNIQUE;
exports.AQL_SORTED = AQL_SORTED;
exports.AQL_UNION = AQL_UNION;
exports.AQL_UNION_DISTINCT = AQL_UNION_DISTINCT;
exports.AQL_CALL = AQL_CALL;

View File

@ -693,6 +693,64 @@ function ahuacatlFunctionsTestSuite () {
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN UNIQUE({ })");
},
testSorted : function () {
var tests = [
[ [ null, { b: 2 }, { a: 1 }, 1, "1", [], 2, "2", 3, "3", 0, false, -1, true, [2], [1] ], [ null, false, true, -1, 0, 1, 2, 3, "1", "2", "3", [], [1], [2], { b: 2 }, { a: 1 } ] ],
[ [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] ],
[ [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1 ], [ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] ],
[ [ 1, 10, 100, 1000, 99, 2, 7, 8, 13, 4, 242, 123 ], [ 1, 2, 4, 7, 8, 10, 13, 99, 100, 123, 242, 1000 ] ],
[ [ 13, 1000, 99, 7, 8, 1, 10, 4, 242, 100, 123, 2 ], [ 1, 2, 4, 7, 8, 10, 13, 99, 100, 123, 242, 1000 ] ],
[ [ "foo", "bar", "foo", "food", "baz", "bark", "foo", "sauron", "bar" ], [ "bar", "bar", "bark", "baz", "foo", "foo", "foo", "food", "sauron" ] ],
[ [ 1, 2, 1, 2, 3, 4, -1, 2, -1, -2, 0 ], [ -2, -1, -1, 0, 1, 1, 2, 2, 2, 3, 4 ] ],
[ [ true, true, false, null, false, true, null ], [ null, null, false, false, true, true, true ] ],
[ [ -3.5, 12.4777, 12.477777, 12.436, 12.46777, -12.4777, 10000, 10000.1, 9999.9999, 9999.999 ], [ -12.4777, -3.5, 12.436, 12.46777, 12.4777, 12.477777, 9999.999, 9999.9999, 10000, 10000.1 ] ],
];
tests.forEach(function(test) {
var actual = getQueryResults("RETURN NOOPT(V8(SORTED(" + JSON.stringify(test[0]) + ")))");
assertEqual([ test[1] ], actual);
actual = getQueryResults("RETURN V8(SORTED(" + JSON.stringify(test[0]) + "))");
assertEqual([ test[1] ], actual);
actual = getQueryResults("RETURN NOOPT(SORTED(" + JSON.stringify(test[0]) + "))");
assertEqual([ test[1] ], actual);
actual = getQueryResults("RETURN SORTED(" + JSON.stringify(test[0]) + ")");
assertEqual([ test[1] ], actual);
});
},
testSortedUnique : function () {
var tests = [
[ [ null, { b: 2 }, { a: 1 }, 1, "1", [], 2, "2", 3, "3", 0, false, -1, true, [2], [1] ], [ null, false, true, -1, 0, 1, 2, 3, "1", "2", "3", [], [1], [2], { b: 2 }, { a: 1 } ] ],
[ [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] ],
[ [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ], [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] ],
[ [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1 ], [ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] ],
[ [ 1, 10, 100, 1000, 99, 2, 7, 8, 13, 4, 242, 123 ], [ 1, 2, 4, 7, 8, 10, 13, 99, 100, 123, 242, 1000 ] ],
[ [ 1, 4, 10, 100, 99, 1000, 99, 2, 1, 7, 8, 13, 4, 10, 2, 242, 123, 1000 ], [ 1, 2, 4, 7, 8, 10, 13, 99, 100, 123, 242, 1000 ] ],
[ [ 13, 1000, 99, 7, 8, 1, 10, 4, 242, 100, 123, 2 ], [ 1, 2, 4, 7, 8, 10, 13, 99, 100, 123, 242, 1000 ] ],
[ [ "foo", "bar", "foo", "food", "baz", "bark", "foo", "sauron", "bar" ], [ "bar", "bark", "baz", "foo", "food", "sauron" ] ],
[ [ 1, 2, 1, 2, 3, 4, -1, 2, -1, -2, 0 ], [ -2, -1, 0, 1, 2, 3, 4 ] ],
[ [ true, true, false, null, false, true, null ], [ null, false, true ] ],
[ [ -3.5, 12.4777, 12.477777, 12.436, 12.46777, 1, 1.0, -12.4777, 10000, 10000.1, 9999.9999, 9999.999, 10000.0 ], [ -12.4777, -3.5, 1, 12.436, 12.46777, 12.4777, 12.477777, 9999.999, 9999.9999, 10000, 10000.1 ] ],
];
tests.forEach(function(test) {
var actual = getQueryResults("RETURN NOOPT(V8(SORTED_UNIQUE(" + JSON.stringify(test[0]) + ")))");
assertEqual([ test[1] ], actual);
actual = getQueryResults("RETURN V8(SORTED_UNIQUE(" + JSON.stringify(test[0]) + "))");
assertEqual([ test[1] ], actual);
actual = getQueryResults("RETURN NOOPT(SORTED_UNIQUE(" + JSON.stringify(test[0]) + "))");
assertEqual([ test[1] ], actual);
actual = getQueryResults("RETURN SORTED_UNIQUE(" + JSON.stringify(test[0]) + ")");
assertEqual([ test[1] ], actual);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test slice function
////////////////////////////////////////////////////////////////////////////////