1
0
Fork 0

Merge branch 'devel' of https://github.com/arangodb/arangodb into devel

This commit is contained in:
jsteemann 2015-10-28 21:43:08 +01:00
commit 733a3000b7
6 changed files with 543 additions and 220 deletions

View File

@ -153,9 +153,9 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
{ "RANGE", Function("RANGE", "AQL_RANGE", "n,n|n", true, true, false, true, true) },
{ "UNION", Function("UNION", "AQL_UNION", "l,l|+", true, true, false, true, true, &Functions::Union) },
{ "UNION_DISTINCT", Function("UNION_DISTINCT", "AQL_UNION_DISTINCT", "l,l|+", true, true, false, true, true, &Functions::UnionDistinct) },
{ "MINUS", Function("MINUS", "AQL_MINUS", "l,l|+", true, true, false, true, true) },
{ "MINUS", Function("MINUS", "AQL_MINUS", "l,l|+", true, true, false, true, true, &Functions::Minus) },
{ "INTERSECTION", Function("INTERSECTION", "AQL_INTERSECTION", "l,l|+", true, true, false, true, true, &Functions::Intersection) },
{ "FLATTEN", Function("FLATTEN", "AQL_FLATTEN", "l|n", true, true, false, true, true) },
{ "FLATTEN", Function("FLATTEN", "AQL_FLATTEN", "l|n", true, true, false, true, true, &Functions::Flatten) },
{ "LENGTH", Function("LENGTH", "AQL_LENGTH", "las", true, true, false, true, true, &Functions::Length) },
{ "MIN", Function("MIN", "AQL_MIN", "l", true, true, false, true, true, &Functions::Min) },
{ "MAX", Function("MAX", "AQL_MAX", "l", true, true, false, true, true, &Functions::Max) },
@ -197,7 +197,7 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
{ "UNSET", Function("UNSET", "AQL_UNSET", "a,sl|+", true, true, false, true, true, &Functions::Unset) },
{ "KEEP", Function("KEEP", "AQL_KEEP", "a,sl|+", true, true, false, true, true, &Functions::Keep) },
{ "TRANSLATE", Function("TRANSLATE", "AQL_TRANSLATE", ".,a|.", true, true, false, true, true) },
{ "ZIP", Function("ZIP", "AQL_ZIP", "l,l", true, true, false, true, true) },
{ "ZIP", Function("ZIP", "AQL_ZIP", "l,l", true, true, false, true, true, &Functions::Zip) },
// geo functions
{ "NEAR", Function("NEAR", "AQL_NEAR", "h,n,n|nz,s", true, false, true, false, true, &Functions::Near, NotInCluster) },
@ -270,7 +270,7 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
{ "NOT_NULL", Function("NOT_NULL", "AQL_NOT_NULL", ".|+", true, true, false, true, true) },
{ "FIRST_LIST", Function("FIRST_LIST", "AQL_FIRST_LIST", ".|+", true, true, false, true, true) },
{ "FIRST_DOCUMENT", Function("FIRST_DOCUMENT", "AQL_FIRST_DOCUMENT", ".|+", true, true, false, true, true) },
{ "PARSE_IDENTIFIER", Function("PARSE_IDENTIFIER", "AQL_PARSE_IDENTIFIER", ".", true, true, false, true, true) },
{ "PARSE_IDENTIFIER", Function("PARSE_IDENTIFIER", "AQL_PARSE_IDENTIFIER", ".", true, true, false, true, true, &Functions::ParseIdentifier) },
{ "CURRENT_USER", Function("CURRENT_USER", "AQL_CURRENT_USER", "", false, false, false, false, true) },
{ "CURRENT_DATABASE", Function("CURRENT_DATABASE", "AQL_CURRENT_DATABASE", "", false, false, false, false, true) }
};

View File

@ -2416,6 +2416,179 @@ AqlValue Functions::Within (triagens::aql::Query* query,
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, array.steal()));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief internal recursive flatten helper
////////////////////////////////////////////////////////////////////////////////
static void FlattenList (Json array, size_t maxDepth, size_t curDepth, Json& result) {
size_t elementCount = array.size();
for (size_t i = 0; i < elementCount; ++i) {
Json tmp = array.at(i);
if (tmp.isArray() && curDepth < maxDepth) {
FlattenList(tmp, maxDepth, curDepth + 1, result);
}
else {
// Transfer the content of tmp into the result
result.transfer(tmp.json());
}
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief function FLATTEN
////////////////////////////////////////////////////////////////////////////////
AqlValue Functions::Flatten (triagens::aql::Query* query,
triagens::arango::AqlTransaction* trx,
FunctionParameters const& parameters) {
size_t const n = parameters.size();
if (n == 0 || n > 2) {
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "FLATTEN", (int) 1, (int) 2);
}
Json listJson = ExtractFunctionParameter(trx, parameters, 0, false);
if (! listJson.isArray()) {
RegisterWarning(query, "FLATTEN", TRI_ERROR_QUERY_ARRAY_EXPECTED);
return AqlValue(new Json(Json::Null));
}
size_t maxDepth = 1;
if (n == 2) {
Json maxDepthJson = ExtractFunctionParameter(trx, parameters, 1, false);
bool isValid = true;
double tmpMaxDepth = ValueToNumber(maxDepthJson.json(), isValid);
if (! isValid || tmpMaxDepth < 1) {
maxDepth = 1;
}
else {
maxDepth = static_cast<size_t>(tmpMaxDepth);
}
}
Json result(Json::Array);
FlattenList(listJson.copy(), maxDepth, 0, result);
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, result.steal()));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief function ZIP
////////////////////////////////////////////////////////////////////////////////
AqlValue Functions::Zip (triagens::aql::Query* query,
triagens::arango::AqlTransaction* trx,
FunctionParameters const& parameters) {
if (parameters.size() != 2) {
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "ZIP", (int) 2, (int) 2);
}
Json keysJson = ExtractFunctionParameter(trx, parameters, 0, false);
Json valuesJson = ExtractFunctionParameter(trx, parameters, 1, false);
if (! keysJson.isArray() ||
! valuesJson.isArray() ||
keysJson.size() != valuesJson.size()) {
RegisterWarning(query, "ZIP", TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return AqlValue(new Json(Json::Null));
}
size_t const n = keysJson.size();
Json result(Json::Object, n);
// Buffer will temporarily hold the keys
triagens::basics::StringBuffer buffer(TRI_UNKNOWN_MEM_ZONE, 24);
for (size_t i = 0; i < n; ++i) {
buffer.reset();
AppendAsString(buffer, keysJson.at(i).json());
result.set(buffer.c_str(), valuesJson.at(i).copy().steal());
}
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, result.steal()));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief function PARSE_IDENTIFIER
////////////////////////////////////////////////////////////////////////////////
AqlValue Functions::ParseIdentifier (triagens::aql::Query* query,
triagens::arango::AqlTransaction* trx,
FunctionParameters const& parameters) {
if (parameters.size() != 1) {
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "PARSE_IDENTIFIER", (int) 1, (int) 1);
}
Json value = ExtractFunctionParameter(trx, parameters, 0, false);
if (value.isObject() && value.has("_id")) {
value = value.get("_id");
}
if (value.isString()) {
std::string identifier(value.json()->_value._string.data, value.json()->_value._string.length - 1);
std::vector<std::string> parts = triagens::basics::StringUtils::split(identifier, "/");
if (parts.size() == 2) {
Json result(Json::Object, 2);
result.set("collection", Json(parts[0]));
result.set("key", Json(parts[1]));
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, result.steal()));
}
}
RegisterWarning(query, "PARSE_IDENTIFIER", TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return AqlValue(new Json(Json::Null));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief function Minus
////////////////////////////////////////////////////////////////////////////////
AqlValue Functions::Minus (triagens::aql::Query* query,
triagens::arango::AqlTransaction* trx,
FunctionParameters const& parameters) {
size_t const n = parameters.size();
if (n < 2) {
// The max number is arbitrary
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "MINUS", (int) 2, (int) 99999);
}
Json baseArray = ExtractFunctionParameter(trx, parameters, 0, false);
std::unordered_map<std::string, size_t> contains;
contains.reserve(n);
if (! baseArray.isArray()) {
RegisterWarning(query, "MINUS", TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return AqlValue(new Json(Json::Null));
}
// Fill the original map
for (size_t i = 0; i < baseArray.size(); ++i) {
contains.emplace(baseArray.at(i).toString(), i);
}
// Iterate through all following parameters and delete found elements from the map
for (size_t k = 1; k < n; ++k) {
Json nextArray = ExtractFunctionParameter(trx, parameters, k, false);
if (! nextArray.isArray()) {
RegisterWarning(query, "MINUS", TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
return AqlValue(new Json(Json::Null));
}
for (size_t j = 0; j < nextArray.size(); ++j) {
std::string search = nextArray.at(j).toString();
auto find = contains.find(search);
if (find != contains.end()) {
contains.erase(find);
}
}
}
// We ommit the normalize part from js, cannot occur here
Json result(Json::Array, contains.size());
for (auto& it : contains) {
result.transfer(baseArray.at(it.second).json());
}
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, result.steal()));
}
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------

View File

