mirror of https://gitee.com/bigwinds/arangodb
Feature/cpp aql reverse (#4911)
This commit is contained in:
parent
7e53d3ed75
commit
a16d4b0109
|
@ -574,6 +574,10 @@ Alternatively, *search* and *replace* can be specified in a combined value.
|
|||
- **value** (string): a string
|
||||
- **mapping** (object): a lookup map with search strings as keys and replacement
|
||||
strings as values. Empty strings and *null* as values remove matches.
|
||||
Please note that no sequence of search strings can be warrantied by this;
|
||||
Means, if you have overlapping search results, one time the first may win,
|
||||
another time the second. If you need to ensure the precedence of the sequence
|
||||
choose the array based invocation method.
|
||||
- **limit** (number, *optional*): cap the number of replacements to this value
|
||||
- returns **substitutedString** (string): a new string with matches replaced
|
||||
(or removed)
|
||||
|
|
|
@ -707,7 +707,7 @@ Building will fail if resources aren't cleaned.
|
|||
However, if you intend a set of OUTPUT and RUN to demonstrate interactively and share generated *ids*, you have to use an alphabetical
|
||||
sortable naming scheme so they're executed in sequence. Using `<modulename>_<sequencenumber>[a|b|c|d]_thisDoesThat` seems to be a good scheme.
|
||||
|
||||
- OUTPUT is intended to create samples that the users can cut'n'paste into their arangosh. Its used for javascript api documentation.
|
||||
- EXAMPLE_ARANGOSH_OUTPUT is intended to create samples that the users can cut'n'paste into their arangosh. Its used for javascript api documentation.
|
||||
* wrapped lines:
|
||||
Lines starting with a pipe (`/// |`) are joined together with the next following line.
|
||||
You have to use this if you want to execute loops, functions or commands which shouldn't be torn apart by the framework.
|
||||
|
@ -727,7 +727,7 @@ sortable naming scheme so they're executed in sequence. Using `<modulename>_<seq
|
|||
/// | someLongStatement()
|
||||
/// ~ // xpError(ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED)
|
||||
|
||||
- RUN is intended to be pasted into a unix shell with *cURL* to demonstrate how the REST-HTTP-APIs work.
|
||||
- EXAMPLE_ARANGOSH_RUN is intended to be pasted into a unix shell with *cURL* to demonstrate how the REST-HTTP-APIs work.
|
||||
The whole chunk of code is executed at once, and is expected **not to throw**.
|
||||
You should use **assert(condition)** to ensure the result is what you've expected.
|
||||
The *body* can be a string, or a javascript object which is then represented in JSON format.
|
||||
|
@ -739,14 +739,14 @@ sortable naming scheme so they're executed in sequence. Using `<modulename>_<seq
|
|||
* output the plain text to dump to the user: `logRawResponse(response);`
|
||||
* dump the reply to the errorlog for testing (will mark run as failed): `logErrorResponse(response);`
|
||||
|
||||
- AQL is intended to contain AQL queries that can be pasted into arangosh or the webinterfaces query editor.
|
||||
- EXAMPLE_AQL is intended to contain AQL queries that can be pasted into arangosh or the webinterfaces query editor.
|
||||
Usually this query references an example dataset generator in `js/common/modules/@arangodb/examples/examples.js`
|
||||
which the users can also invoke to generate the data in their installation.
|
||||
This sort of example consists of three parts:
|
||||
- @DATASET{datasetName} - the name of the dataset in the above mentioned `examples.js` to be instanciated before executing this query.
|
||||
- @EXPLAIN{TRUE|FALSE} - print execution plan of the AQL query. The default is `FALSE`.
|
||||
- A following AQL query which may either end at the end of the comment block, or at the optional next section:
|
||||
- @BV - verbatim object containing the bind parameters to be passed into the query. Will also be put into the generated snippet.
|
||||
- @DATASET{datasetName} - (optional) the name of the dataset in the above mentioned `examples.js` to be instanciated before executing this query.
|
||||
- @EXPLAIN{TRUE|FALSE} - (optional) print execution plan of the AQL query. The default is `FALSE`.
|
||||
- A following AQL query which may either end at the end of the comment block, or at the next section:
|
||||
- @BV - (optional) verbatim object containing the bind parameters to be passed into the query. Will also be put into the generated snippet.
|
||||
|
||||
Swagger integration
|
||||
===================
|
||||
|
|
|
@ -259,7 +259,7 @@ void AqlFunctionFeature::addStringFunctions() {
|
|||
add({"FIND_FIRST", ".,.|.,.", true, false, true, true, &Functions::FindFirst});
|
||||
add({"FIND_LAST", ".,.|.,.", true, false, true, true, &Functions::FindLast});
|
||||
add({"SPLIT", ".|.,.", true, false, true, true, &Functions::Split});
|
||||
add({"SUBSTITUTE", ".,.|.,.", true, false, true, true});
|
||||
add({"SUBSTITUTE", ".,.|.,.", true, false, true, true, &Functions::Substitute});
|
||||
add({"MD5", ".", true, false, true, true, &Functions::Md5});
|
||||
add({"SHA1", ".", true, false, true, true, &Functions::Sha1});
|
||||
add({"SHA512", ".", true, false, true, true, &Functions::Sha512});
|
||||
|
@ -356,7 +356,7 @@ void AqlFunctionFeature::addListFunctions() {
|
|||
add({"SLICE", ".,.|.", true, false, true, true,
|
||||
&Functions::Slice});
|
||||
add({"REVERSE", ".", true, false, true,
|
||||
true}); // note: REVERSE() can be applied on strings, too
|
||||
true, &Functions::Reverse});
|
||||
add({"FIRST", ".", true, false, true, true,
|
||||
&Functions::First});
|
||||
add({"LAST", ".", true, false, true, true,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -144,6 +144,8 @@ struct Functions {
|
|||
VPackFunctionParameters const&);
|
||||
static AqlValue FindLast(arangodb::aql::Query*, transaction::Methods*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Reverse(arangodb::aql::Query*, transaction::Methods*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue First(arangodb::aql::Query*, transaction::Methods*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Last(arangodb::aql::Query*, transaction::Methods*,
|
||||
|
@ -169,6 +171,9 @@ struct Functions {
|
|||
static AqlValue Substring(arangodb::aql::Query*,
|
||||
transaction::Methods*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Substitute(arangodb::aql::Query*,
|
||||
transaction::Methods*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Left(arangodb::aql::Query*,
|
||||
transaction::Methods*,
|
||||
VPackFunctionParameters const&);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
"ERROR_SHUTTING_DOWN" : { "code" : 30, "message" : "shutdown in progress" },
|
||||
"ERROR_ONLY_ENTERPRISE" : { "code" : 31, "message" : "only enterprise version" },
|
||||
"ERROR_RESOURCE_LIMIT" : { "code" : 32, "message" : "resource limit exceeded" },
|
||||
"ERROR_ARANGO_ICU_ERROR" : { "code" : 33, "message" : "icu error: %s" },
|
||||
"ERROR_HTTP_BAD_PARAMETER" : { "code" : 400, "message" : "bad parameter" },
|
||||
"ERROR_HTTP_UNAUTHORIZED" : { "code" : 401, "message" : "unauthorized" },
|
||||
"ERROR_HTTP_FORBIDDEN" : { "code" : 403, "message" : "forbidden" },
|
||||
|
|
|
@ -624,7 +624,7 @@ function ahuacatlCollectionCountTestSuite () {
|
|||
setUp : function () {
|
||||
db._drop(cn);
|
||||
c = db._create(cn, { numberOfShards: 4 });
|
||||
let docs = []
|
||||
let docs = [];
|
||||
|
||||
for (var i = 1; i <= 1000; ++i) {
|
||||
docs.push({ _key: "test" + i });
|
||||
|
|
|
@ -978,7 +978,12 @@ function ahuacatlStringFunctionsTestSuite () {
|
|||
[ 'the quick brown foxx jumped over the lazy dog', 'the quick brown foxx jumped over the lazy dog', 'the', 'a', 0 ],
|
||||
[ 'a quick brown foxx jumped over a lazy dog', 'the quick brown foxx jumped over the lazy dog', [ 'the' ], [ 'a' ] ],
|
||||
[ 'a quick brown foxx jumped over the lazy dog', 'the quick brown foxx jumped over the lazy dog', [ 'the' ], [ 'a' ], 1 ],
|
||||
[ 'the quick brown foxx jumped over the lazy dog', 'the quick brown foxx jumped over the lazy dog', 'thisIsNotThere', 'a'],
|
||||
[ 'the quick brown foxx jumped over the lazy dog', 'the quick brown foxx jumped over the lazy dog', {'thisIsNotThere': 'a'}],
|
||||
[ 'the quick brown foxx jumped over the lazy dog', 'the quick brown foxx jumped over the lazy dog', ['thisIsNotThere', 'thisIsAlsoNotThere'], ['a', 'b'], 0 ],
|
||||
[ 'mötör quick brown mötör jumped over the lazy dog', 'the quick brown foxx jumped over the lazy dog', [ 'over', 'the', 'foxx' ], 'mötör', 2 ],
|
||||
[ 'apfela', 'rabarbara', ['barbara', 'rabarbar'], ['petra', 'apfel']],
|
||||
[ 'rapetra', 'rabarbara', ['barbara', 'bar'], ['petra', 'foo']],
|
||||
[ 'AbCdEF', 'aBcDef', { a: 'A', B: 'b', c: 'C', D: 'd', e: 'E', f: 'F' } ],
|
||||
[ 'AbcDef', 'aBcDef', { a: 'A', B: 'b', c: 'C', D: 'd', e: 'E', f: 'F' }, 2 ],
|
||||
[ 'aBcDef', 'aBcDef', { a: 'A', B: 'b', c: 'C', D: 'd', e: 'E', f: 'F' }, 0 ],
|
||||
|
@ -999,7 +1004,10 @@ function ahuacatlStringFunctionsTestSuite () {
|
|||
for (i = 1; i < n; ++i) {
|
||||
args.push(JSON.stringify(value[i]));
|
||||
}
|
||||
assertEqual([ expected ], getQueryResults('RETURN SUBSTITUTE(' + args.join(', ') + ')'), value);
|
||||
var nuResults = getQueryResults('RETURN SUBSTITUTE(' + args.join(', ') + ')');
|
||||
var jsResults = getQueryResults('RETURN NOOPT(V8(SUBSTITUTE(' + args.join(', ') + ')))');
|
||||
assertEqual([ expected ], nuResults, value);
|
||||
assertEqual(jsResults, nuResults, value);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -1010,6 +1018,8 @@ function ahuacatlStringFunctionsTestSuite () {
|
|||
testSubstituteInvalid: function () {
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, 'RETURN SUBSTITUTE()');
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, `RETURN SUBSTITUTE('foo', 'bar', 'baz', 2, 2)`);
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, 'RETURN NOOPT(V8(SUBSTITUTE()))');
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, `RETURN NOOPT(V8(SUBSTITUTE('foo', 'bar', 'baz', 2, 2)))`);
|
||||
},
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -615,6 +615,22 @@ function ahuacatlFunctionsTestSuite () {
|
|||
assertEqual([ expected[0].reverse() ], actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test reverse function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testReverse5 : function () {
|
||||
let val = [
|
||||
['eÜrCyeltÖM', 'MÖtleyCrÜe'],
|
||||
['狗懶了過跳狸狐色棕的捷敏', '敏捷的棕色狐狸跳過了懶狗']
|
||||
];
|
||||
for (let i = 0; i < 2; i++) {
|
||||
let v = val[i];
|
||||
assertEqual([v[0]], getQueryResults('RETURN REVERSE(@v)', {v: v[1]}));
|
||||
assertEqual([v[0]], getQueryResults('RETURN NOOPT(V8(REVERSE(@v)))', {v: v[1]}));
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test reverse function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -628,6 +644,64 @@ function ahuacatlFunctionsTestSuite () {
|
|||
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN REVERSE({ })");
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test reverse V8 function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testReverseV8_1 : function () {
|
||||
var expected = [ [ ] ];
|
||||
var actual = getQueryResults("RETURN NOOPT(V8(REVERSE([ ])))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test reverse V8 function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testReverseV8_2 : function () {
|
||||
var expected = [ [ "fox" ] ];
|
||||
var actual = getQueryResults("RETURN NOOPT(V8(REVERSE([ \"fox\" ])))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test reverse V8 function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testReverseV8_3 : function () {
|
||||
var expected = [ [ false, [ "fox", "jumped" ], { "quick" : "brown" }, "the" ] ];
|
||||
var actual = getQueryResults("RETURN NOOPT(V8(REVERSE([ \"the\", { \"quick\" : \"brown\" }, [ \"fox\", \"jumped\" ], false ])))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test reverse V8 function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testReverseV8_4 : function () {
|
||||
var expected = [ [ 1, 2, 3 ] ];
|
||||
var actual = getQueryResults("LET a = (FOR i IN [ 1, 2, 3 ] RETURN i) LET b = NOOPT(V8(REVERSE(a))) RETURN a");
|
||||
// make sure reverse does not modify the original value
|
||||
assertEqual(expected, actual);
|
||||
|
||||
actual = getQueryResults("LET a = (FOR i IN [ 1, 2, 3] RETURN i) LET b = NOOPT(V8(REVERSE(a))) RETURN b");
|
||||
assertEqual([ expected[0].reverse() ], actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test reverse V8 function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testReverseV8_Invalid : function () {
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NOOPT(V8(REVERSE()))");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NOOPT(V8(REVERSE([ ], [ ])))");
|
||||
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(V8(REVERSE(null)))");
|
||||
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(V8(REVERSE(true)))");
|
||||
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(V8(REVERSE(4)))");
|
||||
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(V8(REVERSE({ })))");
|
||||
},
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test unique function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*jshint globalstrict:false, strict:false */
|
||||
/*global assertEqual, assertTrue */
|
||||
/*global assertEqual, assertTrue, assertFalse */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests for query language, subqueries in cluster
|
||||
|
@ -109,10 +109,10 @@ function clusterSubqueriesTestSuite () {
|
|||
RETURN sub[*].foo
|
||||
`;
|
||||
let c = db._query(q).toArray();
|
||||
assertEqual(c.length, 10) // we have 10 values for X
|
||||
assertEqual(c.length, 10); // we have 10 values for X
|
||||
let seen = new Set();
|
||||
for (let d of c) {
|
||||
assertEqual(d.length, 5) // we have 5 values for each x
|
||||
assertEqual(d.length, 5); // we have 5 values for each x
|
||||
let first = d[0];
|
||||
seen.add(first);
|
||||
for (let q of d) {
|
||||
|
|
|
@ -32,6 +32,7 @@ ERROR_DEADLOCK,29,"deadlock detected","Will be raised when a deadlock is detecte
|
|||
ERROR_SHUTTING_DOWN,30,"shutdown in progress","Will be raised when a call cannot succeed because a server shutdown is already in progress."
|
||||
ERROR_ONLY_ENTERPRISE,31,"only enterprise version","Will be raised when an enterprise-feature is requested from the community edition."
|
||||
ERROR_RESOURCE_LIMIT,32,"resource limit exceeded","Will be raised when the resources used by an operation exceed the configured maximum value."
|
||||
ERROR_ARANGO_ICU_ERROR,33,"icu error: %s","will be raised if icu operations failed"
|
||||
|
||||
################################################################################
|
||||
## HTTP error status codes
|
||||
|
|
|
@ -37,6 +37,7 @@ void TRI_InitializeErrorMessages() {
|
|||
REG_ERROR(ERROR_SHUTTING_DOWN, "shutdown in progress");
|
||||
REG_ERROR(ERROR_ONLY_ENTERPRISE, "only enterprise version");
|
||||
REG_ERROR(ERROR_RESOURCE_LIMIT, "resource limit exceeded");
|
||||
REG_ERROR(ERROR_ARANGO_ICU_ERROR, "icu error: %s");
|
||||
REG_ERROR(ERROR_HTTP_BAD_PARAMETER, "bad parameter");
|
||||
REG_ERROR(ERROR_HTTP_UNAUTHORIZED, "unauthorized");
|
||||
REG_ERROR(ERROR_HTTP_FORBIDDEN, "forbidden");
|
||||
|
|
|
@ -158,6 +158,11 @@ constexpr int TRI_ERROR_ONLY_ENTERPRISE
|
|||
/// configured maximum value.
|
||||
constexpr int TRI_ERROR_RESOURCE_LIMIT = 32;
|
||||
|
||||
/// 33: ERROR_ARANGO_ICU_ERROR
|
||||
/// "icu error: %s"
|
||||
/// will be raised if icu operations failed
|
||||
constexpr int TRI_ERROR_ARANGO_ICU_ERROR = 33;
|
||||
|
||||
/// 400: ERROR_HTTP_BAD_PARAMETER
|
||||
/// "bad parameter"
|
||||
/// Will be raised when the HTTP request does not fulfill the requirements.
|
||||
|
|
Loading…
Reference in New Issue