1
0
Fork 0

added template string generator function `aqlQuery` for generating AQL queries

This can be used to generate safe AQL queries with JavaScript parameter
variables or expressions easily:

    var name = 'test';
    var attributeName = '_key';
    var query = aqlQuery`FOR u IN users FILTER u.name == ${name} RETURN u.${attributeName}`;
    db._query(query);
This commit is contained in:
Jan Steemann 2015-08-30 22:32:26 +02:00
parent a3ee707f6f
commit 1867d6c4de
5 changed files with 150 additions and 4 deletions

View File

@ -1,6 +1,16 @@
v2.7.0 (XXXX-XX-XX)
-------------------
* added template string generator function `aqlQuery` for generating AQL queries
This can be used to generate safe AQL queries with JavaScript parameter
variables or expressions easily:
var name = 'test';
var attributeName = '_key';
var query = aqlQuery`FOR u IN users FILTER u.name == ${name} RETURN u.${attributeName}`;
db._query(query);
* report memory usage for document header data (revision id, pointer to data etc.)
in `db.collection.figures()`. The memory used for document headers will now
show up in the already existing attribute `indexes.size`. Due to that, the index

View File

@ -31,9 +31,21 @@ To pass bind parameters into a query, they can be specified as second argument t
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 02_workWithAQL_bindValues
Data-modifying AQL queries do not return a result, so the *toArray* method will always
return an empty array. To retrieve statistics for a data-modification query, use the
*getExtra* method:
It is also possible to use ES6 template strings for generating AQL queries. There is
a template string generator function named *aqlQuery*:
@startDocuBlockInline 02_workWithAQL_aqlQuery
@EXAMPLE_ARANGOSH_OUTPUT{02_workWithAQL_aqlQuery}
var key = 'testKey';
db._query(aqlQuery`FOR c IN mycollection FILTER c._key == ${key} RETURN c._key`).toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 02_workWithAQL_aqlQuery
Note: data-modifying AQL queries normally not return a result (unless the AQL query
contains a *RETURN* statement). When not using a *RETURN* statement in the query, the
*toArray* method will return an empty array.
It is always possible to retrieve statistics for a query with the *getExtra* method:
@startDocuBlockInline 03_workWithAQL_getExtra
@EXAMPLE_ARANGOSH_OUTPUT{03_workWithAQL_getExtra}

View File

@ -48,6 +48,25 @@ global.clearInterval = global.clearInterval || function () {};
global.setTimeout = global.setTimeout || function () {};
global.clearTimeout = global.clearTimeout || function () {};
////////////////////////////////////////////////////////////////////////////////
/// @brief template string generator for building an AQL query
////////////////////////////////////////////////////////////////////////////////
global.aqlQuery = function () {
var query = '',
bindVars = { },
n = arguments[0].length;
for (var i = 0; i < n; ++i) {
query += arguments[0][i];
if (i < n - 1) {
query += '@value' + i;
bindVars['value' + i] = arguments[i + 1];
}
}
return { query, bindVars };
};
////////////////////////////////////////////////////////////////////////////////
/// @brief start paging
////////////////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,5 @@
/*jshint globalstrict:false, strict:false */
/*global assertEqual, assertTrue, assertFalse, assertUndefined, fail */
/*global assertEqual, assertTrue, assertFalse, assertUndefined, assertMatch, aqlQuery, fail */
////////////////////////////////////////////////////////////////////////////////
/// @brief test the statement class
@ -837,6 +837,92 @@ function StatementSuite () {
db._useDatabase("_system");
db._dropDatabase("UnitTestsDatabase0");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test string builder
////////////////////////////////////////////////////////////////////////////////
testTemplateStringBuilder : function () {
var foo = "foo-matic", bar = "BAR o MATIC", what = "' this string \\ \" is ' evil\n`";
var result = aqlQuery`FOR ${foo} IN ${bar} RETURN ${what}`;
assertEqual("FOR @value0 IN @value1 RETURN @value2", result.query);
assertEqual({ value0: foo, value1: bar, value2: what }, result.bindVars);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test string builder
////////////////////////////////////////////////////////////////////////////////
testTemplateStringBuilderComplexTypes : function () {
var list = [ 1, 2, 3, 4 ], what = { foo: "bar", baz: "bark" };
var result = aqlQuery`FOR i IN ${list} RETURN ${what}`;
assertEqual("FOR i IN @value0 RETURN @value1", result.query);
assertEqual({ value0: [ 1, 2, 3, 4 ], value1: { foo: "bar", baz: "bark" } }, result.bindVars);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test string builder
////////////////////////////////////////////////////////////////////////////////
testTemplateStringBuilderObject : function () {
var result = aqlQuery`RETURN ${new Date('2015-01-01').toISOString()}`;
assertEqual("RETURN @value0", result.query);
assertEqual({ value0 : "2015-01-01T00:00:00.000Z" }, result.bindVars);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test string builder
////////////////////////////////////////////////////////////////////////////////
testTemplateString : function () {
var one = 1, two = 2, three = 3, add = 9;
var st = db._createStatement(aqlQuery`FOR u IN [ ${one}, ${two}, ${three} ] RETURN u + ${add}`);
var result = st.execute().toArray();
assertEqual([ 10, 11, 12 ], result);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test string builder
////////////////////////////////////////////////////////////////////////////////
testTemplateStringStrings : function () {
var FOR = "FOR", RETURN = "RETURN", PLUS = "+";
try {
db._createStatement(aqlQuery`${FOR} i IN 1..2 ${RETURN} i ${PLUS} 1`).execute();
fail();
}
catch (err) {
assertEqual(ERRORS.ERROR_QUERY_PARSE.code, err.errorNum);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test string builder
////////////////////////////////////////////////////////////////////////////////
testTemplateStringString : function () {
var a = "FROM TO RETURN INSERT";
var st = db._createStatement(aqlQuery`RETURN ${a}`);
var result = st.execute().toArray();
assertEqual([ a ], result);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test string builder
////////////////////////////////////////////////////////////////////////////////
testTemplateStringUndefined : function () {
try {
/*global foo */
db._createStatement(aqlQuery`FOR u IN ${foo} RETURN 1`);
fail();
}
catch (err) {
assertMatch(/^ReferenceError/, String(err));
}
}
};

View File

@ -59,6 +59,25 @@ global.clearInterval = function () {};
global.setTimeout = function () {};
global.clearTimeout = function () {};
////////////////////////////////////////////////////////////////////////////////
/// @brief template string generator for building an AQL query
////////////////////////////////////////////////////////////////////////////////
global.aqlQuery = function () {
var query = '',
bindVars = { },
n = arguments[0].length;
for (var i = 0; i < n; ++i) {
query += arguments[0][i];
if (i < n - 1) {
query += '@value' + i;
bindVars['value' + i] = arguments[i + 1];
}
}
return { query, bindVars };
};
// extend prototypes for internally defined classes
require("org/arangodb");