@ -79,40 +79,44 @@ namespace triagens {
// --SECTION-- AQL function bindings
// -----------------------------------------------------------------------------
static AqlValue IsNull (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsBool (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsNumber (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsString (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsArray (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsObject (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue ToNumber (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue ToString (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue ToBool (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue ToArray (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Length (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Concat (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Like (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Passthru (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Unset (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Keep (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Merge (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Has (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Attributes (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Values (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Min (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Max (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Sum (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Average (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Md5 (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Sha1 (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Unique (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue SortedUnique (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Union (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue UnionDistinct (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Intersection (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Neighbors (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Near (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Within (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsNull (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsBool (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsNumber (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsString (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsArray (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue IsObject (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue ToNumber (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue ToString (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue ToBool (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue ToArray (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Length (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Concat (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Like (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Passthru (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Unset (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Keep (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Merge (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Has (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Attributes (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Values (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Min (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Max (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Sum (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Average (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Md5 (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Sha1 (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Unique (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue SortedUnique (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Union (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue UnionDistinct (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Intersection (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Neighbors (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Near (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Within (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Flatten (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Zip (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue ParseIdentifier (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
static AqlValue Minus (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
};
}

View File

@ -49,27 +49,41 @@ function ahuacatlMiscFunctionsTestSuite () {
testParseIdentifier : function () {
var actual;
var buildQuery = function (nr, input) {
switch (nr) {
case 0:
return `RETURN PARSE_IDENTIFIER(${input})`;
case 1:
return `RETURN NOOPT(PARSE_IDENTIFIER(${input}))`;
case 2:
return `RETURN NOOPT(V8(PARSE_IDENTIFIER(${input})))`;
default:
assertTrue(false, "Undefined state");
}
};
actual = getQueryResults("RETURN PARSE_IDENTIFIER('foo/bar')");
assertEqual([ { collection: 'foo', key: 'bar' } ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER('this-is-a-collection-name/and-this-is-an-id')");
assertEqual([ { collection: 'this-is-a-collection-name', key: 'and-this-is-an-id' } ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER('MY_COLLECTION/MY_DOC')");
assertEqual([ { collection: 'MY_COLLECTION', key: 'MY_DOC' } ], actual);
for (var i = 0; i < 3; ++i) {
actual = getQueryResults(buildQuery(i, "'foo/bar'"));
assertEqual([ { collection: 'foo', key: 'bar' } ], actual);
actual = getQueryResults(buildQuery(i, "'this-is-a-collection-name/and-this-is-an-id'"));
assertEqual([ { collection: 'this-is-a-collection-name', key: 'and-this-is-an-id' } ], actual);
actual = getQueryResults(buildQuery(i, "'MY_COLLECTION/MY_DOC'"));
assertEqual([ { collection: 'MY_COLLECTION', key: 'MY_DOC' } ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER('_users/AbC')");
assertEqual([ { collection: '_users', key: 'AbC' } ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER({ _id: 'foo/bar', value: 'baz' })");
assertEqual([ { collection: 'foo', key: 'bar' } ], actual);
actual = getQueryResults(buildQuery(i, "'_users/AbC'"));
assertEqual([ { collection: '_users', key: 'AbC' } ], actual);
actual = getQueryResults(buildQuery(i, "{ _id: 'foo/bar', value: 'baz' }"));
assertEqual([ { collection: 'foo', key: 'bar' } ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER({ ignore: true, _id: '_system/VALUE', value: 'baz' })");
assertEqual([ { collection: '_system', key: 'VALUE' } ], actual);
actual = getQueryResults(buildQuery(i, "{ ignore: true, _id: '_system/VALUE', value: 'baz' }"));
assertEqual([ { collection: '_system', key: 'VALUE' } ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER({ value: 123, _id: 'Some-Odd-Collection/THIS_IS_THE_KEY' })");
assertEqual([ { collection: 'Some-Odd-Collection', key: 'THIS_IS_THE_KEY' } ], actual);
actual = getQueryResults(buildQuery(i ,"{ value: 123, _id: 'Some-Odd-Collection/THIS_IS_THE_KEY' }"));
assertEqual([ { collection: 'Some-Odd-Collection', key: 'THIS_IS_THE_KEY' } ], actual);
}
},
////////////////////////////////////////////////////////////////////////////////
@ -85,26 +99,40 @@ function ahuacatlMiscFunctionsTestSuite () {
cx.save({ "_key" : "so-this-is-it", "title" : "nada", "value" : 123 });
var expected, actual;
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults("RETURN PARSE_IDENTIFIER(DOCUMENT(CONCAT(@cn, '/', @key)))", { cn: cn, key: "foobar" });
assertEqual(expected, actual);
var buildQuery = function (nr, input) {
switch (nr) {
case 0:
return `RETURN PARSE_IDENTIFIER(${input})`;
case 1:
return `RETURN NOOPT(PARSE_IDENTIFIER(${input}))`;
case 2:
return `RETURN NOOPT(V8(PARSE_IDENTIFIER(${input})))`;
default:
assertTrue(false, "Undefined state");
}
};
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults("RETURN PARSE_IDENTIFIER(DOCUMENT(CONCAT(@cn, '/', @key)))", { cn: cn, key: "foobar" });
assertEqual(expected, actual);
for (var i = 0; i < 3; ++i) {
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults(buildQuery(i, "DOCUMENT(CONCAT(@cn, '/', @key))"), { cn: cn, key: "foobar" });
assertEqual(expected, actual);
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults("RETURN PARSE_IDENTIFIER(DOCUMENT(CONCAT(@cn, '/', 'foobar')))", { cn: cn });
assertEqual(expected, actual);
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults(buildQuery(i, "DOCUMENT(CONCAT(@cn, '/', @key))"), { cn: cn, key: "foobar" });
assertEqual(expected, actual);
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults("RETURN PARSE_IDENTIFIER(DOCUMENT([ @key ])[0])", { key: "UnitTestsAhuacatlFunctions/foobar" });
assertEqual(expected, actual);
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults(buildQuery(i, "DOCUMENT(CONCAT(@cn, '/', 'foobar'))"), { cn: cn });
assertEqual(expected, actual);
expected = [ { collection: cn, key: "so-this-is-it" } ];
actual = getQueryResults("RETURN PARSE_IDENTIFIER(DOCUMENT([ 'UnitTestsAhuacatlFunctions/so-this-is-it' ])[0])");
assertEqual(expected, actual);
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults(buildQuery(i, "DOCUMENT([ @key ])[0]"), { key: "UnitTestsAhuacatlFunctions/foobar" });
assertEqual(expected, actual);
expected = [ { collection: cn, key: "so-this-is-it" } ];
actual = getQueryResults(buildQuery(i, "DOCUMENT([ 'UnitTestsAhuacatlFunctions/so-this-is-it' ])[0]"));
assertEqual(expected, actual);
}
internal.db._drop(cn);
},
@ -114,17 +142,32 @@ function ahuacatlMiscFunctionsTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testParseIdentifierInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN PARSE_IDENTIFIER()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN PARSE_IDENTIFIER('foo', 'bar')");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER(null)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER(false)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER(3)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER(\"foo\")");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER('foo bar')");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER('foo/bar/baz')");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER([ ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER({ })");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER({ foo: 'bar' })");
var buildQuery = function (nr, input) {
switch (nr) {
case 0:
return `RETURN PARSE_IDENTIFIER(${input})`;
case 1:
return `RETURN NOOPT(PARSE_IDENTIFIER(${input}))`;
case 2:
return `RETURN NOOPT(V8(PARSE_IDENTIFIER(${input})))`;
default:
assertTrue(false, "Undefined state");
}
};
for (var i = 0; i < 3; ++i) {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, buildQuery(i, ""));
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, buildQuery(i, "'foo', 'bar'"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "null"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "false"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "3"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "\"foo\""));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "'foo bar'"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "'foo/bar/baz'"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "{ }"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "{ foo: 'bar' }"));
}
},
////////////////////////////////////////////////////////////////////////////////

View File

@ -1558,9 +1558,17 @@ function ahuacatlFunctionsTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testMinus1 : function () {
var expected = [ [ 'b', 'd' ] ];
var expected = [ 'b', 'd' ].sort();
// Opt
var actual = getQueryResults("RETURN MINUS([ 'a', 'b', 'c', 'd' ], [ 'c' ], [ 'a', 'c', 'e' ])");
assertEqual(expected, actual);
assertEqual(expected, actual[0].sort());
// No opt / No v8
actual = getQueryResults("RETURN NOOPT(MINUS([ 'a', 'b', 'c', 'd' ], [ 'c' ], [ 'a', 'c', 'e' ]))");
assertEqual(expected, actual[0].sort());
// No opt / v8
actual = getQueryResults("RETURN NOOPT(V8(MINUS([ 'a', 'b', 'c', 'd' ], [ 'c' ], [ 'a', 'c', 'e' ])))");
assertEqual(expected, actual[0].sort());
},
////////////////////////////////////////////////////////////////////////////////
@ -1568,9 +1576,18 @@ function ahuacatlFunctionsTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testMinus2 : function () {
var expected = [ [ 'a', 'b' ] ];
var expected = [ 'a', 'b' ].sort();
// Opt
var actual = getQueryResults("RETURN MINUS([ 'a', 'b', 'c' ], [ 'c', 'd', 'e' ])");
assertEqual(expected, actual);
assertEqual(expected, actual[0].sort());
// No Opt / No v8
actual = getQueryResults("RETURN NOOPT(MINUS([ 'a', 'b', 'c' ], [ 'c', 'd', 'e' ]))");
assertEqual(expected, actual[0].sort());
// No Opt / v8
actual = getQueryResults("RETURN NOOPT(V8(MINUS([ 'a', 'b', 'c' ], [ 'c', 'd', 'e' ])))");
assertEqual(expected, actual[0].sort());
},
////////////////////////////////////////////////////////////////////////////////
@ -1578,9 +1595,19 @@ function ahuacatlFunctionsTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testMinus3 : function () {
var expected = [ [ 'a', 'b', 'c' ] ];
var expected = [ 'a', 'b', 'c' ].sort();
// Opt
var actual = getQueryResults("RETURN MINUS([ 'a', 'b', 'c' ], [ 1, 2, 3 ])");
assertEqual(expected, actual);
assertEqual(expected, actual[0].sort());
// No Opt / No v8
actual = getQueryResults("RETURN NOOPT(MINUS([ 'a', 'b', 'c' ], [ 1, 2, 3 ]))");
assertEqual(expected, actual[0].sort());
// No Opt / v8
actual = getQueryResults("RETURN NOOPT(V8(MINUS([ 'a', 'b', 'c' ], [ 1, 2, 3 ])))");
assertEqual(expected, actual[0].sort());
},
////////////////////////////////////////////////////////////////////////////////
@ -1588,9 +1615,19 @@ function ahuacatlFunctionsTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testMinus4 : function () {
var expected = [ [ 'a', 'b', 'c' ] ];
var expected = [ 'a', 'b', 'c' ].sort();
// Opt
var actual = getQueryResults("RETURN MINUS([ 'a', 'b', 'c' ], [ 1, 2, 3 ], [ 1, 2, 3 ])");
assertEqual(expected, actual);
assertEqual(expected, actual[0].sort());
// No Opt / No v8
actual = getQueryResults("RETURN NOOPT(MINUS([ 'a', 'b', 'c' ], [ 1, 2, 3 ], [ 1, 2, 3 ]))");
assertEqual(expected, actual[0].sort());
// No Opt / v8
actual = getQueryResults("RETURN NOOPT(V8(MINUS([ 'a', 'b', 'c' ], [ 1, 2, 3 ], [ 1, 2, 3 ])))");
assertEqual(expected, actual[0].sort());
},
////////////////////////////////////////////////////////////////////////////////
@ -1599,8 +1636,18 @@ function ahuacatlFunctionsTestSuite () {
testMinus5 : function () {
var expected = [ [ ] ];
// Opt
var actual = getQueryResults("RETURN MINUS([ 2 ], [ 'a', 'b', 'c' ], [ 1, 2, 3 ], [ 1, 2, 3 ])");
assertEqual(expected, actual);
// No Opt / No v8
actual = getQueryResults("RETURN NOOPT(MINUS([ 2 ], [ 'a', 'b', 'c' ], [ 1, 2, 3 ], [ 1, 2, 3 ]))");
assertEqual(expected, actual);
// No Opt / v8
actual = getQueryResults("RETURN NOOPT(V8(MINUS([ 2 ], [ 'a', 'b', 'c' ], [ 1, 2, 3 ], [ 1, 2, 3 ])))");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -1609,8 +1656,18 @@ function ahuacatlFunctionsTestSuite () {
testMinus6 : function () {
var expected = [ [ ] ];
// Opt
var actual = getQueryResults("RETURN MINUS([ ], [ 'a', 'b', 'c' ], [ 1, 2, 3 ], [ 1, 2, 3 ])");
assertEqual(expected, actual);
// No Opt / No v8
actual = getQueryResults("RETURN NOOPT(MINUS([ ], [ 'a', 'b', 'c' ], [ 1, 2, 3 ], [ 1, 2, 3 ]))");
assertEqual(expected, actual);
// No Opt / v8
actual = getQueryResults("RETURN NOOPT(V8(MINUS([ ], [ 'a', 'b', 'c' ], [ 1, 2, 3 ], [ 1, 2, 3 ])))");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -1818,16 +1875,41 @@ function ahuacatlFunctionsTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testFlattenInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN FLATTEN()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN FLATTEN([ ], 1, 1)");
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN FLATTEN(1)");
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN FLATTEN(null)");
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN FLATTEN(false)");
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN FLATTEN(1)");
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN FLATTEN('foo')");
assertEqual([ [ ] ], getQueryResults("RETURN FLATTEN([ ], 'foo')"));
assertEqual([ [ ] ], getQueryResults("RETURN FLATTEN([ ], [ ])"));
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN FLATTEN({ })");
var buildQuery = function (nr, input) {
switch (nr) {
case 0:
// Optimized
return `RETURN FLATTEN(${input})`;
case 1:
// No opt / No v8
return `RETURN NOOPT(FLATTEN(${input}))`;
case 2:
// No opt / v8
return `RETURN NOOPT(V8(FLATTEN(${input})))`;
default:
assertTrue(false, "Unreachable state");
}
};
for (var i = 0; i < 3; ++i) {
var q = buildQuery(i, "");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, q);
q = buildQuery(i, "[], 1, 1");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, q);
q = buildQuery(i, "1");
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, q);
q = buildQuery(i, "null");
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, q);
q = buildQuery(i, "false");
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, q);
q = buildQuery(i, "'foo'");
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, q);
q = buildQuery(i, "[ ], 'foo'");
assertEqual([ [ ] ], getQueryResults(q), q);
q = buildQuery(i, "[ ], [ ]");
assertEqual([ [ ] ], getQueryResults(q), q);
q = buildQuery(i, "{ }");
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, q);
}
},
////////////////////////////////////////////////////////////////////////////////
@ -1836,11 +1918,26 @@ function ahuacatlFunctionsTestSuite () {
testFlatten1 : function () {
var input = [ [ 2, 4, 5 ], [ 1, 2, 3 ], [ ], [ "foo", "bar" ] ];
// Optimized
var actual = getQueryResults("RETURN FLATTEN(@value)", { value: input });
assertEqual([ [ 2, 4, 5, 1, 2, 3, "foo", "bar" ] ], actual);
actual = getQueryResults("RETURN FLATTEN(@value, 1)", { value: input });
assertEqual([ [ 2, 4, 5, 1, 2, 3, "foo", "bar" ] ], actual);
// No opt / No v8
actual = getQueryResults("RETURN NOOPT(FLATTEN(@value))", { value: input });
assertEqual([ [ 2, 4, 5, 1, 2, 3, "foo", "bar" ] ], actual);
actual = getQueryResults("RETURN NOOPT(FLATTEN(@value, 1))", { value: input });
assertEqual([ [ 2, 4, 5, 1, 2, 3, "foo", "bar" ] ], actual);
// No opt / v8
actual = getQueryResults("RETURN NOOPT(V8(FLATTEN(@value)))", { value: input });
assertEqual([ [ 2, 4, 5, 1, 2, 3, "foo", "bar" ] ], actual);
actual = getQueryResults("RETURN NOOPT(V8(FLATTEN(@value, 1)))", { value: input });
assertEqual([ [ 2, 4, 5, 1, 2, 3, "foo", "bar" ] ], actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -1849,6 +1946,7 @@ function ahuacatlFunctionsTestSuite () {
testFlatten2 : function () {
var input = [ [ 1, 1, 2, 2 ], [ 1, 1, 2, 2 ], [ null, null ], [ [ 1, 2 ], [ 3, 4 ] ] ];
// Optimized
var actual = getQueryResults("RETURN FLATTEN(@value)", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, null, null, [ 1, 2 ], [ 3, 4 ] ] ], actual);
@ -1857,6 +1955,26 @@ function ahuacatlFunctionsTestSuite () {
actual = getQueryResults("RETURN FLATTEN(@value, 2)", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, null, null, 1, 2, 3, 4 ] ], actual);
// No opt / No v8
actual = getQueryResults("RETURN NOOPT(FLATTEN(@value))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, null, null, [ 1, 2 ], [ 3, 4 ] ] ], actual);
actual = getQueryResults("RETURN NOOPT(FLATTEN(@value, 1))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, null, null, [ 1, 2 ], [ 3, 4 ] ] ], actual);
actual = getQueryResults("RETURN NOOPT(FLATTEN(@value, 2))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, null, null, 1, 2, 3, 4 ] ], actual);
// No opt / v8
actual = getQueryResults("RETURN NOOPT(V8(FLATTEN(@value)))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, null, null, [ 1, 2 ], [ 3, 4 ] ] ], actual);
actual = getQueryResults("RETURN NOOPT(V8(FLATTEN(@value, 1)))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, null, null, [ 1, 2 ], [ 3, 4 ] ] ], actual);
actual = getQueryResults("RETURN NOOPT(V8(FLATTEN(@value, 2)))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, null, null, 1, 2, 3, 4 ] ], actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -1865,6 +1983,8 @@ function ahuacatlFunctionsTestSuite () {
testFlatten3 : function () {
var input = [ [ 1, 1, 2, 2 ], [ 1, 1, 2, 2 ], [ [ 1, 2 ], [ 3, 4 ], [ [ 5, 6 ], [ 7, 8 ] ], [ 9, 10, [ 11, 12 ] ] ] ];
// Optimized
var actual = getQueryResults("RETURN FLATTEN(@value, 1)", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, [ 1, 2 ], [ 3, 4 ], [ [ 5, 6 ], [ 7, 8 ] ], [ 9, 10, [ 11, 12 ] ] ] ], actual);
@ -1873,6 +1993,27 @@ function ahuacatlFunctionsTestSuite () {
actual = getQueryResults("RETURN FLATTEN(@value, 3)", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ] ], actual);
// No opt / No v8
actual = getQueryResults("RETURN NOOPT(FLATTEN(@value, 1))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, [ 1, 2 ], [ 3, 4 ], [ [ 5, 6 ], [ 7, 8 ] ], [ 9, 10, [ 11, 12 ] ] ] ], actual);
actual = getQueryResults("RETURN NOOPT(FLATTEN(@value, 2))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, 3, 4, [ 5, 6 ], [ 7, 8 ], 9, 10, [ 11, 12 ] ] ], actual);
actual = getQueryResults("RETURN NOOPT(FLATTEN(@value, 3))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ] ], actual);
// No opt / v8
actual = getQueryResults("RETURN NOOPT(V8(FLATTEN(@value, 1)))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, [ 1, 2 ], [ 3, 4 ], [ [ 5, 6 ], [ 7, 8 ] ], [ 9, 10, [ 11, 12 ] ] ] ], actual);
actual = getQueryResults("RETURN NOOPT(V8(FLATTEN(@value, 2)))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, 3, 4, [ 5, 6 ], [ 7, 8 ], 9, 10, [ 11, 12 ] ] ], actual);
actual = getQueryResults("RETURN NOOPT(V8(FLATTEN(@value, 3)))", { value: input });
assertEqual([ [ 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ] ], actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -1881,113 +2022,52 @@ function ahuacatlFunctionsTestSuite () {
testFlatten4 : function () {
var input = [ 1, [ 2, [ 3, [ 4, [ 5, [ 6, [ 7, [ 8, [ 9 ] ] ] ] ] ] ] ] ];
var actual = getQueryResults("RETURN FLATTEN(@value, 1)", { value: input });
assertEqual([ [ 1, 2, [ 3, [ 4, [ 5, [ 6, [ 7, [ 8, [ 9 ] ] ] ] ] ] ] ] ], actual);
actual = getQueryResults("RETURN FLATTEN(@value, 2)", { value: input });
assertEqual([ [ 1, 2, 3, [ 4, [ 5, [ 6, [ 7, [ 8, [ 9 ] ] ] ] ] ] ] ], actual);
actual = getQueryResults("RETURN FLATTEN(@value, 3)", { value: input });
assertEqual([ [ 1, 2, 3, 4, [ 5, [ 6, [ 7, [ 8, [ 9 ] ] ] ] ] ] ], actual);
actual = getQueryResults("RETURN FLATTEN(@value, 4)", { value: input });
assertEqual([ [ 1, 2, 3, 4, 5, [ 6, [ 7, [ 8, [ 9 ] ] ] ] ] ], actual);
actual = getQueryResults("RETURN FLATTEN(@value, 5)", { value: input });
assertEqual([ [ 1, 2, 3, 4, 5, 6, [ 7, [ 8, [ 9 ] ] ] ] ], actual);
actual = getQueryResults("RETURN FLATTEN(@value, 6)", { value: input });
assertEqual([ [ 1, 2, 3, 4, 5, 6, 7, [ 8, [ 9 ] ] ] ], actual);
actual = getQueryResults("RETURN FLATTEN(@value, 7)", { value: input });
assertEqual([ [ 1, 2, 3, 4, 5, 6, 7, 8, [ 9 ] ] ], actual);
actual = getQueryResults("RETURN FLATTEN(@value, 8)", { value: input });
assertEqual([ [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ], actual);
},
var buildQuery = function (nr, input) {
switch (nr) {
case 0:
return `RETURN FLATTEN(@value, ${input})`;
case 1:
return `RETURN NOOPT(FLATTEN(@value, ${input}))`;
case 2:
return `RETURN NOOPT(V8(FLATTEN(@value, ${input})))`;
default:
assertTrue(false, "Undefined state");
}
};
////////////////////////////////////////////////////////////////////////////////
/// @brief test parse identifier function
////////////////////////////////////////////////////////////////////////////////
testParseIdentifier : function () {
var actual;
for (var i = 0; i < 3; ++i) {
var q = buildQuery(i, 1);
var actual = getQueryResults(q, { value: input });
assertEqual([ [ 1, 2, [ 3, [ 4, [ 5, [ 6, [ 7, [ 8, [ 9 ] ] ] ] ] ] ] ] ], actual, q);
actual = getQueryResults("RETURN PARSE_IDENTIFIER('foo/bar')");
assertEqual([ { collection: 'foo', key: 'bar' } ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER('this-is-a-collection-name/and-this-is-an-id')");
assertEqual([ { collection: 'this-is-a-collection-name', key: 'and-this-is-an-id' } ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER('MY_COLLECTION/MY_DOC')");
assertEqual([ { collection: 'MY_COLLECTION', key: 'MY_DOC' } ], actual);
q = buildQuery(i, 2);
actual = getQueryResults(q, { value: input });
assertEqual([ [ 1, 2, 3, [ 4, [ 5, [ 6, [ 7, [ 8, [ 9 ] ] ] ] ] ] ] ], actual, q);
actual = getQueryResults("RETURN PARSE_IDENTIFIER('_users/AbC')");
assertEqual([ { collection: '_users', key: 'AbC' } ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER({ _id: 'foo/bar', value: 'baz' })");
assertEqual([ { collection: 'foo', key: 'bar' } ], actual);
q = buildQuery(i, 3);
actual = getQueryResults(q, { value: input });
assertEqual([ [ 1, 2, 3, 4, [ 5, [ 6, [ 7, [ 8, [ 9 ] ] ] ] ] ] ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER({ ignore: true, _id: '_system/VALUE', value: 'baz' })");
assertEqual([ { collection: '_system', key: 'VALUE' } ], actual);
q = buildQuery(i, 4);
actual = getQueryResults(q, { value: input });
assertEqual([ [ 1, 2, 3, 4, 5, [ 6, [ 7, [ 8, [ 9 ] ] ] ] ] ], actual);
actual = getQueryResults("RETURN PARSE_IDENTIFIER({ value: 123, _id: 'Some-Odd-Collection/THIS_IS_THE_KEY' })");
assertEqual([ { collection: 'Some-Odd-Collection', key: 'THIS_IS_THE_KEY' } ], actual);
},
q = buildQuery(i, 5);
actual = getQueryResults(q, { value: input });
assertEqual([ [ 1, 2, 3, 4, 5, 6, [ 7, [ 8, [ 9 ] ] ] ] ], actual);
////////////////////////////////////////////////////////////////////////////////
/// @brief test parse identifier function
////////////////////////////////////////////////////////////////////////////////
testParseIdentifierCollection : function () {
var cn = "UnitTestsAhuacatlFunctions";
q = buildQuery(i, 6);
actual = getQueryResults(q, { value: input });
assertEqual([ [ 1, 2, 3, 4, 5, 6, 7, [ 8, [ 9 ] ] ] ], actual);
internal.db._drop(cn);
var cx = internal.db._create(cn);
cx.save({ "title" : "123", "value" : 456, "_key" : "foobar" });
cx.save({ "_key" : "so-this-is-it", "title" : "nada", "value" : 123 });
q = buildQuery(i, 7);
actual = getQueryResults(q, { value: input });
assertEqual([ [ 1, 2, 3, 4, 5, 6, 7, 8, [ 9 ] ] ], actual);
var expected, actual;
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults("RETURN PARSE_IDENTIFIER(DOCUMENT(CONCAT(@cn, '/', @key)))", { cn: cn, key: "foobar" });
assertEqual(expected, actual);
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults("RETURN PARSE_IDENTIFIER(DOCUMENT(CONCAT(@cn, '/', @key)))", { cn: cn, key: "foobar" });
assertEqual(expected, actual);
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults("RETURN PARSE_IDENTIFIER(DOCUMENT(CONCAT(@cn, '/', 'foobar')))", { cn: cn });
assertEqual(expected, actual);
expected = [ { collection: cn, key: "foobar" } ];
actual = getQueryResults("RETURN PARSE_IDENTIFIER(DOCUMENT([ @key ])[0])", { key: "UnitTestsAhuacatlFunctions/foobar" });
assertEqual(expected, actual);
expected = [ { collection: cn, key: "so-this-is-it" } ];
actual = getQueryResults("RETURN PARSE_IDENTIFIER(DOCUMENT([ 'UnitTestsAhuacatlFunctions/so-this-is-it' ])[0])");
assertEqual(expected, actual);
internal.db._drop(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test parse identifier function
////////////////////////////////////////////////////////////////////////////////
testParseIdentifierInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN PARSE_IDENTIFIER()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN PARSE_IDENTIFIER('foo', 'bar')");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER(null)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER(false)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER(3)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER(\"foo\")");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER('foo bar')");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER('foo/bar/baz')");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER([ ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER({ })");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN PARSE_IDENTIFIER({ foo: 'bar' })");
q = buildQuery(i, 8);
actual = getQueryResults(q, { value: input });
assertEqual([ [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ], actual);
}
},
////////////////////////////////////////////////////////////////////////////////
@ -2649,8 +2729,15 @@ function ahuacatlFunctionsTestSuite () {
];
values.forEach(function (value) {
// Opt
var actual = getQueryResults("RETURN ZIP(" + JSON.stringify(value[1]) + ", " + JSON.stringify(value[2]) + ")");
assertEqual(value[0], actual[0], value);
// No opt / No v8
actual = getQueryResults("RETURN NOOPT(ZIP(" + JSON.stringify(value[1]) + ", " + JSON.stringify(value[2]) + "))");
assertEqual(value[0], actual[0], value);
// No opt / v8
actual = getQueryResults("RETURN NOOPT(V8(ZIP(" + JSON.stringify(value[1]) + ", " + JSON.stringify(value[2]) + ")))");
assertEqual(value[0], actual[0], value);
});
},
@ -2659,28 +2746,42 @@ function ahuacatlFunctionsTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testZipInvalid : function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN ZIP()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN ZIP([ ])");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN ZIP([ ], [ ], [ ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP([ ], null)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP([ ], false)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP([ ], true)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP([ ], 0)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP([ ], 1)");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP([ ], \"\")");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP([ ], { })");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP(null, [ ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP(false, [ ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP(true, [ ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP(0, [ ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP(1, [ ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP(\"\", [ ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP({ }, [ ])");
var buildQuery = function (nr, input) {
switch (nr) {
case 0:
return `RETURN ZIP(${input})`;
case 1:
return `RETURN NOOPT(ZIP(${input}))`;
case 2:
return `RETURN NOOPT(V8(ZIP(${input})))`;
default:
assertTrue(false, "Undefined state");
}
};
for (var i = 0; i < 3; ++i) {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, buildQuery(i, ""));
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, buildQuery(i, "[ ]"));
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, buildQuery(i, "[ ], [ ], [ ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ ], null"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ ], false"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ ], true"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ ], 0"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ ], 1"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ ], \"\""));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ ], { }"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "null, [ ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "false, [ ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "true, [ ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "0, [ ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "1, [ ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "\"\", [ ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "{ }, [ ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP([ 1 ], [ ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP([ 1 ], [ 1, 2 ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN ZIP([ ], [ 1, 2 ])");
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ 1 ], [ ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ 1 ], [ 1, 2 ]"));
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, buildQuery(i, "[ ], [ 1, 2 ]"));
}
},
////////////////////////////////////////////////////////////////////////////////

View File

@ -81,7 +81,9 @@ LinenoiseShell::LinenoiseShell (std::string const& history,
Completer* completer)
: ShellBase(history, completer) {
COMPLETER = completer;
#ifndef _WIN32
linenoiseSetMultiLine(1);
#endif
linenoiseSetCompletionCallback(LinenoiseCompletionGenerator);
}