1
0
Fork 0

Merge branch 'aql-functions' of https://github.com/triAGENS/ArangoDB into devel

This commit is contained in:
Jan Steemann 2014-11-20 14:49:02 +01:00
commit 5f453b80e5
15 changed files with 1485 additions and 4 deletions

View File

@ -1,6 +1,11 @@
v2.4.0 (XXXX-XX-XX)
-------------------
* added AQL list functions `PUSH`, `POP`, `UNSHIFT`, `SHIFT`, `REMOVE_VALUES`,
`REMOVE_VALUE`, `REMOVE_NTH` and `APPEND`
* added AQL functions `CALL` and `APPLY` to dynamically call other functions
v2.3.0 (2014-11-18)
-------------------

View File

@ -173,6 +173,85 @@ AQL supports the following functions to operate on list values:
Note: Duplicates will be removed.
- *APPEND(list, values, unique)*: Adds all elements from the list *values* to the list
specified by *list*. If *unique* is set to true, then only those *values* will be added
that are not already contained in *list*.
The modified list is returned. All values are added at the end of the list (right side).
/* [ 1, 2, 3, 5, 6, 9 ] */
APPEND([ 1, 2, 3 ], [ 5, 6, 9 ])
/* [ 1, 2, 3, 4, 5, 9 ] */
APPEND([ 1, 2, 3 ], [ 3, 4, 5, 2, 9 ], true)
- *PUSH(list, value, unique)*: Adds *value* to the list specified by *list*. If
*unique* is set to true, then *value* is not added if already present in the list.
The modified list is returned. The value is added at the end of the list (right side).
Note: non-unique elements will not be removed from the list if they were already present
before the call to `PUSH`. The *unique* flag will only control if the value will
be added again to the list if already present. To make a list unique, use the `UNIQUE`
function.
/* [ 1, 2, 3, 4 ] */
PUSH([ 1, 2, 3 ], 4)
/* [ 1, 2, 3 ] */
PUSH([ 1, 2, 3 ], 2, true)
- *UNSHIFT(list, value, unique)*: Adds *value* to the list specified by *list*. If
*unique* is set to true, then *value* is not added if already present in the list.
The modified list is returned. The value is added at the start of the list (left side).
Note: non-unique elements will not be removed from the list if they were already present
before the call to `UNSHIFT`. The *unique* flag will only control if the value will
be added again to the list if already present. To make a list unique, use the `UNIQUE`
function.
/* [ 4, 1, 2, 3 ] */
UNSHIFT([ 1, 2, 3 ], 4)
/* [ 1, 2, 3 ] */
UNSHIFT([ 1, 2, 3 ], 2, true)
- *POP(list)*: Removes the element at the end (right side) of *list*. The modified list
is returned. If the list is already empty or *null*, an empty list is returned.
/* [ 1, 2, 3 ] */
POP([ 1, 2, 3, 4 ])
- *SHIFT(list)*: Removes the element at the start (left side) of *list*. The modified list
is returned. If the list is already empty or *null*, an empty list is returned.
/* [ 2, 3, 4 ] */
SHIFT([ 1, 2, 3, 4 ])
- *REMOVE_VALUE(list, value, limit)*: Removes all occurrences of *value* in the list
specified by *list*. If the optional *limit* is specified, only *limit* occurrences
will be removed.
/* [ "b", "b", "c" ] */
REMOVE_VALUE([ "a", "b", "b", "a", "c" ], "a")
/* [ "b", "b", "a", "c" ] */
REMOVE_VALUE([ "a", "b", "b", "a", "c" ], "a", 1)
- *REMOVE_VALUES(list, values)*: Removes all occurrences of any of the values specified
in list *values* from the list specified by *list*.
/* [ "b", "c", "e", "g" ] */
REMOVE_VALUES([ "a", "b", "c", "d", "e", "f", "g" ], [ "a", "f", "d" ])
- *REMOVE_NTH(list, position)*: Removes the element at position *position* from the
list specified by *list*. Positions start at 0. Negative positions are supported,
with -1 being the last list element. If *position* is out of bounds, the list is
returned unmodified. Otherwise, the modified list is returned.
/* [ "a", "c", "d", "e" ] */
REMOVE_NTH([ "a", "b", "c", "d", "e" ], 1)
/* [ "a", "b", "c", "e" ] */
REMOVE_NTH([ "a", "b", "c", "d", "e" ], -2)
Apart from these functions, AQL also offers several language constructs (e.g.
*FOR*, *SORT*, *LIMIT*, *COLLECT*) to operate on lists.

View File

@ -66,3 +66,17 @@ function categories:
as in the index.
If no suitable skiplist index is found, an error will be raised and the query will be aborted.
- *CALL(function, arg1, ..., argn)*: Dynamically calls the function with name *function*
with the arguments specified. Both built-in and user-defined functions can be called.
Arguments are passed as seperate parameters to the called function.
/* "this" */
CALL('SUBSTRING', 'this is a test', 0, 4)
- *APPLY(function, arguments)*: Dynamically calls the function with name *function*
with the arguments specified. Both built-in and user-defined functions can be called.
Arguments are passed as seperate parameters to the called function.
/* "this is" */
APPLY('SUBSTRING', [ 'this is a test', 0, 7 ])

View File

@ -533,6 +533,7 @@ unittests-shell-server-ahuacatl:
SHELL_SERVER_AQL = @top_srcdir@/js/server/tests/aql-arithmetic.js \
@top_srcdir@/js/server/tests/aql-bind.js \
@top_srcdir@/js/server/tests/aql-call-apply.js \
@top_srcdir@/js/server/tests/aql-complex.js \
@top_srcdir@/js/server/tests/aql-cross.js \
@top_srcdir@/js/server/tests/aql-edges-noncluster.js \
@ -540,6 +541,7 @@ SHELL_SERVER_AQL = @top_srcdir@/js/server/tests/aql-arithmetic.js \
@top_srcdir@/js/server/tests/aql-explain-noncluster.js \
@top_srcdir@/js/server/tests/aql-functions.js \
@top_srcdir@/js/server/tests/aql-functions-date.js \
@top_srcdir@/js/server/tests/aql-functions-list.js \
@top_srcdir@/js/server/tests/aql-functions-misc.js \
@top_srcdir@/js/server/tests/aql-functions-numeric.js \
@top_srcdir@/js/server/tests/aql-functions-string.js \

View File

@ -155,6 +155,17 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
{ "LAST", Function("LAST", "AQL_LAST", "l", true, false, true) },
{ "NTH", Function("NTH", "AQL_NTH", "l,n", true, false, true) },
{ "POSITION", Function("POSITION", "AQL_POSITION", "l,.|b", true, false, true) },
{ "CALL", Function("CALL", "AQL_CALL", "s|.+", false, true, false) },
{ "APPLY", Function("APPLY", "AQL_APPLY", "s|l", false, true, false) },
{ "PUSH", Function("PUSH", "AQL_PUSH", "l,.|b", true, false, false) },
{ "APPEND", Function("APPEND", "AQL_APPEND", "l,lz|b", true, false, false) },
{ "POP", Function("POP", "AQL_POP", "l", true, false, false) },
{ "POP", Function("POP", "AQL_POP", "l", true, false, false) },
{ "SHIFT", Function("SHIFT", "AQL_SHIFT", "l", true, false, false) },
{ "UNSHIFT", Function("UNSHIFT", "AQL_UNSHIFT", "l,.|b", true, false, false) },
{ "REMOVE_VALUE", Function("REMOVE_VALUE", "AQL_REMOVE_VALUE", "l,.|n", true, false, false) },
{ "REMOVE_VALUES", Function("REMOVE_VALUES", "AQL_REMOVE_VALUES", "l,lz", true, false, false) },
{ "REMOVE_NTH", Function("REMOVE_NTH", "AQL_REMOVE_NTH", "l,n", true, false, false) },
// document functions
{ "HAS", Function("HAS", "AQL_HAS", "az,s", true, false, true) },

