mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'aql2' of ssh://github.com/triAGENS/ArangoDB into aql2
This commit is contained in:
commit
d79c9f928c
|
@ -644,27 +644,48 @@ AstNode* Ast::createNodeArrayElement (char const* attributeName,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode* Ast::createNodeFunctionCall (char const* functionName,
|
||||
AstNode const* parameters) {
|
||||
AstNode const* arguments) {
|
||||
if (functionName == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
std::string const normalizedName = normalizeFunctionName(functionName);
|
||||
char* fname = _query->registerString(normalizedName.c_str(), normalizedName.size(), false);
|
||||
auto normalized = normalizeFunctionName(functionName);
|
||||
|
||||
AstNode* node;
|
||||
|
||||
if (normalizedName[0] == '_') {
|
||||
if (normalized.second) {
|
||||
// built-in function
|
||||
node = createNode(NODE_TYPE_FCALL);
|
||||
// register a pointer to the function
|
||||
auto func = _query->executor()->getFunctionByName(normalized.first);
|
||||
|
||||
TRI_ASSERT(func != nullptr);
|
||||
node->setData(static_cast<void const*>(func));
|
||||
|
||||
TRI_ASSERT(arguments != nullptr);
|
||||
TRI_ASSERT(arguments->type == NODE_TYPE_LIST);
|
||||
|
||||
// validate number of function call arguments
|
||||
size_t const n = arguments->numMembers();
|
||||
|
||||
auto numExpectedArguments = func->numArguments();
|
||||
if (n < numExpectedArguments.first || n > numExpectedArguments.second) {
|
||||
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH,
|
||||
functionName,
|
||||
static_cast<int>(numExpectedArguments.first),
|
||||
static_cast<int>(numExpectedArguments.second));
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// user-defined function
|
||||
node = createNode(NODE_TYPE_FCALL_USER);
|
||||
// register the function name
|
||||
char* fname = _query->registerString(normalized.first.c_str(), normalized.first.size(), false);
|
||||
node->setStringValue(fname);
|
||||
}
|
||||
|
||||
node->setStringValue(fname);
|
||||
node->addMember(parameters);
|
||||
node->addMember(arguments);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -809,6 +830,11 @@ void Ast::optimize () {
|
|||
if (node->type == NODE_TYPE_OPERATOR_TERNARY) {
|
||||
return optimizeTernaryOperator(node);
|
||||
}
|
||||
|
||||
// call to built-in function
|
||||
if (node->type == NODE_TYPE_FCALL) {
|
||||
return optimizeFunctionCall(node);
|
||||
}
|
||||
|
||||
// reference to a variable
|
||||
if (node->type == NODE_TYPE_REFERENCE) {
|
||||
|
@ -875,10 +901,10 @@ std::unordered_set<Variable*> Ast::getReferencedVariables (AstNode const* node)
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes a comparison function
|
||||
/// @brief executes an expression with constant parameters
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode* Ast::executeConstComparison (AstNode const* node) {
|
||||
AstNode* Ast::executeConstExpression (AstNode const* node) {
|
||||
TRI_json_t* result = _query->executor()->executeExpression(node);
|
||||
|
||||
if (result == nullptr) {
|
||||
|
@ -1105,7 +1131,7 @@ AstNode* Ast::optimizeBinaryOperatorRelational (AstNode* node) {
|
|||
return node;
|
||||
}
|
||||
|
||||
return executeConstComparison(node);
|
||||
return executeConstExpression(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1229,6 +1255,31 @@ AstNode* Ast::optimizeTernaryOperator (AstNode* node) {
|
|||
return falsePart;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief optimizes a call to a built-in function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode* Ast::optimizeFunctionCall (AstNode* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->type == NODE_TYPE_FCALL);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
||||
auto func = static_cast<Function*>(node->getData());
|
||||
TRI_ASSERT(func != nullptr);
|
||||
|
||||
if (! func->isDeterministic) {
|
||||
// non-deterministic function
|
||||
return node;
|
||||
}
|
||||
|
||||
if (! node->getMember(0)->isConstant()) {
|
||||
// arguments to function call are not constant
|
||||
return node;
|
||||
}
|
||||
|
||||
return executeConstExpression(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief optimizes a reference to a variable
|
||||
/// references are replaced with constants if possible
|
||||
|
@ -1474,7 +1525,7 @@ void Ast::traverse (AstNode const* node,
|
|||
/// @brief normalize a function name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string Ast::normalizeFunctionName (char const* name) {
|
||||
std::pair<std::string, bool> Ast::normalizeFunctionName (char const* name) {
|
||||
TRI_ASSERT(name != nullptr);
|
||||
|
||||
char* upperName = TRI_UpperAsciiStringZ(TRI_UNKNOWN_MEM_ZONE, name);
|
||||
|
@ -1489,10 +1540,11 @@ std::string Ast::normalizeFunctionName (char const* name) {
|
|||
|
||||
if (functionName.find(':') == std::string::npos) {
|
||||
// prepend default namespace for internal functions
|
||||
functionName = "_AQL:" + functionName;
|
||||
return std::make_pair(functionName, true);
|
||||
}
|
||||
|
||||
return functionName;
|
||||
// user-defined function
|
||||
return std::make_pair(functionName, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -499,10 +499,10 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes a comparison function
|
||||
/// @brief executes an expression with constant parameters
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode* executeConstComparison (AstNode const*);
|
||||
AstNode* executeConstExpression (AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief optimizes a FILTER node
|
||||
|
@ -548,6 +548,12 @@ namespace triagens {
|
|||
|
||||
AstNode* optimizeTernaryOperator (AstNode*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief optimizes a call to a built-in function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode* optimizeFunctionCall (AstNode*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief optimizes a reference to a variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -599,7 +605,7 @@ namespace triagens {
|
|||
/// @brief normalize a function name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string normalizeFunctionName (char const*);
|
||||
std::pair<std::string, bool> normalizeFunctionName (char const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a node of the specified type
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Aql/AstNode.h"
|
||||
#include "Aql/Function.h"
|
||||
#include "Aql/Scopes.h"
|
||||
#include "Basics/StringBuffer.h"
|
||||
|
||||
|
@ -77,12 +78,16 @@ TRI_json_t* AstNode::toJson (TRI_memory_zone_t* zone) const {
|
|||
if (type == NODE_TYPE_COLLECTION ||
|
||||
type == NODE_TYPE_PARAMETER ||
|
||||
type == NODE_TYPE_ATTRIBUTE_ACCESS ||
|
||||
type == NODE_TYPE_FCALL ||
|
||||
type == NODE_TYPE_FCALL_USER) {
|
||||
// dump "name" of node
|
||||
TRI_Insert3ArrayJson(zone, node, "name", TRI_CreateStringCopyJson(zone, getStringValue()));
|
||||
}
|
||||
|
||||
if (type == NODE_TYPE_FCALL) {
|
||||
auto func = static_cast<Function*>(getData());
|
||||
TRI_Insert3ArrayJson(zone, node, "name", TRI_CreateStringCopyJson(zone, func->name.c_str()));
|
||||
}
|
||||
|
||||
if (type == NODE_TYPE_VALUE) {
|
||||
// dump value of "value" node
|
||||
switch (value.type) {
|
||||
|
|
|
@ -366,6 +366,14 @@ namespace triagens {
|
|||
value.value._data = v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the data value of a node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline void setData (void const* v) {
|
||||
value.value._data = const_cast<void*>(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the type name of a node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Aql, built-in function
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
||||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGODB_AQL_FUNCTION_H
|
||||
#define ARANGODB_AQL_FUNCTION_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
|
||||
namespace triagens {
|
||||
namespace aql {
|
||||
|
||||
struct Function {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Function () = delete;
|
||||
|
||||
Function (std::string const& name,
|
||||
std::string const& arguments,
|
||||
bool isDeterministic)
|
||||
: name(name),
|
||||
arguments(arguments),
|
||||
isDeterministic(isDeterministic) {
|
||||
|
||||
initArguments();
|
||||
}
|
||||
|
||||
~Function () {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if the function has been deprecated
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool isDeprecated () const {
|
||||
// currently there are no deprecated functions
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the number of required arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::pair<size_t, size_t> numArguments () const {
|
||||
return std::make_pair(minRequiredArguments, maxRequiredArguments);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief parse the argument list and set the minimum and maximum number of
|
||||
/// arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void initArguments () {
|
||||
minRequiredArguments = maxRequiredArguments = 0;
|
||||
|
||||
// setup some parsing state
|
||||
bool inOptional = false;
|
||||
bool foundArg = false;
|
||||
|
||||
char const* p = arguments.c_str();
|
||||
while (true) {
|
||||
char const c = *p++;
|
||||
|
||||
switch (c) {
|
||||
case '\0':
|
||||
// end of argument list
|
||||
if (foundArg) {
|
||||
if (! inOptional) {
|
||||
++minRequiredArguments;
|
||||
}
|
||||
++maxRequiredArguments;
|
||||
}
|
||||
return;
|
||||
|
||||
case '|':
|
||||
// beginning of optional arguments
|
||||
TRI_ASSERT(! inOptional);
|
||||
if (foundArg) {
|
||||
++minRequiredArguments;
|
||||
++maxRequiredArguments;
|
||||
}
|
||||
inOptional = true;
|
||||
foundArg = false;
|
||||
break;
|
||||
|
||||
case ',':
|
||||
// next argument
|
||||
TRI_ASSERT(foundArg);
|
||||
|
||||
if (! inOptional) {
|
||||
++minRequiredArguments;
|
||||
}
|
||||
++maxRequiredArguments;
|
||||
foundArg = false;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
// repeated optional argument
|
||||
TRI_ASSERT(inOptional);
|
||||
maxRequiredArguments = MaxArguments;
|
||||
return;
|
||||
|
||||
default:
|
||||
foundArg = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief function name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string const name;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief function arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string const arguments;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the function is deterministic (i.e. its results are
|
||||
/// identical when called repeatedly with the same input values)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool const isDeterministic;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief minimum number of required arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t minRequiredArguments;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief maximum number of required arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t maxRequiredArguments;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief maximum number of function arguments that can be used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static size_t const MaxArguments = 1024;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
// End:
|
|
@ -163,7 +163,7 @@ void Query::registerError (int code,
|
|||
THROW_ARANGO_EXCEPTION(code);
|
||||
}
|
||||
else {
|
||||
THROW_ARANGO_EXCEPTION_STRING(code, details);
|
||||
THROW_ARANGO_EXCEPTION_PARAMS(code, details);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ void Scopes::addVariable (Variable* variable) {
|
|||
|
||||
if (scope->existsVariable(variable->name)) {
|
||||
// duplicate variable name
|
||||
THROW_ARANGO_EXCEPTION_STRING(TRI_ERROR_QUERY_VARIABLE_REDECLARED, variable->name);
|
||||
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_VARIABLE_REDECLARED, variable->name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,10 +39,14 @@
|
|||
using namespace triagens::aql;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- function names used in execution
|
||||
// --SECTION-- static initialization
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
std::unordered_map<int, std::string> const V8Executor::FunctionNames{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief internal functions used in execution
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unordered_map<int, std::string const> const V8Executor::InternalFunctionNames{
|
||||
{ static_cast<int>(NODE_TYPE_OPERATOR_UNARY_PLUS), "UNARY_PLUS" },
|
||||
{ static_cast<int>(NODE_TYPE_OPERATOR_UNARY_MINUS), "UNARY_MINUS" },
|
||||
{ static_cast<int>(NODE_TYPE_OPERATOR_UNARY_NOT), "LOGICAL_NOT" },
|
||||
|
@ -63,6 +67,156 @@ std::unordered_map<int, std::string> const V8Executor::FunctionNames{
|
|||
{ static_cast<int>(NODE_TYPE_OPERATOR_TERNARY), "TERNARY_OPERATOR_FN" }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief user-accessible functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unordered_map<std::string, Function const> const V8Executor::FunctionNames{
|
||||
// meanings of the symbols in the function arguments list
|
||||
// ------------------------------------------------------
|
||||
//
|
||||
// . = argument of any type (except 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
|
||||
// s = string
|
||||
// p = primitive
|
||||
// l = list
|
||||
// a = (hash) array/document
|
||||
// r = regex (a string with a special format). note: the regex type is mutually exclusive with all other types
|
||||
|
||||
// type check functions
|
||||
{ "IS_NULL", Function("IS_NULL", ".", true) },
|
||||
{ "IS_BOOL", Function("IS_BOOL", ".", true) },
|
||||
{ "IS_NUMBER", Function("IS_NUMBER", ".", true) },
|
||||
{ "IS_STRING", Function("IS_STRING", ".", true) },
|
||||
{ "IS_LIST", Function("IS_LIST", ".", true) },
|
||||
{ "IS_DOCUMENT", Function("IS_DOCUMENT", ".", true) },
|
||||
|
||||
// type cast functions
|
||||
{ "TO_NUMBER", Function("CAST_NUMBER", ".", true) },
|
||||
{ "TO_STRING", Function("CAST_STRING", ".", true) },
|
||||
{ "TO_BOOL", Function("CAST_BOOL", ".", true) },
|
||||
{ "TO_LIST", Function("CAST_LIST", ".", true) },
|
||||
|
||||
// string functions
|
||||
{ "CONCAT", Function("STRING_CONCAT", "sz,sz|+", true) },
|
||||
{ "CONCAT_SEPARATOR", Function("STRING_CONCAT_SEPARATOR", "s,sz,sz|+", true) },
|
||||
{ "CHAR_LENGTH", Function("CHAR_LENGTH", "s", true) },
|
||||
{ "LOWER", Function("STRING_LOWER", "s", true) },
|
||||
{ "UPPER", Function("STRING_UPPER", "s", true) },
|
||||
{ "SUBSTRING", Function("STRING_SUBSTRING", "s,n|n", true) },
|
||||
{ "CONTAINS", Function("STRING_CONTAINS", "s,s|b", true) },
|
||||
{ "LIKE", Function("STRING_LIKE", "s,r|b", true) },
|
||||
{ "LEFT", Function("STRING_LEFT", "s,n", true) },
|
||||
{ "RIGHT", Function("STRING_RIGHT", "s,n", true) },
|
||||
{ "TRIM", Function("STRING_TRIM", "s|n", true) },
|
||||
|
||||
// numeric functions
|
||||
{ "FLOOR", Function("NUMBER_FLOOR", "n", true) },
|
||||
{ "CEIL", Function("NUMBER_CEIL", "n", true) },
|
||||
{ "ROUND", Function("NUMBER_ROUND", "n", true) },
|
||||
{ "ABS", Function("NUMBER_ABS", "n", true) },
|
||||
{ "RAND", Function("NUMBER_RAND", "", false) },
|
||||
{ "SQRT", Function("NUMBER_SQRT", "n", true) },
|
||||
|
||||
// list functions
|
||||
{ "RANGE", Function("RANGE", "n,n|n", true) },
|
||||
{ "UNION", Function("UNION", "l,l|+",true) },
|
||||
{ "UNION_DISTINCT", Function("UNION_DISTINCT", "l,l|+", true) },
|
||||
{ "MINUS", Function("MINUS", "l,l|+", true) },
|
||||
{ "INTERSECTION", Function("INTERSECTION", "l,l|+", true) },
|
||||
{ "FLATTEN", Function("FLATTEN", "l|n", true) },
|
||||
{ "LENGTH", Function("LENGTH", "las", true) },
|
||||
{ "MIN", Function("MIN", "l", true) },
|
||||
{ "MAX", Function("MAX", "l", true) },
|
||||
{ "SUM", Function("SUM", "l", true) },
|
||||
{ "MEDIAN", Function("MEDIAN", "l", true) },
|
||||
{ "AVERAGE", Function("AVERAGE", "l", true) },
|
||||
{ "VARIANCE_SAMPLE", Function("VARIANCE_SAMPLE", "l", true) },
|
||||
{ "VARIANCE_POPULATION", Function("VARIANCE_POPULATION", "l", true) },
|
||||
{ "STDDEV_SAMPLE", Function("STDDEV_SAMPLE", "l", true) },
|
||||
{ "STDDEV_POPULATION", Function("STDDEV_POPULATION", "l", true) },
|
||||
{ "UNIQUE", Function("UNIQUE", "l", true) },
|
||||
{ "SLICE", Function("SLICE", "l,n|n", true) },
|
||||
{ "REVERSE", Function("REVERSE", "ls", true) }, // note: REVERSE() can be applied on strings, too
|
||||
{ "FIRST", Function("FIRST", "l", true) },
|
||||
{ "LAST", Function("LAST", "l", true) },
|
||||
{ "NTH", Function("NTH", "l,n", true) },
|
||||
{ "POSITION", Function("POSITION", "l,.|b", true) },
|
||||
|
||||
// document functions
|
||||
{ "HAS", Function("HAS", "az,s", true) },
|
||||
{ "ATTRIBUTES", Function("ATTRIBUTES", "a|b,b", true) },
|
||||
{ "MERGE", Function("MERGE", "a,a|+", true) },
|
||||
{ "MERGE_RECURSIVE", Function("MERGE_RECURSIVE", "a,a|+", true) },
|
||||
{ "DOCUMENT", Function("DOCUMENT", "h.|.", true) },
|
||||
{ "MATCHES", Function("MATCHES", ".,l|b", true) },
|
||||
{ "UNSET", Function("UNSET", "a,sl|+", true) },
|
||||
{ "KEEP", Function("KEEP", "a,sl|+", true) },
|
||||
{ "TRANSLATE", Function("TRANSLATE", ".,a|.", true) },
|
||||
|
||||
// geo functions
|
||||
{ "NEAR", Function("GEO_NEAR", "h,n,n|nz,s", false) },
|
||||
{ "WITHIN", Function("GEO_WITHIN", "h,n,n,n|s", false) },
|
||||
|
||||
// fulltext functions
|
||||
{ "FULLTEXT", Function("FULLTEXT", "h,s,s", false) },
|
||||
|
||||
// graph functions
|
||||
{ "PATHS", Function("GRAPH_PATHS", "c,h|s,b", false )},
|
||||
{ "GRAPH_PATHS", Function("GENERAL_GRAPH_PATHS", "s|a", false )},
|
||||
{ "SHORTEST_PATH", Function("GRAPH_SHORTEST_PATH", "h,h,s,s,s|a", false )},
|
||||
{ "GRAPH_SHORTEST_PATH", Function("GENERAL_GRAPH_SHORTEST_PATH", "s,als,als|a", false )},
|
||||
{ "GRAPH_DISTANCE_TO", Function("GENERAL_GRAPH_DISTANCE_TO", "s,als,als|a", false )},
|
||||
{ "TRAVERSAL", Function("GRAPH_TRAVERSAL", "h,h,s,s|a", false )},
|
||||
{ "GRAPH_TRAVERSAL", Function("GENERAL_GRAPH_TRAVERSAL", "s,als,s|a", false )},
|
||||
{ "TRAVERSAL_TREE", Function("GRAPH_TRAVERSAL_TREE", "s,als,s,s|a", false )},
|
||||
{ "GRAPH_TRAVERSAL_TREE", Function("GENERAL_GRAPH_TRAVERSAL_TREE", "s,als,s,s|a", false )},
|
||||
{ "EDGES", Function("GRAPH_EDGES", "h,s,s|l", false )},
|
||||
{ "GRAPH_EDGES", Function("GENERAL_GRAPH_EDGES", "s,als|a", false )},
|
||||
{ "GRAPH_VERTICES", Function("GENERAL_GRAPH_VERTICES", "s,als|a", false )},
|
||||
{ "NEIGHBORS", Function("GRAPH_NEIGHBORS", "h,h,s,s|l", false )},
|
||||
{ "GRAPH_NEIGHBORS", Function("GENERAL_GRAPH_NEIGHBORS", "s,als|a", false )},
|
||||
{ "GRAPH_COMMON_NEIGHBORS", Function("GENERAL_GRAPH_COMMON_NEIGHBORS", "s,als,als|a,a", false )},
|
||||
{ "GRAPH_COMMON_PROPERTIES", Function("GENERAL_GRAPH_COMMON_PROPERTIES", "s,als,als|a", false )},
|
||||
{ "GRAPH_ECCENTRICITY", Function("GENERAL_GRAPH_ECCENTRICITY", "s|a", false )},
|
||||
{ "GRAPH_BETWEENNESS", Function("GENERAL_GRAPH_BETWEENNESS", "s|a", false )},
|
||||
{ "GRAPH_CLOSENESS", Function("GENERAL_GRAPH_CLOSENESS", "s|a", false )},
|
||||
{ "GRAPH_ABSOLUTE_ECCENTRICITY", Function("GENERAL_GRAPH_ABSOLUTE_ECCENTRICITY", "s,als|a", false )},
|
||||
{ "GRAPH_ABSOLUTE_CLOSENESS", Function("GENERAL_GRAPH_ABSOLUTE_CLOSENESS", "s,als|a", false )},
|
||||
{ "GRAPH_DIAMETER", Function("GENERAL_GRAPH_DIAMETER", "s|a", false )},
|
||||
{ "GRAPH_RADIUS", Function("GENERAL_GRAPH_RADIUS", "s|a", false )},
|
||||
|
||||
// date functions
|
||||
{ "DATE_NOW", Function("DATE_NOW", "", false) },
|
||||
{ "DATE_TIMESTAMP", Function("DATE_TIMESTAMP", "ns|ns,ns,ns,ns,ns,ns", true) },
|
||||
{ "DATE_ISO8601", Function("DATE_ISO8601", "ns|ns,ns,ns,ns,ns,ns", true) },
|
||||
{ "DATE_DAYOFWEEK", Function("DATE_DAYOFWEEK", "ns", true) },
|
||||
{ "DATE_YEAR", Function("DATE_YEAR", "ns", true) },
|
||||
{ "DATE_MONTH", Function("DATE_MONTH", "ns", true) },
|
||||
{ "DATE_DAY", Function("DATE_DAY", "ns", true) },
|
||||
{ "DATE_HOUR", Function("DATE_HOUR", "ns", true) },
|
||||
{ "DATE_MINUTE", Function("DATE_MINUTE", "ns", true) },
|
||||
{ "DATE_SECOND", Function("DATE_SECOND", "ns", true) },
|
||||
{ "DATE_MILLISECOND", Function("DATE_MILLISECOND", "ns", true) },
|
||||
|
||||
// misc functions
|
||||
{ "FAIL", Function("FAIL", "|s", false) },
|
||||
{ "PASSTHRU", Function("PASSTHRU", ".", false) },
|
||||
{ "SLEEP", Function("SLEEP", "n", false) },
|
||||
{ "COLLECTIONS", Function("COLLECTIONS", "", false) },
|
||||
{ "NOT_NULL", Function("NOT_NULL", ".|+", true) },
|
||||
{ "FIRST_LIST", Function("FIRST_LIST", ".|+", true) },
|
||||
{ "FIRST_DOCUMENT", Function("FIRST_DOCUMENT", ".|+", true) },
|
||||
{ "PARSE_IDENTIFIER", Function("PARSE_IDENTIFIER", ".", true) },
|
||||
{ "SKIPLIST", Function("SKIPLIST_QUERY", "h,a|n,n", false) },
|
||||
{ "CURRENT_USER", Function("CURRENT_USER", "", false) },
|
||||
{ "CURRENT_DATABASE", Function("CURRENT_DATABASE", "", false) }
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -96,9 +250,9 @@ V8Executor::~V8Executor () {
|
|||
|
||||
V8Expression* V8Executor::generateExpression (AstNode const* node) {
|
||||
generateCodeExpression(node);
|
||||
|
||||
std::cout << "CREATED CODE: " << _buffer->c_str() << "\n";
|
||||
|
||||
std::cout << "Executor::generateExpression: " << _buffer->c_str() << "\n";
|
||||
|
||||
v8::Handle<v8::Script> compiled = v8::Script::Compile(v8::String::New(_buffer->c_str(), (int) _buffer->length()),
|
||||
v8::String::New("--script--"));
|
||||
|
||||
|
@ -111,6 +265,23 @@ V8Expression* V8Executor::generateExpression (AstNode const* node) {
|
|||
|
||||
if (tryCatch.HasCaught()) {
|
||||
if (tryCatch.CanContinue()) {
|
||||
if (tryCatch.Exception()->IsObject()) {
|
||||
// cast the exception into an object
|
||||
v8::Handle<v8::Array> objValue = v8::Handle<v8::Array>::Cast(tryCatch.Exception());
|
||||
|
||||
v8::Handle<v8::String> errorName = v8::String::New("errorName");
|
||||
|
||||
if (objValue->HasOwnProperty(errorName)) {
|
||||
v8::Handle<v8::Value> errorNum = objValue->Get(errorName);
|
||||
|
||||
if (errorNum->IsNumber()) {
|
||||
int errorCode = static_cast<int>(TRI_ObjectToInt64(errorNum));
|
||||
// TODO: handle errors
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
else {
|
||||
|
@ -122,6 +293,7 @@ V8Expression* V8Executor::generateExpression (AstNode const* node) {
|
|||
}
|
||||
|
||||
if (val.IsEmpty()) {
|
||||
// out of memory
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
|
@ -136,9 +308,26 @@ V8Expression* V8Executor::generateExpression (AstNode const* node) {
|
|||
TRI_json_t* V8Executor::executeExpression (AstNode const* node) {
|
||||
generateCodeExpression(node);
|
||||
|
||||
std::cout << "Executor::ExecuteExpression: " << _buffer->c_str() << "\n";
|
||||
|
||||
return execute();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns a reference to a built-in function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Function const* V8Executor::getFunctionByName (std::string const& name) {
|
||||
auto it = FunctionNames.find(name);
|
||||
|
||||
if (it == FunctionNames.end()) {
|
||||
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_NAME_UNKNOWN, name.c_str());
|
||||
}
|
||||
|
||||
// return the address of the function
|
||||
return &((*it).second);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -214,9 +403,9 @@ void V8Executor::generateCodeUnaryOperator (AstNode const* node) {
|
|||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
||||
auto it = FunctionNames.find(static_cast<int>(node->type));
|
||||
auto it = InternalFunctionNames.find(static_cast<int>(node->type));
|
||||
|
||||
if (it == FunctionNames.end()) {
|
||||
if (it == InternalFunctionNames.end()) {
|
||||
// no function found for the type of node
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
@ -237,9 +426,9 @@ void V8Executor::generateCodeBinaryOperator (AstNode const* node) {
|
|||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 2);
|
||||
|
||||
auto it = FunctionNames.find(static_cast<int>(node->type));
|
||||
auto it = InternalFunctionNames.find(static_cast<int>(node->type));
|
||||
|
||||
if (it == FunctionNames.end()) {
|
||||
if (it == InternalFunctionNames.end()) {
|
||||
// no function found for the type of node
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
@ -275,9 +464,9 @@ void V8Executor::generateCodeTernaryOperator (AstNode const* node) {
|
|||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 3);
|
||||
|
||||
auto it = FunctionNames.find(static_cast<int>(node->type));
|
||||
auto it = InternalFunctionNames.find(static_cast<int>(node->type));
|
||||
|
||||
if (it == FunctionNames.end()) {
|
||||
if (it == InternalFunctionNames.end()) {
|
||||
// no function found for the type of node
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
@ -340,23 +529,23 @@ void V8Executor::generateCodeCollection (AstNode const* node) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate JavaScript code for a function call
|
||||
/// @brief generate JavaScript code for a call to a built-in function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void V8Executor::generateCodeFunctionCall (AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
||||
char const* name = node->getStringValue();
|
||||
|
||||
_buffer->appendText("aql.");
|
||||
_buffer->appendText(name);
|
||||
_buffer->appendText("(");
|
||||
auto func = static_cast<Function*>(node->getData());
|
||||
|
||||
auto args = node->getMember(0);
|
||||
TRI_ASSERT(args != nullptr);
|
||||
TRI_ASSERT(args->type == NODE_TYPE_LIST);
|
||||
|
||||
_buffer->appendText("aql.");
|
||||
_buffer->appendText(func->name);
|
||||
_buffer->appendText("(");
|
||||
|
||||
size_t const n = args->numMembers();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
if (i > 0) {
|
||||
|
@ -368,6 +557,36 @@ void V8Executor::generateCodeFunctionCall (AstNode const* node) {
|
|||
_buffer->appendText(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate JavaScript code for a call to a user-defined function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void V8Executor::generateCodeUserFunctionCall (AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
||||
char const* name = node->getStringValue();
|
||||
TRI_ASSERT(name != nullptr);
|
||||
|
||||
auto args = node->getMember(0);
|
||||
TRI_ASSERT(args != nullptr);
|
||||
TRI_ASSERT(args->type == NODE_TYPE_LIST);
|
||||
|
||||
_buffer->appendText("aql.FCALL_USER(\"");
|
||||
_buffer->appendJsonEncoded(name);
|
||||
_buffer->appendText("\", [");
|
||||
|
||||
size_t const n = args->numMembers();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
if (i > 0) {
|
||||
_buffer->appendText(", ");
|
||||
}
|
||||
|
||||
generateCodeNode(args->getMember(i));
|
||||
}
|
||||
_buffer->appendText("])");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate JavaScript code for an expansion (i.e. [*] operator)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -497,6 +716,10 @@ void V8Executor::generateCodeNode (AstNode const* node) {
|
|||
generateCodeFunctionCall(node);
|
||||
break;
|
||||
|
||||
case NODE_TYPE_FCALL_USER:
|
||||
generateCodeUserFunctionCall(node);
|
||||
break;
|
||||
|
||||
case NODE_TYPE_EXPAND:
|
||||
generateCodeExpand(node);
|
||||
break;
|
||||
|
@ -560,6 +783,7 @@ TRI_json_t* V8Executor::execute () {
|
|||
// it will fail badly
|
||||
|
||||
TRI_ASSERT(_buffer != nullptr);
|
||||
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
v8::Handle<v8::Script> compiled = v8::Script::Compile(v8::String::New(_buffer->c_str(), (int) _buffer->length()),
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#define ARANGODB_AQL_V8_EXECUTOR_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Aql/Function.h"
|
||||
|
||||
struct TRI_json_s;
|
||||
|
||||
|
@ -86,6 +87,12 @@ namespace triagens {
|
|||
|
||||
struct TRI_json_s* executeExpression (AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns a reference to a built-in function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Function const* getFunctionByName (std::string const&);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -147,11 +154,17 @@ namespace triagens {
|
|||
void generateCodeCollection (AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate JavaScript code for a function call
|
||||
/// @brief generate JavaScript code for a call to a built-in function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void generateCodeFunctionCall (AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate JavaScript code for a user-defined function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void generateCodeUserFunctionCall (AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate JavaScript code for an expansion (i.e. [*] operator)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -213,11 +226,16 @@ namespace triagens {
|
|||
triagens::basics::StringBuffer* _buffer;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief AQL function names
|
||||
/// @brief AQL internal function names
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::unordered_map<int, std::string> const FunctionNames;
|
||||
static std::unordered_map<int, std::string const> const InternalFunctionNames;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief AQL user-callable function names
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::unordered_map<std::string, Function const> const FunctionNames;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -90,9 +90,33 @@ namespace triagens {
|
|||
values->Set(v8::String::New(varname.c_str(), (int) varname.size()), argv[startPos + reg].toV8(trx, docColls[reg]));
|
||||
}
|
||||
|
||||
// set function arguments
|
||||
v8::Handle<v8::Value> args[] = { values };
|
||||
|
||||
// execute the function
|
||||
v8::TryCatch tryCatch;
|
||||
v8::Handle<v8::Value> result = func->Call(func, 1, args);
|
||||
|
||||
if (tryCatch.HasCaught()) {
|
||||
if (tryCatch.CanContinue()) {
|
||||
if (tryCatch.Exception()->IsObject()) {
|
||||
// cast the exception into an object
|
||||
v8::Handle<v8::Array> objValue = v8::Handle<v8::Array>::Cast(tryCatch.Exception());
|
||||
v8::Handle<v8::String> errorNum = v8::String::New("errorNum");
|
||||
|
||||
if (objValue->HasOwnProperty(errorNum)) {
|
||||
v8::Handle<v8::Value> errorNumValue = objValue->Get(errorNum);
|
||||
|
||||
if (errorNumValue->IsNumber()) {
|
||||
int errorCode = static_cast<int>(TRI_ObjectToInt64(errorNumValue));
|
||||
THROW_ARANGO_EXCEPTION(errorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: handle case when we can NOT continue
|
||||
}
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
|
|
@ -34,14 +34,28 @@ using namespace std;
|
|||
using namespace triagens::arango;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor
|
||||
/// @brief constructor, without format string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Exception::Exception (int code,
|
||||
string const& details,
|
||||
char const* file,
|
||||
int line)
|
||||
: _details(details),
|
||||
: _errorMessage(TRI_errno_string(code)),
|
||||
_file(file),
|
||||
_line(line),
|
||||
_code(code) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor, for creating an exception with an already created
|
||||
/// error message (normally based on error templates containing %s, %d etc.)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Exception::Exception (int code,
|
||||
string const& errorMessage,
|
||||
char const* file,
|
||||
int line)
|
||||
: _errorMessage(errorMessage),
|
||||
_file(file),
|
||||
_line(line),
|
||||
_code(code) {
|
||||
|
@ -74,20 +88,7 @@ char const* Exception::what () const throw () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string Exception::message () const throw () {
|
||||
string message(TRI_errno_string(_code));
|
||||
|
||||
if (strstr(message.c_str(), "%s") != nullptr) {
|
||||
// error message contains "%s" wildcard
|
||||
try {
|
||||
// replace %s with actual details
|
||||
return basics::StringUtils::replace(message, "%s", _details);
|
||||
}
|
||||
catch (...) {
|
||||
return "internal error";
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
return _errorMessage;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -98,6 +99,25 @@ int Exception::code () const throw () {
|
|||
return _code;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief construct an error message from a template string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string Exception::FillExceptionString (int code,
|
||||
...) {
|
||||
char const* format = TRI_errno_string(code);
|
||||
TRI_ASSERT(format != nullptr);
|
||||
|
||||
char buffer[1024];
|
||||
va_list ap;
|
||||
va_start(ap, code);
|
||||
vsnprintf(buffer, sizeof(buffer) - 1, format, ap);
|
||||
va_end(ap);
|
||||
buffer[sizeof(buffer) - 1] = '\0'; // Windows
|
||||
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -44,14 +44,14 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define THROW_ARANGO_EXCEPTION(code) \
|
||||
throw triagens::arango::Exception(code, "", __FILE__, __LINE__)
|
||||
throw triagens::arango::Exception(code, __FILE__, __LINE__)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief throws an exception for internal errors
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define THROW_ARANGO_EXCEPTION_STRING(code, details) \
|
||||
throw triagens::arango::Exception(code, details, __FILE__, __LINE__)
|
||||
#define THROW_ARANGO_EXCEPTION_PARAMS(code, ...) \
|
||||
throw triagens::arango::Exception(code, triagens::arango::Exception::FillExceptionString(code, __VA_ARGS__), __FILE__, __LINE__)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
|
@ -67,7 +67,11 @@ namespace triagens {
|
|||
class Exception : public virtual std::exception {
|
||||
public:
|
||||
Exception (int code,
|
||||
std::string const& details,
|
||||
char const* file,
|
||||
int line);
|
||||
|
||||
Exception (int code,
|
||||
std::string const& errorMessage,
|
||||
char const* file,
|
||||
int line);
|
||||
|
||||
|
@ -80,8 +84,10 @@ namespace triagens {
|
|||
|
||||
int code () const throw();
|
||||
|
||||
static std::string FillExceptionString (int, ...);
|
||||
|
||||
protected:
|
||||
std::string const _details;
|
||||
std::string const _errorMessage;
|
||||
char const* _file;
|
||||
int const _line;
|
||||
int const _code;
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"ERROR_QUERY_TOO_MANY_COLLECTIONS" : { "code" : 1522, "message" : "too many collections" },
|
||||
"ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED" : { "code" : 1530, "message" : "document attribute '%s' is assigned multiple times" },
|
||||
"ERROR_QUERY_FUNCTION_NAME_UNKNOWN" : { "code" : 1540, "message" : "usage of unknown function '%s()'" },
|
||||
"ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH" : { "code" : 1541, "message" : "invalid number of arguments for function '%s()'" },
|
||||
"ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH" : { "code" : 1541, "message" : "invalid number of arguments for function '%s()', expected number of arguments: minimum: %d, maximum: %d" },
|
||||
"ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH" : { "code" : 1542, "message" : "invalid argument type used in call to function '%s()'" },
|
||||
"ERROR_QUERY_INVALID_REGEX" : { "code" : 1543, "message" : "invalid regex argument value used in call to function '%s()'" },
|
||||
"ERROR_QUERY_BIND_PARAMETERS_INVALID" : { "code" : 1550, "message" : "invalid structure of bind parameters" },
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
"ERROR_QUERY_TOO_MANY_COLLECTIONS" : { "code" : 1522, "message" : "too many collections" },
|
||||
"ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED" : { "code" : 1530, "message" : "document attribute '%s' is assigned multiple times" },
|
||||
"ERROR_QUERY_FUNCTION_NAME_UNKNOWN" : { "code" : 1540, "message" : "usage of unknown function '%s()'" },
|
||||
"ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH" : { "code" : 1541, "message" : "invalid number of arguments for function '%s()'" },
|
||||
"ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH" : { "code" : 1541, "message" : "invalid number of arguments for function '%s()', expected number of arguments: minimum: %d, maximum: %d" },
|
||||
"ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH" : { "code" : 1542, "message" : "invalid argument type used in call to function '%s()'" },
|
||||
"ERROR_QUERY_INVALID_REGEX" : { "code" : 1543, "message" : "invalid regex argument value used in call to function '%s()'" },
|
||||
"ERROR_QUERY_BIND_PARAMETERS_INVALID" : { "code" : 1550, "message" : "invalid structure of bind parameters" },
|
||||
|
|
|
@ -196,7 +196,7 @@ ERROR_QUERY_COLLECTION_LOCK_FAILED,1521,"unable to read-lock collection %s","Wil
|
|||
ERROR_QUERY_TOO_MANY_COLLECTIONS,1522,"too many collections","Will be raised when the number of collections in a query is beyond the allowed value."
|
||||
ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED,1530,"document attribute '%s' is assigned multiple times","Will be raised when a document attribute is re-assigned."
|
||||
ERROR_QUERY_FUNCTION_NAME_UNKNOWN,1540,"usage of unknown function '%s()'","Will be raised when an undefined function is called."
|
||||
ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH,1541,"invalid number of arguments for function '%s()'","Will be raised when the number of arguments used in a function call does not match the expected number of arguments for the function."
|
||||
ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH,1541,"invalid number of arguments for function '%s()', expected number of arguments: minimum: %d, maximum: %d","Will be raised when the number of arguments used in a function call does not match the expected number of arguments for the function."
|
||||
ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH,1542,"invalid argument type used in call to function '%s()'","Will be raised when the type of an argument used in a function call does not match the expected argument type."
|
||||
ERROR_QUERY_INVALID_REGEX,1543,"invalid regex argument value used in call to function '%s()'","Will be raised when an invalid regex argument value is used in a call to a function that expects a regex."
|
||||
ERROR_QUERY_BIND_PARAMETERS_INVALID,1550,"invalid structure of bind parameters","Will be raised when the structure of bind parameters passed has an unexpected format."
|
||||
|
|
|
@ -156,7 +156,7 @@ void TRI_InitialiseErrorMessages (void) {
|
|||
REG_ERROR(ERROR_QUERY_TOO_MANY_COLLECTIONS, "too many collections");
|
||||
REG_ERROR(ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED, "document attribute '%s' is assigned multiple times");
|
||||
REG_ERROR(ERROR_QUERY_FUNCTION_NAME_UNKNOWN, "usage of unknown function '%s()'");
|
||||
REG_ERROR(ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "invalid number of arguments for function '%s()'");
|
||||
REG_ERROR(ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "invalid number of arguments for function '%s()', expected number of arguments: minimum: %d, maximum: %d");
|
||||
REG_ERROR(ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "invalid argument type used in call to function '%s()'");
|
||||
REG_ERROR(ERROR_QUERY_INVALID_REGEX, "invalid regex argument value used in call to function '%s()'");
|
||||
REG_ERROR(ERROR_QUERY_BIND_PARAMETERS_INVALID, "invalid structure of bind parameters");
|
||||
|
|
|
@ -8,7 +8,7 @@ extern "C" {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page ArangoErrors Error codes and meanings
|
||||
/// @startDocuBlock errorCodes
|
||||
///
|
||||
/// The following errors might be raised when running ArangoDB:
|
||||
///
|
||||
/// - 0: @LIT{no error}
|
||||
|
@ -371,7 +371,7 @@ extern "C" {
|
|||
/// Will be raised when a document attribute is re-assigned.
|
||||
/// - 1540: @LIT{usage of unknown function '\%s()'}
|
||||
/// Will be raised when an undefined function is called.
|
||||
/// - 1541: @LIT{invalid number of arguments for function '\%s()'}
|
||||
/// - 1541: @LIT{invalid number of arguments for function '\%s()', expected number of arguments: minimum: \%d, maximum: \%d}
|
||||
/// Will be raised when the number of arguments used in a function call does
|
||||
/// not match the expected number of arguments for the function.
|
||||
/// - 1542: @LIT{invalid argument type used in call to function '\%s()'}
|
||||
|
@ -586,7 +586,6 @@ extern "C" {
|
|||
/// Will be returned if the element was not found in the structure.
|
||||
/// - 20000: @LIT{newest version of app already installed}
|
||||
/// newest version of app already installed
|
||||
/// @endDocuBlock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2122,7 +2121,8 @@ void TRI_InitialiseErrorMessages (void);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief 1541: ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH
|
||||
///
|
||||
/// invalid number of arguments for function '%s()'
|
||||
/// invalid number of arguments for function '%s()', expected number of
|
||||
/// arguments: minimum: %d, maximum: %d
|
||||
///
|
||||
/// Will be raised when the number of arguments used in a function call does
|
||||
/// not match the expected number of arguments for the function.
|
||||
|
|
Loading…
Reference in New Issue