mirror of https://gitee.com/bigwinds/arangodb
added AQL TRANSLATE function
This commit is contained in:
parent
85b92dbf21
commit
34389a10d3
|
@ -1,6 +1,13 @@
|
|||
v2.2.0 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* added AQL TRANSLATE function
|
||||
|
||||
This function can be used to perform lookups from static lists, e.g.
|
||||
|
||||
LET countryNames = { US: "United States", UK: "United Kingdom", FR: "France" }
|
||||
RETURN TRANSLATE("FR", countryNames)
|
||||
|
||||
* fixed check-version for empty directory
|
||||
|
||||
* moved try/catch block to the top of routing chain
|
||||
|
|
|
@ -40,11 +40,6 @@
|
|||
// --SECTION-- private macros
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Ahuacatl
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief shorthand to register a query function and process the result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -62,19 +57,10 @@
|
|||
return false; \
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Ahuacatl
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief parameter type holder
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -91,19 +77,10 @@ typedef struct param_s {
|
|||
}
|
||||
param_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Ahuacatl
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a param_t structure with all bits set to 0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -356,19 +333,10 @@ static bool EqualName (TRI_associative_pointer_t* array,
|
|||
function->_externalName);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- optimiser callbacks
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Ahuacatl
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check if we have a matching restriction we can use to optimise
|
||||
/// a PATHS query
|
||||
|
@ -554,11 +522,13 @@ static void OptimisePaths (const TRI_aql_node_t* const fcallNode,
|
|||
|
||||
// add min and max values to the function call argument list
|
||||
argNode = TRI_CreateNodeValueIntAql(context, useMin ? (int64_t) minValue : (int64_t) 0);
|
||||
|
||||
if (argNode) {
|
||||
// min value node
|
||||
TRI_PushBackVectorPointer(&args->_members, (void*) argNode);
|
||||
|
||||
argNode = TRI_CreateNodeValueIntAql(context, useMax ? (int64_t) maxValue : (int64_t) (1024 * 1024));
|
||||
|
||||
if (argNode) {
|
||||
// max value node
|
||||
TRI_PushBackVectorPointer(&args->_members, (void*) argNode);
|
||||
|
@ -568,19 +538,10 @@ static void OptimisePaths (const TRI_aql_node_t* const fcallNode,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Ahuacatl
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialise the array with the function declarations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -694,6 +655,7 @@ TRI_associative_pointer_t* TRI_CreateFunctionsAql (void) {
|
|||
REGISTER_FUNCTION("MATCHES", "MATCHES", true, false, ".,l|b", NULL);
|
||||
REGISTER_FUNCTION("UNSET", "UNSET", true, false, "a,sl|+", NULL);
|
||||
REGISTER_FUNCTION("KEEP", "KEEP", true, false, "a,sl|+", NULL);
|
||||
REGISTER_FUNCTION("TRANSLATE", "TRANSLATE", true, false, ".,a|.", NULL);
|
||||
|
||||
// geo functions
|
||||
REGISTER_FUNCTION("NEAR", "GEO_NEAR", false, false, "h,n,n|nz,s", NULL);
|
||||
|
@ -1059,10 +1021,6 @@ bool TRI_ValidateArgsFunctionAql (TRI_aql_context_t* const context,
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
|
|
|
@ -44,11 +44,6 @@ struct TRI_associative_pointer_s;
|
|||
// --SECTION-- public defines
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Ahuacatl
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief default namespace for aql functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -73,19 +68,10 @@ struct TRI_associative_pointer_s;
|
|||
|
||||
#define TRI_AQL_DEFAULT_PREFIX TRI_AQL_DEFAULT_NAMESPACE TRI_AQL_NAMESPACE_SEPARATOR
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Ahuacatl
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief query function data structure
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -102,19 +88,10 @@ typedef struct TRI_aql_function_s {
|
|||
}
|
||||
TRI_aql_function_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Ahuacatl
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialise the array with the function declarations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -167,10 +144,6 @@ bool TRI_ValidateArgsFunctionAql (struct TRI_aql_context_s* const,
|
|||
const TRI_aql_function_t* const,
|
||||
const TRI_aql_node_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
|
|
|
@ -3770,6 +3770,29 @@ function MERGE_RECURSIVE () {
|
|||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief translate a value, using a lookup document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function TRANSLATE (value, lookup, defaultValue) {
|
||||
"use strict";
|
||||
|
||||
if (defaultValue === undefined) {
|
||||
defaultValue = value;
|
||||
}
|
||||
|
||||
if (TYPEWEIGHT(lookup) !== TYPEWEIGHT_DOCUMENT) {
|
||||
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "TRANSLATE");
|
||||
}
|
||||
|
||||
var key = String(value);
|
||||
if (lookup.hasOwnProperty(key)) {
|
||||
return lookup[key];
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compare an object against a list of examples and return whether the
|
||||
/// object matches any of the examples. returns the example index or a bool,
|
||||
|
@ -7060,6 +7083,7 @@ exports.UNSET = UNSET;
|
|||
exports.KEEP = KEEP;
|
||||
exports.MERGE = MERGE;
|
||||
exports.MERGE_RECURSIVE = MERGE_RECURSIVE;
|
||||
exports.TRANSLATE = TRANSLATE;
|
||||
exports.MATCHES = MATCHES;
|
||||
exports.PASSTHRU = PASSTHRU;
|
||||
exports.SLEEP = SLEEP;
|
||||
|
|
|
@ -1561,6 +1561,131 @@ function ahuacatlFunctionsTestSuite () {
|
|||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN MERGE_RECURSIVE({ }, { }, [ ])");
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test translate function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTranslate1 : function () {
|
||||
var tests = [
|
||||
{ value: "foo", lookup: { }, expected: "foo" },
|
||||
{ value: "foo", lookup: { foo: "bar" }, expected: "bar" },
|
||||
{ value: "foo", lookup: { bar: "foo" }, expected: "foo" },
|
||||
{ value: 1, lookup: { 1: "one", 2: "two" }, expected: "one" },
|
||||
{ value: 1, lookup: { "1": "one", "2": "two" }, expected: "one" },
|
||||
{ value: "1", lookup: { 1: "one", 2: "two" }, expected: "one" },
|
||||
{ value: "1", lookup: { "1": "one", "2": "two" }, expected: "one" },
|
||||
{ value: null, lookup: { foo: "bar", bar: "foo" }, expected: null },
|
||||
{ value: "foobar", lookup: { foo: "bar", bar: "foo" }, expected: "foobar" },
|
||||
{ value: "foobaz", lookup: { foobar: "bar", foobaz: "replaced!" }, expected: "replaced!" },
|
||||
{ value: "foobaz", lookup: { foobar: "bar", foobaz: null }, expected: null },
|
||||
{ value: "foobaz", lookup: { foobar: "bar", foobaz: [ 1, 2, 3 ] }, expected: [ 1, 2, 3 ] },
|
||||
{ value: "foobaz", lookup: { foobar: "bar", foobaz: { thefoxx: "is great" } }, expected: { thefoxx: "is great" } },
|
||||
{ value: "one", lookup: { one: "two", two: "three", three: "four" }, expected: "two" },
|
||||
{ value: null, lookup: { "foo": "one", " ": "bar", "empty": 3 }, expected: null },
|
||||
{ value: false, lookup: { "foo": "one", " ": "bar", "empty": 3 }, expected: false },
|
||||
{ value: 0, lookup: { "foo": "one", " ": "bar", "empty": 3 }, expected: 0 },
|
||||
{ value: "", lookup: { "foo": "one", " ": "bar", "empty": 3 }, expected: "" },
|
||||
{ value: "CGN", lookup: { "DUS" : "Duessldorf", "FRA" : "Frankfurt", "CGN" : "Cologne" }, expected: "Cologne" }
|
||||
];
|
||||
|
||||
tests.forEach(function(t) {
|
||||
var actual = getQueryResults("RETURN TRANSLATE(@value, @lookup)", { value: t.value, lookup: t.lookup });
|
||||
assertEqual(t.expected, actual[0]);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test translate function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTranslate2 : function () {
|
||||
var i, lookup = { };
|
||||
for (i = 0; i < 100; ++i) {
|
||||
lookup["test" + i] = "the quick brown Foxx:" + i;
|
||||
}
|
||||
|
||||
for (i = 0; i < 100; ++i) {
|
||||
var actual = getQueryResults("RETURN TRANSLATE(@value, @lookup)", { value: "test" + i, lookup: lookup });
|
||||
assertEqual(lookup["test" + i], actual[0]);
|
||||
assertEqual("the quick brown Foxx:" + i, actual[0]);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test translate function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTranslate3 : function () {
|
||||
var i, lookup = { };
|
||||
for (i = 0; i < 100; ++i) {
|
||||
lookup[i] = i * i;
|
||||
}
|
||||
|
||||
for (i = 0; i < 100; ++i) {
|
||||
var actual = getQueryResults("RETURN TRANSLATE(@value, @lookup, @def)", { value: i, lookup: lookup, def: "fail!" });
|
||||
assertEqual(lookup[i], actual[0]);
|
||||
assertEqual(i * i, actual[0]);
|
||||
|
||||
actual = getQueryResults("RETURN TRANSLATE(@value, @lookup, @def)", { value: "test" + i, lookup: lookup, def: "fail" + i });
|
||||
assertEqual("fail" + i, actual[0]);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test translate function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTranslateDefault : function () {
|
||||
var tests = [
|
||||
{ value: "foo", lookup: { }, expected: "bar", def: "bar" },
|
||||
{ value: "foo", lookup: { foo: "bar" }, expected: "bar", def: "lol" },
|
||||
{ value: "foo", lookup: { bar: "foo" }, expected: "lol", def: "lol" },
|
||||
{ value: 1, lookup: { 1: "one", 2: "two" }, expected: "one", def: "foobar" },
|
||||
{ value: 1, lookup: { "1": "one", "2": "two" }, expected: "one", def: "test" },
|
||||
{ value: 1, lookup: { "3": "one", "2": "two" }, expected: "test", def: "test" },
|
||||
{ value: "1", lookup: { 1: "one", 2: "two" }, expected: "one", def: "test" },
|
||||
{ value: "1", lookup: { 3: "one", 2: "two" }, expected: "test", def: "test" },
|
||||
{ value: "1", lookup: { "1": "one", "2": "two" }, expected: "one", def: "test" },
|
||||
{ value: "1", lookup: { "3": "one", "2": "two" }, expected: "test", def: "test" },
|
||||
{ value: null, lookup: { foo: "bar", bar: "foo" }, expected: 1, def: 1 },
|
||||
{ value: null, lookup: { foo: "bar", bar: "foo" }, expected: "foobar", def: "foobar" },
|
||||
{ value: "foobar", lookup: { foo: "bar", bar: "foo" }, expected: "foobart", def: "foobart" },
|
||||
{ value: "foobaz", lookup: { foobar: "bar", foobaz: "replaced!" }, expected: "replaced!", def: "foobart" },
|
||||
{ value: "foobaz", lookup: { foobar: "bar", foobaz: null }, expected: null, def: "foobaz" },
|
||||
{ value: "foobaz", lookup: { foobar: "bar", foobaz: [ 1, 2, 3 ] }, expected: [ 1, 2, 3 ], def: null },
|
||||
{ value: "foobaz", lookup: { foobar: "bar" }, expected: null, def: null },
|
||||
{ value: "foobaz", lookup: { }, expected: "FOXX", def: "FOXX" },
|
||||
{ value: "foobaz", lookup: { foobar: "bar", foobaz: { thefoxx: "is great" } }, expected: { thefoxx: "is great" }, def: null },
|
||||
{ value: "one", lookup: { one: "two", two: "three", three: "four" }, expected: "two", def: "foo" },
|
||||
{ value: null, lookup: { "foo": "one", " ": "bar", "empty": 3 }, expected: "bla", def: "bla" },
|
||||
{ value: false, lookup: { "foo": "one", " ": "bar", "empty": 3 }, expected: true, def: true },
|
||||
{ value: 0, lookup: { "foo": "one", " ": "bar", "empty": 3 }, expected: 42, def: 42 },
|
||||
{ value: "", lookup: { "foo": "one", " ": "bar", "empty": 3 }, expected: "three", def: "three" },
|
||||
{ value: "CGN", lookup: { "DUS" : "Duessldorf", "FRA" : "Frankfurt", "MUC" : "Munich" }, expected: "Cologne", def: "Cologne" }
|
||||
];
|
||||
|
||||
tests.forEach(function(t) {
|
||||
var actual = getQueryResults("RETURN TRANSLATE(@value, @lookup, @def)", { value: t.value, lookup: t.lookup, def: t.def });
|
||||
assertEqual(t.expected, actual[0]);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test merge_recursive function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTranslateInvalid : function () {
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN TRANSLATE()");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN TRANSLATE('foo')");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN TRANSLATE('foo', { }, '', 'baz')");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN TRANSLATE({ }, 'foo')");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN TRANSLATE('', null)");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN TRANSLATE('', true)");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN TRANSLATE('', 1)");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN TRANSLATE('', '')");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN TRANSLATE('', [])");
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test union function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue