1
0
Fork 0

Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel

This commit is contained in:
Michael Hackstein 2013-11-04 23:01:36 +01:00
commit ed46b28f7c
5 changed files with 197 additions and 0 deletions

View File

@ -1,6 +1,8 @@
v1.5.x (XXXX-XX-XX)
-------------------
* added AQL functions `NTH` and `POSITION`
* added signal handler for arangosh to save last command in more cases
* added extra prompt placeholders for arangosh:

View File

@ -1103,6 +1103,16 @@ AQL supports the following functions to operate on list values:
- @FN{LAST(@FA{list})}: returns the last element in @FA{list} or `null` if the
list is empty.
- @FN{NTH(@FA{list}, @FA{position})}: returns the list element at position @FA{position}.
Positions start at 0. If @FA{position} is negative or beyond the upper bound of the list
specified by @FA{list}, then `null` will be returned.
- @FN{POSITION(@FA{list}, @FA{search}, @FA{return-index})}: returns the position of the
element @FA{search} in list @FA{list}. Positions start at 0. If the element is not
found, then `-1` is returned. If @FA{return-index} is `false`, then instead of the
position only `true` or `false` are returned, depending on whether the sought element
is contained in the list.
- @FN{UNIQUE(@FA{list})}: returns all unique elements in @FA{list}. To determine
uniqueness, the function will use the comparison order defined in @ref AqlTypeOrder.
Calling this function might return the unique elements in any order.

View File

@ -673,6 +673,8 @@ TRI_associative_pointer_t* TRI_CreateFunctionsAql (void) {
REGISTER_FUNCTION("REVERSE", "REVERSE", true, false, "ls", NULL);
REGISTER_FUNCTION("FIRST", "FIRST", true, false, "l", NULL);
REGISTER_FUNCTION("LAST", "LAST", true, false, "l", NULL);
REGISTER_FUNCTION("NTH", "NTH", true, false, "l,n", NULL);
REGISTER_FUNCTION("POSITION", "POSITION", true, false, "l,.|b", NULL);
// document functions
REGISTER_FUNCTION("HAS", "HAS", true, false, "az,s", NULL);

View File

@ -2482,6 +2482,44 @@ function LAST (value) {
return value[value.length - 1];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the position of an element in a list
////////////////////////////////////////////////////////////////////////////////
function POSITION (value, search, returnIndex) {
"use strict";
LIST(value);
returnIndex = returnIndex || false;
var i, n = value.length;
if (n > 0) {
for (i = 0; i < n; ++i) {
if (RELATIONAL_EQUAL(value[i], search)) {
return returnIndex ? i : true;
}
}
}
return returnIndex ? -1 : false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the nth element in a list, or null if the item does not exist
////////////////////////////////////////////////////////////////////////////////
function NTH (value, position) {
"use strict";
LIST(value);
if (position < 0 || position >= value.length) {
return null;
}
return value[position];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief reverse the elements in a list or in a string
////////////////////////////////////////////////////////////////////////////////
@ -4035,6 +4073,8 @@ exports.LIMIT = LIMIT;
exports.LENGTH = LENGTH;
exports.FIRST = FIRST;
exports.LAST = LAST;
exports.POSITION = POSITION;
exports.NTH = NTH;
exports.REVERSE = REVERSE;
exports.RANGE = RANGE;
exports.UNIQUE = UNIQUE;

View File

@ -306,6 +306,149 @@ function ahuacatlFunctionsTestSuite () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN LAST({ })");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test position function
////////////////////////////////////////////////////////////////////////////////
testPosition : function () {
var list = [ "foo", "bar", null, "baz", true, 42, [ "BORK" ], { code: "foo", name: "test" }, false, 0, "" ];
var data = [
[ "foo", 0 ],
[ "bar", 1 ],
[ null, 2 ],
[ "baz", 3 ],
[ true, 4 ],
[ 42, 5 ],
[ [ "BORK" ], 6 ],
[ { code: "foo", name: "test" }, 7 ],
[ false, 8 ],
[ 0, 9 ],
[ "", 10 ]
];
data.forEach(function (d) {
var search = d[0];
var expected = d[1];
// find if element is contained in list (should be true)
var actual = getQueryResults("RETURN POSITION(@list, @search, false)", { list: list, search: search });
assertTrue(actual[0]);
// find position of element in list
actual = getQueryResults("RETURN POSITION(@list, @search, true)", { list: list, search: search });
assertEqual(expected, actual[0]);
// look up the element using the position
actual = getQueryResults("RETURN NTH(@list, @position)", { list: list, position: actual[0] });
assertEqual(search, actual[0]);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test position function
////////////////////////////////////////////////////////////////////////////////
testPositionNotThere : function () {
var list = [ "foo", "bar", null, "baz", true, 42, [ "BORK" ], { code: "foo", name: "test" }, false, 0, "" ];
var data = [ "foot", "barz", 43, 1, -42, { code: "foo", name: "test", bar: "baz" }, " ", " foo", "FOO", "bazt", 0.1, [ ], [ "bork" ] ];
data.forEach(function (d) {
var actual = getQueryResults("RETURN POSITION(@list, @search, false)", { list: list, search: d });
assertFalse(actual[0]);
actual = getQueryResults("RETURN POSITION(@list, @search, true)", { list: list, search: d });
assertEqual(-1, actual[0]);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test position function
////////////////////////////////////////////////////////////////////////////////
testPositionInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN POSITION()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN POSITION([ ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN POSITION(null, 'foo')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN POSITION(true, 'foo')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN POSITION(4, 'foo')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN POSITION(\"yes\", 'foo')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN POSITION({ }, 'foo')");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test nth function
////////////////////////////////////////////////////////////////////////////////
testNthEmpty : function () {
var i;
for (i = -3; i <= 3; ++i) {
var actual = getQueryResults("RETURN NTH([ ], @pos)", { pos: i });
assertNull(actual[0]);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test nth function
////////////////////////////////////////////////////////////////////////////////
testNthNegative : function () {
var i;
for (i = -3; i <= 3; ++i) {
var actual = getQueryResults("RETURN NTH([ 1, 2, 3, 4 ], @pos)", { pos: i });
if (i < 0) {
assertNull(actual[0]);
}
else {
assertEqual(i + 1, actual[0]);
}
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test nth function
////////////////////////////////////////////////////////////////////////////////
testNthBounds : function () {
var i;
for (i = 0; i <= 10; ++i) {
var actual = getQueryResults("RETURN NTH([ 'a1', 'a2', 'a3', 'a4', 'a5' ], @pos)", { pos: i });
if (i < 5) {
assertEqual('a' + (i + 1), actual[0]);
}
else {
assertNull(actual[0]);
}
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test nth function
////////////////////////////////////////////////////////////////////////////////
testNthInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NTH()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NTH([ ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH(null, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH(true, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH(4, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH(\"yes\", 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH({ }, 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH([ ], null)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH([ ], false)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH([ ], true)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH([ ], '')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH([ ], '1234')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH([ ], [ ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH([ ], { \"foo\": true})");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN NTH([ ], { })");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test reverse function
////////////////////////////////////////////////////////////////////////////////