View File

@ -177,7 +177,7 @@ namespace triagens {
/// @brief maximum number of function arguments that can be used
////////////////////////////////////////////////////////////////////////////////
static size_t const MaxArguments = 1024;
static size_t const MaxArguments = 65536;
};

View File

@ -177,6 +177,7 @@
"ERROR_QUERY_COMPILE_TIME_OPTIONS" : { "code" : 1575, "message" : "query options must be readable at query compile time" },
"ERROR_QUERY_EXCEPTION_OPTIONS" : { "code" : 1576, "message" : "query options expected" },
"ERROR_QUERY_COLLECTION_USED_IN_EXPRESSION" : { "code" : 1577, "message" : "collection '%s' used as expression operand" },
"ERROR_QUERY_DISALLOWED_DYNAMIC_CALL" : { "code" : 1578, "message" : "disallowed dynamic call to '%s'" },
"ERROR_QUERY_FUNCTION_INVALID_NAME" : { "code" : 1580, "message" : "invalid user function name" },
"ERROR_QUERY_FUNCTION_INVALID_CODE" : { "code" : 1581, "message" : "invalid user function code" },
"ERROR_QUERY_FUNCTION_NOT_FOUND" : { "code" : 1582, "message" : "user function '%s()' not found" },

View File

@ -177,6 +177,7 @@
"ERROR_QUERY_COMPILE_TIME_OPTIONS" : { "code" : 1575, "message" : "query options must be readable at query compile time" },
"ERROR_QUERY_EXCEPTION_OPTIONS" : { "code" : 1576, "message" : "query options expected" },
"ERROR_QUERY_COLLECTION_USED_IN_EXPRESSION" : { "code" : 1577, "message" : "collection '%s' used as expression operand" },
"ERROR_QUERY_DISALLOWED_DYNAMIC_CALL" : { "code" : 1578, "message" : "disallowed dynamic call to '%s'" },
"ERROR_QUERY_FUNCTION_INVALID_NAME" : { "code" : 1580, "message" : "invalid user function name" },
"ERROR_QUERY_FUNCTION_INVALID_CODE" : { "code" : 1581, "message" : "invalid user function code" },
"ERROR_QUERY_FUNCTION_NOT_FOUND" : { "code" : 1582, "message" : "user function '%s()' not found" },

View File

