1
0
Fork 0

issue #80: support LENGTH(collection)

This commit is contained in:
Jan Steemann 2012-05-23 17:50:58 +02:00
parent fbc1d65135
commit 7c0e146246
5 changed files with 71 additions and 22 deletions

View File

@ -1138,8 +1138,8 @@ static void ProcessArgList (TRI_aql_codegen_js_t* const generator,
ScopeOutput(generator, ", ");
}
if (parameter->_type == AQL_NODE_COLLECTION) {
// collection arguments will be created as string arguments => e.g. "users"
if (parameter->_type == AQL_NODE_COLLECTION && TRI_ConvertParameterFunctionAql(function, i)) {
// collection arguments will be created as string argument => e.g. "users"
ScopeOutputQuoted(generator, TRI_AQL_NODE_STRING(parameter));
}
else {

View File

@ -128,6 +128,7 @@ static bool CheckArgumentType (TRI_aql_node_t* parameter,
if (*name == '@') {
// collection bind parameter. this is an error
found._collection = true;
found._list = true; // a collection is a list of documents
}
else {
// regular bind parameter
@ -168,13 +169,14 @@ static bool CheckArgumentType (TRI_aql_node_t* parameter,
else if (parameter->_type == AQL_NODE_COLLECTION) {
// actual parameter is a collection
found._collection = true;
found._list = true; // a collection is a list of documents
}
else {
// we cannot yet determine the type of the parameter
// this is the case if the argument is an expression, a function call etc.
if (!allowed->_collection) {
// if we do require anything else but collection, we don't know the
// if we do require anything else but a collection, we don't know the
// type and must exit here
return true;
}
@ -341,7 +343,8 @@ TRI_associative_pointer_t* TRI_InitialiseFunctionsAql (void) {
NULL);
// . = argument of any type (except collection)
// c = collection
// c = collection name, will be converted into list with documents
// h = collection name, will be converted into string
// z = null
// b = bool
// n = number
@ -380,11 +383,11 @@ TRI_associative_pointer_t* TRI_InitialiseFunctionsAql (void) {
REGISTER_FUNCTION("RAND", "NUMBER_RAND", false, false, "");
// geo functions
REGISTER_FUNCTION("NEAR", "GEO_NEAR", false, false, "c,n,n,n|s");
REGISTER_FUNCTION("WITHIN", "GEO_WITHIN", false, false, "c,n,n,n|s");
REGISTER_FUNCTION("NEAR", "GEO_NEAR", false, false, "h,n,n,n|s");
REGISTER_FUNCTION("WITHIN", "GEO_WITHIN", false, false, "h,n,n,n|s");
// graph functions
REGISTER_FUNCTION("PATHS", "GRAPH_PATHS", false, false, "c,c|s,b");
REGISTER_FUNCTION("PATHS", "GRAPH_PATHS", false, false, "c,h|s,b");
// misc functions
REGISTER_FUNCTION("FAIL", "FAIL", false, false, "|s"); // FAIL is non-deterministic, otherwise query optimisation will fail!
@ -531,6 +534,45 @@ bool TRI_RegisterFunctionAql (TRI_associative_pointer_t* functions,
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief check whether a function argument must be converted to another type
////////////////////////////////////////////////////////////////////////////////
bool TRI_ConvertParameterFunctionAql (const TRI_aql_function_t* const function,
const size_t checkArg) {
const char* pattern;
char c;
size_t i = 0;
bool foundArg = false;
assert(function);
i = 0;
pattern = function->_argPattern;
while ((c = *pattern++)) {
switch (c) {
case '|':
case ',':
if (foundArg) {
if (++i > checkArg) {
return false;
}
}
foundArg = false;
break;
case 'h':
if (i == checkArg) {
return true;
}
// break intentionally missing
default:
foundArg = true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief validate the arguments passed to a function
////////////////////////////////////////////////////////////////////////////////
@ -642,7 +684,11 @@ bool TRI_ValidateArgsFunctionAql (TRI_aql_context_t* const context,
allowed._array = true;
foundArg = true;
break;
case 'c': // collection
case 'c': // collection name => list
allowed._collection = true;
foundArg = true;
break;
case 'h': // collection name => string
allowed._collection = true;
foundArg = true;
break;

View File

@ -103,6 +103,13 @@ bool TRI_RegisterFunctionAql (TRI_associative_pointer_t*,
const bool,
const char* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief check whether a function argument must be converted to another type
////////////////////////////////////////////////////////////////////////////////
bool TRI_ConvertParameterFunctionAql (const TRI_aql_function_t* const,
const size_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief validate the arguments passed to a function
////////////////////////////////////////////////////////////////////////////////

View File

@ -1912,8 +1912,8 @@ function AHUACATL_GEO_WITHIN () {
////////////////////////////////////////////////////////////////////////////////
function AHUACATL_GRAPH_PATHS () {
var collection1 = arguments[0];
var collection2 = arguments[1];
var vertices = arguments[0];
var edgeCollection = arguments[1];
var direction = arguments[2] != undefined ? arguments[2] : "outbound";
var followCycles = arguments[3] ? arguments[3] : false;
@ -1921,6 +1921,8 @@ function AHUACATL_GRAPH_PATHS () {
var maxLength = 10;
var searchDirection;
AHUACATL_LIST(vertices);
// validate arguments
if (direction == "outbound") {
searchDirection = 1;
@ -1940,18 +1942,14 @@ function AHUACATL_GRAPH_PATHS () {
AHUACATL_THROW(internal.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "PATHS");
}
var vertexCollection = internal.db[collection1];
var edgeCollection = internal.edges[collection2];
var searchAttributes = {
"vertexCollection" : vertexCollection,
"edgeCollection" : edgeCollection,
"edgeCollection" : internal.edges[edgeCollection],
"minLength" : minLength,
"maxLength" : maxLength,
"direction" : searchDirection,
"followCycles" : followCycles,
};
var vertices = vertexCollection.all().toArray();
// TODO: restrict allEdges to edges with certain _from values etc.
var result = [ ];

View File

@ -1913,8 +1913,8 @@ static string JS_server_ahuacatl =
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"function AHUACATL_GRAPH_PATHS () {\n"
" var collection1 = arguments[0];\n"
" var collection2 = arguments[1];\n"
" var vertices = arguments[0];\n"
" var edgeCollection = arguments[1];\n"
" var direction = arguments[2] != undefined ? arguments[2] : \"outbound\";\n"
" var followCycles = arguments[3] ? arguments[3] : false;\n"
"\n"
@ -1922,6 +1922,8 @@ static string JS_server_ahuacatl =
" var maxLength = 10;\n"
" var searchDirection;\n"
"\n"
" AHUACATL_LIST(vertices);\n"
"\n"
" // validate arguments\n"
" if (direction == \"outbound\") {\n"
" searchDirection = 1;\n"
@ -1941,18 +1943,14 @@ static string JS_server_ahuacatl =
" AHUACATL_THROW(internal.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, \"PATHS\");\n"
" }\n"
"\n"
" var vertexCollection = internal.db[collection1];\n"
" var edgeCollection = internal.edges[collection2];\n"
" var searchAttributes = { \n"
" \"vertexCollection\" : vertexCollection, \n"
" \"edgeCollection\" : edgeCollection, \n"
" \"edgeCollection\" : internal.edges[edgeCollection],\n"
" \"minLength\" : minLength, \n"
" \"maxLength\" : maxLength, \n"
" \"direction\" : searchDirection,\n"
" \"followCycles\" : followCycles,\n"
" };\n"
"\n"
" var vertices = vertexCollection.all().toArray();\n"
" // TODO: restrict allEdges to edges with certain _from values etc.\n"
"\n"
" var result = [ ];\n"