mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'aql2' of ssh://github.com/triAGENS/ArangoDB into aql2
This commit is contained in:
commit
aefea865f5
|
@ -51,8 +51,8 @@ Function::Function (std::string const& externalName,
|
|||
arguments(arguments),
|
||||
isDeterministic(isDeterministic),
|
||||
canThrow(canThrow),
|
||||
containsCollectionParameter(false),
|
||||
implementation(implementation) {
|
||||
implementation(implementation),
|
||||
conversions() {
|
||||
|
||||
initArguments();
|
||||
}
|
||||
|
@ -68,56 +68,16 @@ Function::~Function () {
|
|||
// --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
|
||||
/// arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Function::initArguments () {
|
||||
minRequiredArguments = maxRequiredArguments = 0;
|
||||
minRequiredArguments = 0;
|
||||
maxRequiredArguments = 0;
|
||||
|
||||
size_t position = 0;
|
||||
|
||||
// setup some parsing state
|
||||
bool inOptional = false;
|
||||
|
@ -140,6 +100,7 @@ void Function::initArguments () {
|
|||
|
||||
case '|':
|
||||
// beginning of optional arguments
|
||||
++position;
|
||||
TRI_ASSERT(! inOptional);
|
||||
if (foundArg) {
|
||||
++minRequiredArguments;
|
||||
|
@ -151,6 +112,7 @@ void Function::initArguments () {
|
|||
|
||||
case ',':
|
||||
// next argument
|
||||
++position;
|
||||
TRI_ASSERT(foundArg);
|
||||
|
||||
if (! inOptional) {
|
||||
|
@ -166,12 +128,35 @@ void Function::initArguments () {
|
|||
maxRequiredArguments = MaxArguments;
|
||||
return;
|
||||
|
||||
default:
|
||||
if (c == 'h') {
|
||||
// note that we found a collection parameter
|
||||
containsCollectionParameter = true;
|
||||
case 'h':
|
||||
// we found a collection 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_REQUIRED);
|
||||
}
|
||||
else if (conversions[position] == CONVERSION_NONE) {
|
||||
// we already had a parameter at this position
|
||||
conversions[position] = CONVERSION_OPTIONAL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,12 @@ namespace triagens {
|
|||
|
||||
struct Function {
|
||||
|
||||
enum Conversion {
|
||||
CONVERSION_NONE,
|
||||
CONVERSION_OPTIONAL,
|
||||
CONVERSION_REQUIRED
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -87,7 +93,12 @@ namespace triagens {
|
|||
/// 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
|
||||
|
@ -104,63 +115,62 @@ namespace triagens {
|
|||
/// @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)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string const externalName;
|
||||
std::string const externalName;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief function arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string const 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;
|
||||
bool const isDeterministic;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the function may throw a runtime exception
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool const canThrow;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not the function contains a collection parameter that
|
||||
/// will cause some special conversion during function calls
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool containsCollectionParameter;
|
||||
bool const canThrow;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief minimum number of required arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t minRequiredArguments;
|
||||
size_t minRequiredArguments;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief maximum number of required arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t maxRequiredArguments;
|
||||
size_t maxRequiredArguments;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static size_t const MaxArguments = 1024;
|
||||
static size_t const MaxArguments = 1024;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -623,28 +623,28 @@ void V8Executor::generateCodeFunctionCall (AstNode const* node) {
|
|||
|
||||
auto member = args->getMember(i);
|
||||
|
||||
if (member != nullptr) {
|
||||
if (func->containsCollectionParameter &&
|
||||
member->type == NODE_TYPE_COLLECTION &&
|
||||
func->mustConvertArgument(i)) {
|
||||
// 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
|
||||
char const* name = member->getStringValue();
|
||||
generateCodeString(name);
|
||||
}
|
||||
/*
|
||||
else {
|
||||
// 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
|
||||
generateCodeNode(args->getMember(i));
|
||||
}
|
||||
if (member == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto conversion = func->getArgumentConversion(i);
|
||||
|
||||
if (member->type == NODE_TYPE_COLLECTION &&
|
||||
(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
|
||||
char const* name = member->getStringValue();
|
||||
generateCodeString(name);
|
||||
}
|
||||
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 {
|
||||
generateCodeNode(args->getMember(i));
|
||||
}
|
||||
}
|
||||
|
||||
_buffer->appendText(")");
|
||||
}
|
||||
|
||||
|
|
|
@ -3420,6 +3420,14 @@ function GEO_NEAR (collection, latitude, longitude, limit, distanceAttribute) {
|
|||
// use default value
|
||||
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) {
|
||||
var query = COLLECTION(collection).near(latitude, longitude);
|
||||
|
@ -3462,6 +3470,11 @@ function GEO_WITHIN (collection, latitude, longitude, radius, distanceAttribute)
|
|||
query._distance = distanceAttribute;
|
||||
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" ]);
|
||||
|
||||
|
|
Loading…
Reference in New Issue