@ -544,8 +544,7 @@ function FCALL_USER (name, parameters) {
if (UserFunctions[prefix].hasOwnProperty(name)) {
try {
var result = UserFunctions[prefix][name].func.apply(null, parameters);
return FIX_VALUE(result);
return FIX_VALUE(UserFunctions[prefix][name].func.apply(null, parameters));
}
catch (err) {
WARN(name, INTERNAL.errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, AQL_TO_STRING(err));
@ -556,6 +555,76 @@ function FCALL_USER (name, parameters) {
THROW(null, INTERNAL.errors.ERROR_QUERY_FUNCTION_NOT_FOUND, NORMALIZE_FNAME(name));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief dynamically call a function
////////////////////////////////////////////////////////////////////////////////
function FCALL_DYNAMIC (func, applyDirect, values, name, args) {
var toCall;
name = AQL_TO_STRING(name).toUpperCase();
if (name.indexOf('::') > 0) {
// user-defined function
var prefix = DB_PREFIX();
if (! UserFunctions.hasOwnProperty(prefix)) {
reloadUserFunctions();
}
if (! UserFunctions.hasOwnProperty(prefix) ||
! UserFunctions[prefix].hasOwnProperty(name)) {
THROW(func, INTERNAL.errors.ERROR_QUERY_FUNCTION_NOT_FOUND, NORMALIZE_FNAME(name));
}
toCall = UserFunctions[prefix][name].func;
}
else {
// built-in function
if (name === "CALL" || name === "APPLY") {
THROW(func, INTERNAL.errors.ERROR_QUERY_DISALLOWED_DYNAMIC_CALL, NORMALIZE_FNAME(name));
}
if (! exports.hasOwnProperty("AQL_" + name)) {
THROW(func, INTERNAL.errors.ERROR_QUERY_FUNCTION_NOT_FOUND, NORMALIZE_FNAME(name));
}
toCall = exports["AQL_" + name];
}
if (applyDirect) {
try {
return FIX_VALUE(toCall.apply(null, args));
}
catch (err) {
WARN(name, INTERNAL.errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR, AQL_TO_STRING(err));
return null;
}
}
var type = TYPEWEIGHT(values), result, i;
if (type === TYPEWEIGHT_DOCUMENT) {
result = { };
for (i in values) {
if (values.hasOwnProperty(i)) {
args[0] = values[i];
result[i] = FIX_VALUE(toCall.apply(null, args));
}
}
return result;
}
else if (type === TYPEWEIGHT_LIST) {
result = [ ];
for (i = 0; i < values.length; ++i) {
args[0] = values[i];
result[i] = FIX_VALUE(toCall.apply(null, args));
}
return result;
}
WARN(func, INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return null;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the numeric value or undefined if it is out of range
////////////////////////////////////////////////////////////////////////////////
@ -2525,6 +2594,323 @@ function AQL_UNION_DISTINCT () {
return result;
}
/*
////////////////////////////////////////////////////////////////////////////////
/// @brief call a function for each element in the input list
////////////////////////////////////////////////////////////////////////////////
function AQL_CALL (values, name) {
"use strict";
var args = [ null ], i;
for (i = 2; i < arguments.length; ++i) {
args.push(arguments[i]);
}
return FCALL_DYNAMIC("CALL", false, values, name, args);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief call a function for each element in the input list
////////////////////////////////////////////////////////////////////////////////
function AQL_APPLY (values, name, parameters) {
"use strict";
var args = [ null ], i;
if (Array.isArray(parameters)) {
args = args.concat(parameters);
}
return FCALL_DYNAMIC("APPLY", false, values, name, args);
}
*/
////////////////////////////////////////////////////////////////////////////////
/// @brief call a function for each element in the input list
////////////////////////////////////////////////////////////////////////////////
function AQL_CALL (name) {
"use strict";
var args = [ ], i;
for (i = 1; i < arguments.length; ++i) {
args.push(arguments[i]);
}
return FCALL_DYNAMIC("CALL", true, null, name, args);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief call a function for each element in the input list
////////////////////////////////////////////////////////////////////////////////
function AQL_APPLY (name, parameters) {
"use strict";
var args = [ ], i;
if (Array.isArray(parameters)) {
args = args.concat(parameters);
}
return FCALL_DYNAMIC("APPLY", true, null, name, args);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief removes elements from a list
////////////////////////////////////////////////////////////////////////////////
function AQL_REMOVE_VALUES (list, values) {
"use strict";
var type = TYPEWEIGHT(values);
if (type === TYPEWEIGHT_NULL) {
return list;
}
else if (type !== TYPEWEIGHT_LIST) {
WARN("REMOVE_VALUES", INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return null;
}
type = TYPEWEIGHT(list);
if (type === TYPEWEIGHT_NULL) {
return [ ];
}
else if (type === TYPEWEIGHT_LIST) {
var copy = [ ], i;
for (i = 0; i < list.length; ++i) {
if (RELATIONAL_IN(list[i], values)) {
continue;
}
copy.push(CLONE(list[i]));
}
return copy;
}
WARN("REMOVE_VALUES", INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return null;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief removes an element from a list
////////////////////////////////////////////////////////////////////////////////
function AQL_REMOVE_VALUE (list, value, limit) {
"use strict";
var type = TYPEWEIGHT(list);
if (type === TYPEWEIGHT_NULL) {
return [ ];
}
else if (type === TYPEWEIGHT_LIST) {
if (TYPEWEIGHT(limit) === TYPEWEIGHT_NULL) {
limit = -1;
}
var copy = [ ], i;
for (i = 0; i < list.length; ++i) {
if (limit === -1 && RELATIONAL_CMP(list[i], value) === 0) {
continue;
}
else if (limit > 0 && RELATIONAL_CMP(list[i], value) === 0) {
--limit;
continue;
}
copy.push(CLONE(list[i]));
}
return copy;
}
WARN("REMOVE_VALUE", INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return null;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief removes an element from a list
////////////////////////////////////////////////////////////////////////////////
function AQL_REMOVE_NTH (list, position) {
"use strict";
var type = TYPEWEIGHT(list);
if (type === TYPEWEIGHT_NULL) {
return [ ];
}
else if (type === TYPEWEIGHT_LIST) {
position = AQL_TO_NUMBER(position);
if (position >= list.length || position < - list.length) {
return list;
}
if (position === 0) {
return list.slice(1);
}
else if (position === - list.length) {
return list.slice(position + 1);
}
else if (position === list.length - 1) {
return list.slice(0, position);
}
else if (position < 0) {
return list.slice(0, list.length + position).concat(list.slice(list.length + position + 1));
}
return list.slice(0, position).concat(list.slice(position + 1));
}
WARN("REMOVE_NTH", INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return null;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief adds an element to a list
////////////////////////////////////////////////////////////////////////////////
function AQL_PUSH (list, value, unique) {
"use strict";
var type = TYPEWEIGHT(list);
if (type === TYPEWEIGHT_NULL) {
return [ value ];
}
else if (type === TYPEWEIGHT_LIST) {
if (AQL_TO_BOOL(unique)) {
if (RELATIONAL_IN(value, list)) {
return list;
}
}
var copy = CLONE(list);
copy.push(value);
return copy;
}
WARN("PUSH", INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return null;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief adds elements to a list
////////////////////////////////////////////////////////////////////////////////
function AQL_APPEND (list, values, unique) {
"use strict";
var type = TYPEWEIGHT(values);
if (type === TYPEWEIGHT_NULL) {
return list;
}
else if (type !== TYPEWEIGHT_LIST) {
WARN("APPEND", INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return null;
}
if (values.length === 0) {
return list;
}
unique = AQL_TO_BOOL(unique);
if (values.length > 1 && unique) {
// make values unique themselves
values = AQL_UNIQUE(values);
}
type = TYPEWEIGHT(list);
if (type === TYPEWEIGHT_NULL) {
return values;
}
else if (type === TYPEWEIGHT_LIST) {
var copy = CLONE(list);
if (unique) {
var i;
for (i = 0; i < values.length; ++i) {
if (RELATIONAL_IN(values[i], list)) {
continue;
}
copy.push(values[i]);
}
return copy;
}
return copy.concat(values);
}
WARN("APPEND", INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return null;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief pops an element from a list
////////////////////////////////////////////////////////////////////////////////
function AQL_POP (list) {
"use strict";
var type = TYPEWEIGHT(list);
if (type === TYPEWEIGHT_NULL) {
return null;
}
else if (type === TYPEWEIGHT_LIST) {
if (list.length === 0) {
return [ ];
}
var copy = CLONE(list);
copy.pop();
return copy;
}
WARN("POP", INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return null;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief insert an element into a list
////////////////////////////////////////////////////////////////////////////////
function AQL_UNSHIFT (list, value, unique) {
"use strict";
var type = TYPEWEIGHT(list);
if (type === TYPEWEIGHT_NULL) {
return [ value ];
}
else if (type === TYPEWEIGHT_LIST) {
if (unique) {
if (RELATIONAL_IN(value, list)) {
return list;
}
}
var copy = CLONE(list);
copy.unshift(value);
return copy;
}
WARN("UNSHIFT", INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief pops an element from a list
////////////////////////////////////////////////////////////////////////////////
function AQL_SHIFT (list) {
"use strict";
var type = TYPEWEIGHT(list);
if (type === TYPEWEIGHT_NULL) {
return null;
}
else if (type === TYPEWEIGHT_LIST) {
if (list.length === 0) {
return [ ];
}
var copy = CLONE(list);
copy.shift();
return copy;
}
WARN("SHIFT", INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return null;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extract a slice from a list
@ -7148,6 +7534,16 @@ exports.AQL_RANGE = AQL_RANGE;
exports.AQL_UNIQUE = AQL_UNIQUE;
exports.AQL_UNION = AQL_UNION;
exports.AQL_UNION_DISTINCT = AQL_UNION_DISTINCT;
exports.AQL_CALL = AQL_CALL;
exports.AQL_APPLY = AQL_APPLY;
exports.AQL_REMOVE_VALUE = AQL_REMOVE_VALUE;
exports.AQL_REMOVE_VALUES = AQL_REMOVE_VALUES;
exports.AQL_REMOVE_NTH = AQL_REMOVE_NTH;
exports.AQL_PUSH = AQL_PUSH;
exports.AQL_APPEND = AQL_APPEND;
exports.AQL_POP = AQL_POP;
exports.AQL_SHIFT = AQL_SHIFT;
exports.AQL_UNSHIFT = AQL_UNSHIFT;
exports.AQL_SLICE = AQL_SLICE;
exports.AQL_MINUS = AQL_MINUS;
exports.AQL_INTERSECTION = AQL_INTERSECTION;

View File

@ -0,0 +1,340 @@
/*jshint strict: false, maxlen: 500 */
/*global require, assertEqual */
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for query language, functions
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var internal = require("internal");
var errors = internal.errors;
var jsunity = require("jsunity");
var helper = require("org/arangodb/aql-helper");
var getQueryResults = helper.getQueryResults;
var assertQueryError = helper.assertQueryError;
var assertQueryWarningAndNull = helper.assertQueryWarningAndNull;
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function ahuacatlCallApplyTestSuite () {
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief test call function
////////////////////////////////////////////////////////////////////////////////
testCall : function () {
var data = [
[ "foo bar", [ "TRIM", " foo bar " ] ],
[ "foo bar", [ "TRIM", " foo bar ", "\r\n \t" ] ],
[ "..foo bar..", [ "TRIM", " ..foo bar.. " ] ],
[ "foo bar", [ "TRIM", " ..foo bar.. ", ". " ] ],
[ "foo", [ "LEFT", "foobarbaz", 3 ] ],
[ "fooba", [ "LEFT", "foobarbaz", 5 ] ],
[ "foob", [ "SUBSTRING", "foobarbaz", 0, 4 ] ],
[ "oob", [ "SUBSTRING", "foobarbaz", 1, 3 ] ],
[ "barbaz", [ "SUBSTRING", "foobarbaz", 3 ] ],
[ "FOOBARBAZ", [ "UPPER", "foobarbaz" ] ],
[ "foobarbaz", [ "lower", "FOOBARBAZ" ] ],
[ "abcfood", [ "concat", "a", "b", "c", "foo", "d" ] ],
[ 1, [ "flOoR", 1.6 ] ],
[ 17, [ "MIN", [ 23, 42, 17 ] ] ],
[ [ 1, 2, 3, 4, 7, 9, 10, 12 ], [ "UNION_DISTINCT", [ 1, 2, 3, 4 ], [ 9, 12 ], [ 2, 9, 7, 10 ] ] ],
[ { a: true, b: false, c: null }, [ "ZIP", [ "a", "b", "c" ], [ true, false, null ] ] ]
];
data.forEach(function (d) {
var actual = getQueryResults("RETURN CALL(" + d[1].map(function (v) { return JSON.stringify(v); }).join(", ") + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test call function
////////////////////////////////////////////////////////////////////////////////
testCallDynamic1 : function () {
var actual = getQueryResults("FOR func IN [ 'TRIM', 'LOWER', 'UPPER' ] RETURN CALL(func, ' foObAr ')");
assertEqual(actual, [ 'foObAr', ' foobar ', ' FOOBAR ' ]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test call function
////////////////////////////////////////////////////////////////////////////////
testCallDynamic2 : function () {
var actual = getQueryResults("FOR doc IN [ { value: ' foobar', func: 'TRIM' }, { value: 'FOOBAR', func: 'LOWER' }, { value: 'foobar', func: 'UPPER' } ] RETURN CALL(doc.func, doc.value)");
assertEqual(actual, [ 'foobar', 'foobar', 'FOOBAR' ]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test call function
////////////////////////////////////////////////////////////////////////////////
testCallNonExisting : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN CALL()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL('nono-existing', [ 'baz' ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL('foobar', 'baz')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL(' trim', 'baz')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL('foo::bar::baz', 'baz')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL(123, 'baz')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL([ ], 'baz')");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test call function
////////////////////////////////////////////////////////////////////////////////
testCallDisallowed : function () {
assertQueryError(errors.ERROR_QUERY_DISALLOWED_DYNAMIC_CALL.code, "RETURN CALL('CALL')");
assertQueryError(errors.ERROR_QUERY_DISALLOWED_DYNAMIC_CALL.code, "RETURN CALL('APPLY')");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test apply function
////////////////////////////////////////////////////////////////////////////////
testApply : function () {
var data = [
[ "foo bar", [ "TRIM", " foo bar " ] ],
[ "foo bar", [ "TRIM", " foo bar ", "\r\n \t" ] ],
[ "..foo bar..", [ "TRIM", " ..foo bar.. " ] ],
[ "foo bar", [ "TRIM", " ..foo bar.. ", ". " ] ],
[ "foo", [ "LEFT", "foobarbaz", 3 ] ],
[ "fooba", [ "LEFT", "foobarbaz", 5 ] ],
[ "foob", [ "SUBSTRING", "foobarbaz", 0, 4 ] ],
[ "oob", [ "SUBSTRING", "foobarbaz", 1, 3 ] ],
[ "barbaz", [ "SUBSTRING", "foobarbaz", 3 ] ],
[ "FOOBARBAZ", [ "UPPER", "foobarbaz" ] ],
[ "foobarbaz", [ "lower", "FOOBARBAZ" ] ],
[ "abcfood", [ "concat", "a", "b", "c", "foo", "d" ] ],
[ 1, [ "flOoR", 1.6 ] ],
[ 17, [ "MIN", [ 23, 42, 17 ] ] ],
[ [ 1, 2, 3, 4, 7, 9, 10, 12 ], [ "UNION_DISTINCT", [ 1, 2, 3, 4 ], [ 9, 12 ], [ 2, 9, 7, 10 ] ] ],
[ { a: true, b: false, c: null }, [ "ZIP", [ "a", "b", "c" ], [ true, false, null ] ] ]
];
data.forEach(function (d) {
var args = [ ];
for (var i = 1; i < d[1].length; ++i) {
args.push(d[1][i]);
}
var actual = getQueryResults("RETURN APPLY(" + JSON.stringify(d[1][0]) + ", " + JSON.stringify(args) + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test apply function
////////////////////////////////////////////////////////////////////////////////
testApplyDynamic1 : function () {
var actual = getQueryResults("FOR func IN [ 'TRIM', 'LOWER', 'UPPER' ] RETURN APPLY(func, [ ' foObAr ' ])");
assertEqual(actual, [ 'foObAr', ' foobar ', ' FOOBAR ' ]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test apply function
////////////////////////////////////////////////////////////////////////////////
testApplyDynamic2 : function () {
var actual = getQueryResults("FOR doc IN [ { value: ' foobar', func: 'TRIM' }, { value: 'FOOBAR', func: 'LOWER' }, { value: 'foobar', func: 'UPPER' } ] RETURN APPLY(doc.func, [ doc.value ])");
assertEqual(actual, [ 'foobar', 'foobar', 'FOOBAR' ]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test apply function
////////////////////////////////////////////////////////////////////////////////
testApplyNonExisting : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN APPLY()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN APPLY('TRIM', 1, 2)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY('nono-existing', [ 'baz' ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY('foobar', [ 'baz' ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY(' trim', [ 'baz' ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY('foo::bar::baz', [ 'baz' ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY(123, [ 'baz' ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY([ ], [ 'baz' ])");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test apply function
////////////////////////////////////////////////////////////////////////////////
testApplyDisallowed : function () {
assertQueryError(errors.ERROR_QUERY_DISALLOWED_DYNAMIC_CALL.code, "RETURN APPLY('CALL')");
assertQueryError(errors.ERROR_QUERY_DISALLOWED_DYNAMIC_CALL.code, "RETURN APPLY('APPLY')");
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function ahuacatlCallUserDefinedTestSuite () {
var aqlfunctions = require("org/arangodb/aql/functions");
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
[ "add3", "add2", "call", "throwing" ].forEach(function (f) {
try {
aqlfunctions.unregister("UnitTests::func::" + f);
}
catch (err) {
}
});
aqlfunctions.register("UnitTests::func::add3", function (a, b, c) {
return a + b + c;
});
aqlfunctions.register("UnitTests::func::add2", function (a, b) {
return a + b;
});
aqlfunctions.register("UnitTests::func::call", function () {
return undefined;
});
aqlfunctions.register("UnitTests::func::throwing", function () {
throw "doh!";
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
[ "add3", "add2", "call", "throwing" ].forEach(function (f) {
try {
aqlfunctions.unregister("UnitTests::func::" + f);
}
catch (err) {
}
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test call function
////////////////////////////////////////////////////////////////////////////////
testCall : function () {
var data = [
[ null, [ "UnitTests::func::call", 1234 ] ],
[ null, [ "UnitTests::func::call", "foo", "bar" ] ],
[ null, [ "UnitTests::func::add2" ] ],
[ null, [ "UnitTests::func::add2", 23 ] ],
[ 23, [ "UnitTests::func::add2", 23, null ] ],
[ 65, [ "UnitTests::func::add2", 23, 42 ] ],
[ null, [ "UnitTests::func::add3", 23 ] ],
[ null, [ "UnitTests::func::add3", 23, 42 ] ],
[ 65, [ "UnitTests::func::add3", 23, 42, null ] ],
[ 120, [ "UnitTests::func::add3", 23, 42, 55 ] ],
[ "65foo", [ "UnitTests::func::add3", 23, 42, "foo" ] ],
[ "bar4213", [ "UnitTests::func::add3", "bar", 42, 13 ] ],
[ 96, [ "UNITTESTS::FUNC::aDD3", -1, 42, 55 ] ],
[ 96, [ "unittests::func::ADD3", -1, 42, 55 ] ]
];
data.forEach(function (d) {
var actual = getQueryResults("RETURN CALL(" + d[1].map(function (v) { return JSON.stringify(v); }).join(", ") + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test apply function
////////////////////////////////////////////////////////////////////////////////
testApply : function () {
var data = [
[ null, [ "UnitTests::func::call", 1234 ] ],
[ null, [ "UnitTests::func::call", "foo", "bar" ] ],
[ null, [ "UnitTests::func::add2" ] ],
[ null, [ "UnitTests::func::add2", 23 ] ],
[ 23, [ "UnitTests::func::add2", 23, null ] ],
[ 65, [ "UnitTests::func::add2", 23, 42 ] ],
[ null, [ "UnitTests::func::add3", 23 ] ],
[ null, [ "UnitTests::func::add3", 23, 42 ] ],
[ 65, [ "UnitTests::func::add3", 23, 42, null ] ],
[ 120, [ "UnitTests::func::add3", 23, 42, 55 ] ],
[ "65foo", [ "UnitTests::func::add3", 23, 42, "foo" ] ],
[ "bar4213", [ "UnitTests::func::add3", "bar", 42, 13 ] ],
[ 96, [ "UNITTESTS::FUNC::aDD3", -1, 42, 55 ] ],
[ 96, [ "unittests::func::ADD3", -1, 42, 55 ] ]
];
data.forEach(function (d) {
var args = [ ];
for (var i = 1; i < d[1].length; ++i) {
args.push(d[1][i]);
}
var actual = getQueryResults("RETURN APPLY(" + JSON.stringify(d[1][0]) + ", " + JSON.stringify(args) + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test non-existing functions
////////////////////////////////////////////////////////////////////////////////
testNonExisting : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL('UNITTESTS::FUNC::MEOW', 'baz')");
assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY('UNITTESTS::FUNC::MEOW', [ 'baz' ])");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test throwing function
////////////////////////////////////////////////////////////////////////////////
testThrows : function () {
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR.code, "RETURN CALL('UNITTESTS::FUNC::THROWING')");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR.code, "RETURN APPLY('UNITTESTS::FUNC::THROWING', [ ])");
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ahuacatlCallApplyTestSuite);
jsunity.run(ahuacatlCallUserDefinedTestSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

View File

@ -0,0 +1,617 @@
/*jshint strict: false, maxlen: 500 */
/*global require, assertEqual */
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for query language, functions
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var internal = require("internal");
var errors = internal.errors;
var jsunity = require("jsunity");
var helper = require("org/arangodb/aql-helper");
var getQueryResults = helper.getQueryResults;
var assertQueryError = helper.assertQueryError;
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function ahuacatlListTestSuite () {
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief test push function
////////////////////////////////////////////////////////////////////////////////
testPush : function () {
var data = [
[ [ 1, 2, 3, 4 ], [ [ 1, 2, 3 ], 4 ] ],
[ [ 1, 2, 3, "foo" ], [ [ 1, 2, 3 ], "foo" ] ],
[ [ "foo", "bar", "baz", "foo" ], [ [ "foo", "bar", "baz", ], "foo" ] ],
[ [ "foo" ], [ null, "foo" ] ],
[ null, [ false, "foo" ] ],
[ null, [ 1, "foo" ] ],
[ [ "foo" ], [ [ ], "foo" ] ],
[ null, [ "foo", "foo" ] ],
[ null, [ { }, "foo" ] ],
[ [ "" ], [ [ ], "" ] ],
[ [ false, false ], [ [ false ], false ] ],
[ [ false, null ], [ [ false ], null ] ],
[ [ 0 ], [ [ ], 0, true ] ],
[ [ true, 1 ], [ [ true ], 1, true ] ],
[ [ true ], [ [ true ], true, true ] ],
[ [ true, true ], [ [ true ], true, false ] ],
[ [ "foo", "bar", "foo" ], [ [ "foo", "bar", "foo" ], "foo", true ] ],
[ [ "foo", [ ] ], [ [ "foo" ], [ ], true ] ],
[ [ "foo", [ ] ], [ [ "foo", [ ] ], [ ], true ] ],
[ [ "foo", [ ], [ ] ], [ [ "foo", [ ] ], [ ], false ] ],
[ [ { a: 1 }, { a: 2 }, { b: 1 } ], [ [ { a: 1 }, { a: 2 }, { b: 1 } ], { a: 1 }, true ] ],
[ [ { a: 1 }, { a: 2 }, { b: 1 }, { a: 1 } ], [ [ { a: 1 }, { a: 2 }, { b: 1 } ], { a: 1 }, false ] ],
[ [ { a: 1 }, { a: 2 }, { b: 1 }, { b: 2 } ], [ [ { a: 1 }, { a: 2 }, { b: 1 } ], { b: 2 }, true ] ]
];
data.forEach(function (d) {
var actual = getQueryResults("RETURN PUSH(" + d[1].map(function (v) { return JSON.stringify(v); }).join(", ") + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test push function
////////////////////////////////////////////////////////////////////////////////
testPushBig : function () {
var l = [];
for (var i = 0; i < 2000; i += 2) {
l.push(i);
}
var actual = getQueryResults("RETURN PUSH(" + JSON.stringify(l) + ", 1000, true)");
assertEqual(l, actual[0]);
assertEqual(1000, actual[0].length);
actual = getQueryResults("RETURN PUSH(" + JSON.stringify(l) + ", 1000, true)");
assertEqual(l, actual[0]);
assertEqual(1000, actual[0].length);
actual = getQueryResults("RETURN PUSH(" + JSON.stringify(l) + ", 1000, false)");
l.push(1000);
assertEqual(l, actual[0]);
assertEqual(1001, actual[0].length);
actual = getQueryResults("RETURN PUSH(" + JSON.stringify(l) + ", 1001, true)");
l.push(1001);
assertEqual(l, actual[0]);
assertEqual(1002, actual[0].length);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test push function
////////////////////////////////////////////////////////////////////////////////
testPushInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN PUSH()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN PUSH([ ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN PUSH([ ], 1, 2, 3)");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test unshift function
////////////////////////////////////////////////////////////////////////////////
testUnshift : function () {
var data = [
[ [ 4, 1, 2, 3 ], [ [ 1, 2, 3 ], 4 ] ],
[ [ "foo", 1, 2, 3 ], [ [ 1, 2, 3 ], "foo" ] ],
[ [ "foo", "foo", "bar", "baz" ], [ [ "foo", "bar", "baz", ], "foo" ] ],
[ [ "foo" ], [ null, "foo" ] ],
[ null, [ false, "foo" ] ],
[ null, [ 1, "foo" ] ],
[ [ "foo" ], [ [ ], "foo" ] ],
[ null, [ "foo", "foo" ] ],
[ null, [ { }, "foo" ] ],
[ [ "" ], [ [ ], "" ] ],
[ [ false, false ], [ [ false ], false ] ],
[ [ null, false ], [ [ false ], null ] ],
[ [ 0 ], [ [ ], 0, true ] ],
[ [ 1, true ], [ [ true ], 1, true ] ],
[ [ true ], [ [ true ], true, true ] ],
[ [ true, true ], [ [ true ], true, false ] ],
[ [ "foo", "bar", "foo" ], [ [ "foo", "bar", "foo" ], "foo", true ] ],
[ [ "baz", "foo", "bar", "foo" ], [ [ "foo", "bar", "foo" ], "baz", true ] ],
[ [ [ ], "foo" ], [ [ "foo" ], [ ], true ] ],
[ [ "foo", [ ] ], [ [ "foo", [ ] ], [ ], true ] ],
[ [ [ ], "foo" ], [ [ [ ], "foo" ], [ ], true ] ],
[ [ [ ], "foo", [ ] ], [ [ "foo", [ ] ], [ ], false ] ],
[ [ [ ], [ ], "foo" ], [ [ [ ], "foo" ], [ ], false ] ],
[ [ { a: 1 }, { a: 2 }, { b: 1 } ], [ [ { a: 1 }, { a: 2 }, { b: 1 } ], { a: 1 }, true ] ],
[ [ { a: 1 }, { a: 1 }, { a: 2 }, { b: 1 } ], [ [ { a: 1 }, { a: 2 }, { b: 1 } ], { a: 1 }, false ] ],
[ [ { b: 2 }, { a: 1 }, { a: 2 }, { b: 1 } ], [ [ { a: 1 }, { a: 2 }, { b: 1 } ], { b: 2 }, true ] ]
];
data.forEach(function (d) {
var actual = getQueryResults("RETURN UNSHIFT(" + d[1].map(function (v) { return JSON.stringify(v); }).join(", ") + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test unshift function
////////////////////////////////////////////////////////////////////////////////
testUnshiftBig : function () {
var l = [];
for (var i = 0; i < 2000; i += 2) {
l.push(i);
}
var actual = getQueryResults("RETURN UNSHIFT(" + JSON.stringify(l) + ", 1000, true)");
assertEqual(l, actual[0]);
assertEqual(1000, actual[0].length);
actual = getQueryResults("RETURN UNSHIFT(" + JSON.stringify(l) + ", 1000, true)");
assertEqual(l, actual[0]);
assertEqual(1000, actual[0].length);
actual = getQueryResults("RETURN UNSHIFT(" + JSON.stringify(l) + ", 1000, false)");
l.unshift(1000);
assertEqual(l, actual[0]);
assertEqual(1001, actual[0].length);
actual = getQueryResults("RETURN UNSHIFT(" + JSON.stringify(l) + ", 1001, true)");
l.unshift(1001);
assertEqual(l, actual[0]);
assertEqual(1002, actual[0].length);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test unshift function
////////////////////////////////////////////////////////////////////////////////
testUnshiftInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN UNSHIFT()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN UNSHIFT([ ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN UNSHIFT([ ], 1, 2, 3)");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test pop function
////////////////////////////////////////////////////////////////////////////////
testPop : function () {
var data = [
[ null, null ],
[ null, false ],
[ null, true ],
[ null, 23 ],
[ null, "foo" ],
[ null, { } ],
[ [ ], [ ] ],
[ [ 1, 2 ], [ 1, 2, 3 ] ],
[ [ 1, 2, 3, "foo" ], [ 1, 2, 3, "foo", 4 ] ],
[ [ 1, 2, 3 ], [ 1, 2, 3, "foo" ] ],
[ [ "foo", "bar", "baz" ], [ "foo", "bar", "baz", "foo" ] ],
[ [ null ], [ null, "foo" ] ],
[ [ false ], [ false, "foo" ] ],
[ [ 1 ], [ 1, "foo" ] ],
[ [ [ ] ], [ [ ], "foo" ] ],
[ [ "foo" ], [ "foo", "foo" ] ],
[ [ "foo" ], [ "foo", "bar" ] ],
[ [ { } ], [ { }, "foo" ] ],
[ [ [ ] ], [ [ ], "" ] ],
[ [ [ false ] ], [ [ false ], false ] ],
[ [ [ false ] ], [ [ false ], null ] ],
[ [ [ ], 0 ], [ [ ], 0, true ] ],
[ [ true, 1 ], [ true, 1, true ] ],
[ [ true, true ], [ true, true, true ] ],
[ [ true, false ], [ true, false, true ] ],
[ [ true, false ], [ true, false, false ] ],
[ [ [ true ], true ], [ [ true ], true, false ] ],
[ [ [ "foo", "bar", "foo" ], "foo" ], [ [ "foo", "bar", "foo" ], "foo", true ] ],
[ [ "foo", [ ] ], [ "foo", [ ], true ] ],
[ [ "foo", [ ], [ ] ], [ "foo", [ ], [ ], true ] ],
[ [ "foo", [ ], [ ] ], [ "foo", [ ], [ ], false ] ],
[ [ { a: 1 }, { a: 2 } ], [ { a: 1 }, { a: 2 }, { b: 1 } ] ],
[ [ { a: 1 }, { a: 2 }, { b: 1 } ], [ { a: 1 }, { a: 2 }, { b: 1 }, { a: 1 } ] ],
[ [ { a: 1 }, { a: 2 }, { b: 1 } ], [ { a: 1 }, { a: 2 }, { b: 1 }, { b: 2 } ] ]
];
data.forEach(function (d) {
var actual = getQueryResults("RETURN POP(" + JSON.stringify(d[1]) + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test pop function
////////////////////////////////////////////////////////////////////////////////
testPopBig : function () {
var l = [];
for (var i = 0; i < 2000; i += 2) {
l.push(i);
}
var actual = getQueryResults("RETURN POP(" + JSON.stringify(l) + ")");
l.pop();
assertEqual(l, actual[0]);
assertEqual(999, actual[0].length);
actual = getQueryResults("RETURN POP(" + JSON.stringify(l) + ")");
l.pop();
assertEqual(l, actual[0]);
assertEqual(998, actual[0].length);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test pop function
////////////////////////////////////////////////////////////////////////////////
testPopInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN POP()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN POP([ ], 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN POP([ ], 1, 2)");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test shift function
////////////////////////////////////////////////////////////////////////////////
testShift : function () {
var data = [
[ null, null ],
[ null, false ],
[ null, true ],
[ null, 23 ],
[ null, "foo" ],
[ null, { } ],
[ [ ], [ ] ],
[ [ 2, 3 ], [ 1, 2, 3 ] ],
[ [ 2, 3, "foo", 4 ], [ 1, 2, 3, "foo", 4 ] ],
[ [ 2, 3, "foo" ], [ 1, 2, 3, "foo" ] ],
[ [ "bar", "baz", "foo" ], [ "foo", "bar", "baz", "foo" ] ],
[ [ "foo" ], [ null, "foo" ] ],
[ [ "foo" ], [ false, "foo" ] ],
[ [ "foo" ], [ 1, "foo" ] ],
[ [ "foo" ], [ [ ], "foo" ] ],
[ [ "foo" ], [ "foo", "foo" ] ],
[ [ "bar" ], [ "foo", "bar" ] ],
[ [ "foo" ], [ { }, "foo" ] ],
[ [ { } ], [ "foo", { } ] ],
[ [ "" ], [ [ ], "" ] ],
[ [ [ ] ], [ "", [ ] ] ],
[ [ false ], [ [ false ], false ] ],
[ [ null ], [ [ false ], null ] ],
[ [ 0, true ], [ [ ], 0, true ] ],
[ [ 1, true ], [ true, 1, true ] ],
[ [ true, true ], [ true, true, true ] ],
[ [ false, true ], [ true, false, true ] ],
[ [ false, false ], [ true, false, false ] ],
[ [ true, false ], [ [ true ], true, false ] ],
[ [ "foo", true ], [ [ "foo", "bar", "foo" ], "foo", true ] ],
[ [ [ ], true ], [ "foo", [ ], true ] ],
[ [ [ ], [ ], true ], [ "foo", [ ], [ ], true ] ],
[ [ [ ], [ ], false ], [ "foo", [ ], [ ], false ] ],
[ [ { a: 2 }, { b: 1 } ], [ { a: 1 }, { a: 2 }, { b: 1 } ] ],
[ [ { a: 2 }, { b: 1 }, { a: 1 } ], [ { a: 1 }, { a: 2 }, { b: 1 }, { a: 1 } ] ],
[ [ { a: 2 }, { b: 1 }, { b: 2 } ], [ { a: 1 }, { a: 2 }, { b: 1 }, { b: 2 } ] ]
];
data.forEach(function (d) {
var actual = getQueryResults("RETURN SHIFT(" + JSON.stringify(d[1]) + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test shift function
////////////////////////////////////////////////////////////////////////////////
testShiftBig : function () {
var l = [];
for (var i = 0; i < 2000; i += 2) {
l.push(i);
}
var actual = getQueryResults("RETURN SHIFT(" + JSON.stringify(l) + ")");
l.shift();
assertEqual(l, actual[0]);
assertEqual(999, actual[0].length);
actual = getQueryResults("RETURN SHIFT(" + JSON.stringify(l) + ")");
l.shift();
assertEqual(l, actual[0]);
assertEqual(998, actual[0].length);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test shift function
////////////////////////////////////////////////////////////////////////////////
testShiftInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN SHIFT()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN SHIFT([ ], 1)");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN SHIFT([ ], 1, 2)");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test push/pop function
////////////////////////////////////////////////////////////////////////////////
testPushPop : function () {
var l = [], i, actual;
for (i = 0; i < 1000; ++i) {
actual = getQueryResults("RETURN PUSH(" + JSON.stringify(l) + ", " + JSON.stringify(i) + ")");
l.push(i);
assertEqual(l, actual[0]);
}
for (i = 0; i < 1000; ++i) {
actual = getQueryResults("RETURN POP(" + JSON.stringify(l) + ")");
l.pop();
assertEqual(l, actual[0]);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test unshift/shift function
////////////////////////////////////////////////////////////////////////////////
testUnshiftShift : function () {
var l = [], i, actual;
for (i = 0; i < 1000; ++i) {
actual = getQueryResults("RETURN UNSHIFT(" + JSON.stringify(l) + ", " + JSON.stringify(i) + ")");
l.unshift(i);
assertEqual(l, actual[0]);
}
for (i = 0; i < 1000; ++i) {
actual = getQueryResults("RETURN SHIFT(" + JSON.stringify(l) + ")");
l.shift();
assertEqual(l, actual[0]);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test append function
////////////////////////////////////////////////////////////////////////////////
testAppend : function () {
var data = [
[ [ ], [ [ ], [ ] ] ],
[ [ "foo", "bar", "baz" ], [ [ "foo" ], [ "bar", "baz" ] ] ],
[ [ "foo", "foo", "bar", "baz" ], [ [ "foo" ], [ "foo", "bar", "baz" ] ] ],
[ [ "foo", "bar", "baz" ], [ [ "foo" ], [ "foo", "bar", "baz" ], true ] ],
[ [ "foo", "bar", "baz" ], [ [ "foo" ], [ "foo", "bar", "baz", "foo" ], true ] ],
[ [ "foo", "bar", "baz" ], [ [ "foo", "bar" ], [ "baz" ] ] ],
[ [ "foo", "bar", "baz" ], [ null, [ "foo", "bar", "baz" ] ] ],
[ [ "foo", "bar", "baz" ], [ [ "foo", "bar", "baz" ], null ] ],
[ [ "foo", "bar", "baz" ], [ [ ], [ "foo", "bar", "baz" ] ] ],
[ [ "foo", "bar", "baz" ], [ [ "foo", "bar", "baz" ], [ ] ] ],
[ [ "foo", "bar", "baz", "one", "two", "three" ], [ [ "foo", "bar", "baz" ], [ "one", "two", "three" ] ] ],
[ [ "foo", "bar", "baz", "one", "two", null, "three" ], [ [ "foo", "bar", "baz" ], [ "one", "two", null, "three" ] ] ],
[ [ "two", "one", null, "three", "one", "two", null, "three" ], [ [ "two", "one", null, "three" ], [ "one", "two", null, "three" ] ] ],
[ [ "two", "one", null, "three" ], [ [ "two", "one", null, "three" ], [ "one", "two", null, "three" ], true ] ],
[ [ "two", "one", null, "three", "four" ], [ [ "two", "one", null, "three" ], [ "one", "two", "four", null, "three" ], true ] ]
];
data.forEach(function (d) {
var actual = getQueryResults("RETURN APPEND(" + d[1].map(function (v) { return JSON.stringify(v); }).join(", ") + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test append function
////////////////////////////////////////////////////////////////////////////////
testAppendBig : function () {
var l1 = [], l2 = [ ];
for (var i = 0; i < 2000; i += 4) {
l1.push(i);
l2.push(i + 1);
}
var actual = getQueryResults("RETURN APPEND(" + JSON.stringify(l1) + ", " + JSON.stringify(l2) + ")");
var l = l1.concat(l2);
assertEqual(l, actual[0]);
assertEqual(1000, actual[0].length);
actual = getQueryResults("RETURN APPEND(" + JSON.stringify(l) + ", " + JSON.stringify(l1) + ")");
l = l.concat(l1);
assertEqual(l, actual[0]);
assertEqual(1500, actual[0].length);
actual = getQueryResults("RETURN APPEND(" + JSON.stringify(l) + ", " + JSON.stringify(l1) + ", true)");
assertEqual(l, actual[0]);
assertEqual(1500, actual[0].length);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test append function
////////////////////////////////////////////////////////////////////////////////
testAppendInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN APPEND()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN APPEND([ ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN APPEND([ ], [ ], false, [ ])");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test removeValues function
////////////////////////////////////////////////////////////////////////////////
testRemoveValues : function () {
var data = [
[ [ ], [ [ ], [ ] ] ],
[ [ ], [ [ ], [ "1", "2" ] ] ],
[ [ "1", "2" ], [ [ "1", "2" ], [ ] ] ],
[ [ "1", "2" ], [ [ "1", "2" ], [ 1, 2 ] ] ],
[ [ 1, 2 ], [ [ 1, 2 ], [ "1", "2" ] ] ],
[ [ 2 ], [ [ 1, 2 ], [ "1", "2", 1 ] ] ],
[ [ "1", "2" ], [ [ "1", "2" ], [ "foo", 1] ] ],
[ [ "foo" ], [ [ "foo" ], [ "bar", "baz" ] ] ],
[ [ ], [ [ "foo" ], [ "foo", "bar", "baz" ] ] ],
[ [ ], [ [ "foo" ], [ "foo", "bar", "baz" ] ] ],
[ [ ], [ [ "foo" ], [ "foo", "bar", "baz", "foo" ] ] ],
[ [ "foo", "bar" ], [ [ "foo", "bar" ], [ "baz" ] ] ],
[ [ ], [ null, [ "foo", "bar", "baz" ] ] ],
[ [ "foo", "bar", "baz" ], [ [ "foo", "bar", "baz" ], null ] ],
[ [ ], [ [ ], [ "foo", "bar", "baz" ] ] ],
[ [ "foo", "bar", "baz" ], [ [ "foo", "bar", "baz" ], [ ] ] ],
[ [ "foo", "bar", "baz" ], [ [ "foo", "bar", "baz" ], [ "one", "two", "three" ] ] ],
[ [ "foo", "bar", "baz" ], [ [ "foo", null, "bar", "baz" ], [ "one", "two", null, "three" ] ] ],
[ [ ], [ [ "two", "one", null, "three" ], [ "one", "two", null, "three" ] ] ],
[ [ null ], [ [ "two", "one", null, "three" ], [ "one", "two", "three" ] ] ],
[ [ "four", "five" ], [ [ "two", "four", "one", null, "three", "five" ], [ "one", "two", null, "three" ] ] ],
[ [ ], [ [ "two", "one", null, "three" ], [ "one", "two", "four", null, "three" ] ] ]
];
data.forEach(function (d) {
var actual = getQueryResults("RETURN REMOVE_VALUES(" + d[1].map(function (v) { return JSON.stringify(v); }).join(", ") + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test removeValues function
////////////////////////////////////////////////////////////////////////////////
testRemoveValuesInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REMOVE_VALUES()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REMOVE_VALUES([ ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REMOVE_VALUES([ ], [ ], true)");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test removeValue function
////////////////////////////////////////////////////////////////////////////////
testRemoveValue : function () {
var data = [
[ [ ], [ [ ], null ] ],
[ [ ], [ [ ], false ] ],
[ [ ], [ [ ], 1 ] ],
[ [ ], [ [ ], "1" ] ],
[ [ ], [ [ ], [ ] ] ],
[ [ ], [ [ ], [ "1", "2" ] ] ],
[ [ "1", "2" ], [ [ "1", "2" ], [ ] ] ],
[ [ "1", "2" ], [ [ "1", "2" ], 1 ] ],
[ [ "1", "2" ], [ [ "1", "2" ], 2 ] ],
[ [ "2" ], [ [ "1", "2" ], "1" ] ],
[ [ "1" ], [ [ "1", "2" ], "2" ] ],
[ [ "1", "1", "1", "3" ], [ [ "1", "1", "1", "2", "2", "3" ], "2" ] ],
[ [ "1", "1", "1", "2", "3" ], [ [ "1", "1", "1", "2", "2", "3" ], "2", 1 ] ],
[ [ ], [ [ "foo" ], "foo" ] ],
[ [ "bar" ], [ [ "bar" ], "foo" ] ],
[ [ "foo" ], [ [ "foo" ], "bar" ] ],
[ [ ], [ [ "foo", "foo", "foo" ], "foo" ] ],
[ [ "foo", "foo" ], [ [ "foo", "foo", "foo" ], "foo", 1 ] ],
[ [ "foo" ], [ [ "foo", "foo", "foo" ], "foo", 2 ] ],
[ [ ], [ [ "foo", "foo", "foo" ], "foo", 3 ] ],
[ [ ], [ [ "foo", "foo", "foo" ], "foo", 496 ] ],
[ [ "bar", "foo", "bam", "foo", "baz" ], [ [ "bar", "foo", "foo", "bam", "foo", "baz" ], "foo", 1 ] ],
[ [ "bar", "bam", "baz", "foo" ], [ [ "bar", "bam", "baz", "foo", "foo" ], "foo", 1 ] ],
[ [ "bar", "bam", "baz" ], [ [ "bar", "bam", "baz", "foo", "foo" ], "foo", 2 ] ],
[ [ [ 1, 2, 3 ] ], [ [ [ 1, 2, 3 ] ], [ 1, 2 ] ] ],
[ [ [ 1, 2, 3 ] ], [ [ [ 1, 2, 3 ] ], [ 1, 3, 2 ] ] ],
[ [ ], [ [ [ 1, 2, 3 ] ], [ 1, 2, 3] ] ]
];
data.forEach(function (d) {
var actual = getQueryResults("RETURN REMOVE_VALUE(" + d[1].map(function (v) { return JSON.stringify(v); }).join(", ") + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test removeValue function
////////////////////////////////////////////////////////////////////////////////
testRemoveValueInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REMOVE_VALUE()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REMOVE_VALUE([ ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REMOVE_VALUE([ ], [ ], true, true)");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test removeNth function
////////////////////////////////////////////////////////////////////////////////
testRemoveNth : function () {
var data = [
[ [ ], [ [ ], 0 ] ],
[ [ ], [ [ ], -1 ] ],
[ [ ], [ [ ], -2 ] ],
[ [ ], [ [ ], 99 ] ],
[ [ ], [ [ ], null ] ],
[ [ "2" ], [ [ "1", "2" ], 0 ] ],
[ [ "1" ], [ [ "1", "2" ], 1 ] ],
[ [ "1", "2" ], [ [ "1", "2" ], 2 ] ],
[ [ "1", "2" ], [ [ "1", "2" ], -3 ] ],
[ [ "2" ], [ [ "1", "2" ], -2 ] ],
[ [ "1" ], [ [ "1", "2" ], -1 ] ],
[ [ "1b", "1c", "2a", "2b", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], 0 ] ],
[ [ "1a", "1c", "2a", "2b", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], 1 ] ],
[ [ "1a", "1b", "2a", "2b", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], 2 ] ],
[ [ "1a", "1b", "1c", "2b", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], 3 ] ],
[ [ "1a", "1b", "1c", "2a", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], 4 ] ],
[ [ "1a", "1b", "1c", "2a", "2b" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], 5 ] ],
[ [ "1a", "1b", "1c", "2a", "2b", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], 6 ] ],
[ [ "1a", "1b", "1c", "2a", "2b" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], -1 ] ],
[ [ "1a", "1b", "1c", "2a", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], -2 ] ],
[ [ "1a", "1b", "1c", "2b", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], -3 ] ],
[ [ "1a", "1b", "2a", "2b", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], -4 ] ],
[ [ "1a", "1c", "2a", "2b", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], -5 ] ],
[ [ "1b", "1c", "2a", "2b", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], -6 ] ],
[ [ "1a", "1b", "1c", "2a", "2b", "3" ], [ [ "1a", "1b", "1c", "2a", "2b", "3" ], -7 ] ]
];
data.forEach(function (d) {
var actual = getQueryResults("RETURN REMOVE_NTH(" + d[1].map(function (v) { return JSON.stringify(v); }).join(", ") + ")");
assertEqual(d[0], actual[0], d);
});
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test removeNth function
////////////////////////////////////////////////////////////////////////////////
testRemoveNthInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REMOVE_NTH()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REMOVE_NTH([ ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN REMOVE_NTH([ ], 1, true)");
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ahuacatlListTestSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End:

View File

@ -32,7 +32,6 @@ var errors = internal.errors;
var jsunity = require("jsunity");
var helper = require("org/arangodb/aql-helper");
var getQueryResults = helper.getQueryResults;
var getQueryResults = helper.getQueryResults;
var assertQueryError = helper.assertQueryError;
var assertQueryWarningAndNull = helper.assertQueryWarningAndNull;

View File

@ -218,6 +218,7 @@ ERROR_QUERY_MODIFY_IN_SUBQUERY,1574,"modify operation in subquery", "Will be rai
ERROR_QUERY_COMPILE_TIME_OPTIONS,1575,"query options must be readable at query compile time", "Will be raised when an AQL data-modification query contains options that cannot be figured out at query compile time."
ERROR_QUERY_EXCEPTION_OPTIONS,1576,"query options expected", "Will be raised when an AQL data-modification query contains an invalid options specification."
ERROR_QUERY_COLLECTION_USED_IN_EXPRESSION,1577,"collection '%s' used as expression operand", "Will be raised when a collection is used as an operand in an AQL expression."
ERROR_QUERY_DISALLOWED_DYNAMIC_CALL,1578,"disallowed dynamic call to '%s'", "Will be raised when a dynamic function call is made to a function that cannot be called dynamically."
################################################################################
## AQL user functions

View File

@ -173,6 +173,7 @@ void TRI_InitialiseErrorMessages () {
REG_ERROR(ERROR_QUERY_COMPILE_TIME_OPTIONS, "query options must be readable at query compile time");
REG_ERROR(ERROR_QUERY_EXCEPTION_OPTIONS, "query options expected");
REG_ERROR(ERROR_QUERY_COLLECTION_USED_IN_EXPRESSION, "collection '%s' used as expression operand");
REG_ERROR(ERROR_QUERY_DISALLOWED_DYNAMIC_CALL, "disallowed dynamic call to '%s'");
REG_ERROR(ERROR_QUERY_FUNCTION_INVALID_NAME, "invalid user function name");
REG_ERROR(ERROR_QUERY_FUNCTION_INVALID_CODE, "invalid user function code");
REG_ERROR(ERROR_QUERY_FUNCTION_NOT_FOUND, "user function '%s()' not found");

View File

@ -427,6 +427,9 @@
/// - 1577: @LIT{collection '\%s' used as expression operand}
/// "Will be raised when a collection is used as an operand in an AQL
/// expression."
/// - 1578: @LIT{disallowed dynamic call to '\%s'}
/// "Will be raised when a dynamic function call is made to a function that
/// cannot be called dynamically."
/// - 1580: @LIT{invalid user function name}
/// Will be raised when a user function with an invalid name is registered.
/// - 1581: @LIT{invalid user function code}
@ -2352,6 +2355,17 @@ void TRI_InitialiseErrorMessages ();
#define TRI_ERROR_QUERY_COLLECTION_USED_IN_EXPRESSION (1577)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1578: ERROR_QUERY_DISALLOWED_DYNAMIC_CALL
///
/// disallowed dynamic call to '%s'
///
/// "Will be raised when a dynamic function call is made to a function that
/// cannot be called dynamically."
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_QUERY_DISALLOWED_DYNAMIC_CALL (1578)
////////////////////////////////////////////////////////////////////////////////
/// @brief 1580: ERROR_QUERY_FUNCTION_INVALID_NAME
///