1
0
Fork 0

Merge branch 'aql2' of ssh://github.com/triAGENS/ArangoDB into aql2

This commit is contained in:
Max Neunhoeffer 2014-08-29 11:09:44 +02:00
commit aefea865f5
4 changed files with 95 additions and 87 deletions

View File

@ -51,8 +51,8 @@ Function::Function (std::string const& externalName,
arguments(arguments), arguments(arguments),
isDeterministic(isDeterministic), isDeterministic(isDeterministic),
canThrow(canThrow), canThrow(canThrow),
containsCollectionParameter(false), implementation(implementation),
implementation(implementation) { conversions() {
initArguments(); initArguments();
} }
@ -68,56 +68,16 @@ Function::~Function () {
// --SECTION-- public methods // --SECTION-- public methods
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not a positional argument needs to be converted from a
/// collection parameter to a collection name parameter
////////////////////////////////////////////////////////////////////////////////
bool Function::mustConvertArgument (size_t position) const {
bool foundArg = false;
size_t i = 0;
char const* p = arguments.c_str();
while (true) {
char const c = *p++;
switch (c) {
case '\0':
return false;
case '|':
case ',':
if (foundArg) {
if (++i > position) {
return false;
}
}
foundArg = false;
break;
case 'h':
if (i == position) {
// found an argument to convert
return true;
}
foundArg = true;
break;
default:
foundArg = true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief parse the argument list and set the minimum and maximum number of /// @brief parse the argument list and set the minimum and maximum number of
/// arguments /// arguments
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void Function::initArguments () { void Function::initArguments () {
minRequiredArguments = maxRequiredArguments = 0; minRequiredArguments = 0;
maxRequiredArguments = 0;
size_t position = 0;
// setup some parsing state // setup some parsing state
bool inOptional = false; bool inOptional = false;
@ -140,6 +100,7 @@ void Function::initArguments () {
case '|': case '|':
// beginning of optional arguments // beginning of optional arguments
++position;
TRI_ASSERT(! inOptional); TRI_ASSERT(! inOptional);
if (foundArg) { if (foundArg) {
++minRequiredArguments; ++minRequiredArguments;
@ -151,6 +112,7 @@ void Function::initArguments () {
case ',': case ',':
// next argument // next argument
++position;
TRI_ASSERT(foundArg); TRI_ASSERT(foundArg);
if (! inOptional) { if (! inOptional) {
@ -166,12 +128,35 @@ void Function::initArguments () {
maxRequiredArguments = MaxArguments; maxRequiredArguments = MaxArguments;
return; return;
default: case 'h':
if (c == 'h') { // we found a collection parameter
// note that we found a collection parameter
containsCollectionParameter = true; // set the conversion info for the position
if (conversions.size() <= position) {
// we don't yet have another parameter at this position
conversions.push_back(CONVERSION_REQUIRED);
}
else if (conversions[position] == CONVERSION_NONE) {
// we already had a parameter at this position
conversions[position] = CONVERSION_OPTIONAL;
} }
foundArg = true; foundArg = true;
break;
default:
// we found any other parameter
// set the conversion info for the position
if (conversions.size() <= position) {
// we don't yet have another parameter at this position
conversions.push_back(CONVERSION_NONE);
}
else if (conversions[position] == CONVERSION_REQUIRED) {
// we already had a parameter at this position
conversions[position] = CONVERSION_OPTIONAL;
}
foundArg = true;
break;
} }
} }
} }

View File

@ -38,6 +38,12 @@ namespace triagens {
struct Function { struct Function {
enum Conversion {
CONVERSION_NONE,
CONVERSION_OPTIONAL,
CONVERSION_REQUIRED
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors // --SECTION-- constructors / destructors
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -87,7 +93,12 @@ namespace triagens {
/// collection parameter to a collection name parameter /// collection parameter to a collection name parameter
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool mustConvertArgument (size_t) const; inline Conversion getArgumentConversion (size_t position) const {
if (position >= conversions.size()) {
return CONVERSION_NONE;
}
return conversions[position];
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief parse the argument list and set the minimum and maximum number of /// @brief parse the argument list and set the minimum and maximum number of
@ -104,63 +115,62 @@ namespace triagens {
/// @brief function name (name used in JavaScript implementation) /// @brief function name (name used in JavaScript implementation)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::string const internalName; std::string const internalName;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief function name (name visible to the end user) /// @brief function name (name visible to the end user)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::string const externalName; std::string const externalName;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief function arguments /// @brief function arguments
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::string const arguments; std::string const arguments;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the function is deterministic (i.e. its results are /// @brief whether or not the function is deterministic (i.e. its results are
/// identical when called repeatedly with the same input values) /// identical when called repeatedly with the same input values)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool const isDeterministic; bool const isDeterministic;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the function may throw a runtime exception /// @brief whether or not the function may throw a runtime exception
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool const canThrow; bool const canThrow;
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the function contains a collection parameter that
/// will cause some special conversion during function calls
////////////////////////////////////////////////////////////////////////////////
bool containsCollectionParameter;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief minimum number of required arguments /// @brief minimum number of required arguments
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
size_t minRequiredArguments; size_t minRequiredArguments;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief maximum number of required arguments /// @brief maximum number of required arguments
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
size_t maxRequiredArguments; size_t maxRequiredArguments;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief C++ implementation of the function (maybe nullptr) /// @brief C++ implementation of the function (maybe nullptr)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
FunctionImplementation implementation; FunctionImplementation implementation;
////////////////////////////////////////////////////////////////////////////////
/// @brief function argument conversion information
////////////////////////////////////////////////////////////////////////////////
std::vector<Conversion> conversions;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief maximum number of function arguments that can be used /// @brief maximum number of function arguments that can be used
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static size_t const MaxArguments = 1024; static size_t const MaxArguments = 1024;
}; };

View File

@ -623,28 +623,28 @@ void V8Executor::generateCodeFunctionCall (AstNode const* node) {
auto member = args->getMember(i); auto member = args->getMember(i);
if (member != nullptr) { if (member == nullptr) {
if (func->containsCollectionParameter && continue;
member->type == NODE_TYPE_COLLECTION && }
func->mustConvertArgument(i)) {
// the parameter at this position is a collection name that is converted to a string auto conversion = func->getArgumentConversion(i);
// do a parameter conversion from a collection parameter to a collection name parameter
char const* name = member->getStringValue(); if (member->type == NODE_TYPE_COLLECTION &&
generateCodeString(name); (conversion == Function::CONVERSION_REQUIRED || conversion == Function::CONVERSION_OPTIONAL)) {
} // the parameter at this position is a collection name that is converted to a string
/* // do a parameter conversion from a collection parameter to a collection name parameter
else { char const* name = member->getStringValue();
// the parameter at the position is not a collection name... fail generateCodeString(name);
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, func->internalName.c_str()); }
} else if (conversion == Function::CONVERSION_REQUIRED) {
} // the parameter at the position is not a collection name... fail
*/ THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, func->internalName.c_str());
else { }
// generate regular code for the node else {
generateCodeNode(args->getMember(i)); generateCodeNode(args->getMember(i));
}
} }
} }
_buffer->appendText(")"); _buffer->appendText(")");
} }

View File

@ -3420,6 +3420,14 @@ function GEO_NEAR (collection, latitude, longitude, limit, distanceAttribute) {
// use default value // use default value
limit = 100; limit = 100;
} }
else if (TYPEWEIGHT(limit) !== TYPEWEIGHT_NUMBER) {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "NEAR");
}
var weight = TYPEWEIGHT(distanceAttribute);
if (weight !== TYPEWEIGHT_NULL && weight !== TYPEWEIGHT_STRING) {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "NEAR");
}
if (isCoordinator) { if (isCoordinator) {
var query = COLLECTION(collection).near(latitude, longitude); var query = COLLECTION(collection).near(latitude, longitude);
@ -3462,6 +3470,11 @@ function GEO_WITHIN (collection, latitude, longitude, radius, distanceAttribute)
query._distance = distanceAttribute; query._distance = distanceAttribute;
return query.toArray(); return query.toArray();
} }
var weight = TYPEWEIGHT(distanceAttribute);
if (weight !== TYPEWEIGHT_NULL && weight !== TYPEWEIGHT_STRING) {
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "NEAR");
}
var idx = INDEX(COLLECTION(collection), [ "geo1", "geo2" ]); var idx = INDEX(COLLECTION(collection), [ "geo1", "geo2" ]);