mirror of https://gitee.com/bigwinds/arangodb
added `SORTED` and `SORTED_UNIQUE` AQL functions (#4157)
This commit is contained in:
parent
6cb79b164e
commit
7018d003cc
|
@ -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
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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*,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue