mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/AvocadoDB into devel
This commit is contained in:
commit
22f4bc3651
|
@ -1667,6 +1667,7 @@ char* TRI_GenerateCodeAql (const void* const data) {
|
|||
OutputString(&generator->_buffer, REGISTER_PREFIX);
|
||||
OutputInt(&generator->_buffer, (int64_t) resultRegister);
|
||||
OutputString(&generator->_buffer, ";\n");
|
||||
|
||||
OutputString(&generator->_buffer, "})()");
|
||||
|
||||
if (generator->_error) {
|
||||
|
@ -1681,7 +1682,7 @@ char* TRI_GenerateCodeAql (const void* const data) {
|
|||
|
||||
if (code) {
|
||||
LOG_TRACE("generated code: %s", code);
|
||||
// printf("generated code: %s", code);
|
||||
// printf("generated code: %s", code);
|
||||
}
|
||||
|
||||
return code;
|
||||
|
|
|
@ -41,11 +41,62 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create code for a function call
|
||||
/// @brief create javascript function code for a relational operation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_string_buffer_t* FcallCode(const char* const name,
|
||||
const TRI_aql_node_t* const args) {
|
||||
static TRI_string_buffer_t* RelationCode (const char* const name,
|
||||
const TRI_aql_node_t* const lhs,
|
||||
const TRI_aql_node_t* const rhs) {
|
||||
TRI_string_buffer_t* buffer = TRI_CreateStringBuffer(TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
if (!lhs || !rhs) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (TRI_AppendStringStringBuffer(buffer, "(function(){return AHUACATL_RELATIONAL_") != TRI_ERROR_NO_ERROR) {
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (TRI_AppendStringStringBuffer(buffer, name) != TRI_ERROR_NO_ERROR) {
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (TRI_AppendStringStringBuffer(buffer, "(") != TRI_ERROR_NO_ERROR) {
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!TRI_NodeJavascriptAql(buffer, lhs)) {
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (TRI_AppendCharStringBuffer(buffer, ',') != TRI_ERROR_NO_ERROR) {
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!TRI_NodeJavascriptAql(buffer, rhs)) {
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (TRI_AppendStringStringBuffer(buffer, ");})") != TRI_ERROR_NO_ERROR) {
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create javascript function code for a function call
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_string_buffer_t* FcallCode (const char* const name,
|
||||
const TRI_aql_node_t* const args) {
|
||||
TRI_string_buffer_t* buffer = TRI_CreateStringBuffer(TRI_UNKNOWN_MEM_ZONE);
|
||||
size_t i;
|
||||
size_t n;
|
||||
|
@ -98,8 +149,8 @@ static TRI_string_buffer_t* FcallCode(const char* const name,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_aql_node_t* OptimiseFcall (TRI_aql_context_t* const context,
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* args = (TRI_aql_node_t*) node->_members._buffer[0];
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* args = TRI_AQL_NODE_MEMBER(node, 0);
|
||||
TRI_aql_function_t* function;
|
||||
TRI_js_exec_context_t* execContext;
|
||||
TRI_string_buffer_t* code;
|
||||
|
@ -126,12 +177,14 @@ static TRI_aql_node_t* OptimiseFcall (TRI_aql_context_t* const context,
|
|||
}
|
||||
|
||||
// all arguments are constants
|
||||
// create the function code
|
||||
code = FcallCode(function->_internalName, args);
|
||||
if (!code) {
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
// execute the function code
|
||||
execContext = TRI_CreateExecutionContext(code->_buffer);
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, code);
|
||||
|
||||
|
@ -147,9 +200,82 @@ static TRI_aql_node_t* OptimiseFcall (TRI_aql_context_t* const context,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// use the constant values instead of the function call node
|
||||
node = TRI_JsonNodeAql(context, json);
|
||||
if (!node) {
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
}
|
||||
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
|
||||
LOG_TRACE("optimised function call");
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief optimise a sort expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_aql_node_t* OptimiseSort (TRI_aql_context_t* const context,
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* list = TRI_AQL_NODE_MEMBER(node, 0);
|
||||
size_t i, n;
|
||||
|
||||
if (!list) {
|
||||
return node;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
n = list->_members._length;
|
||||
while (i < n) {
|
||||
// sort element
|
||||
TRI_aql_node_t* element = TRI_AQL_NODE_MEMBER(list, i);
|
||||
TRI_aql_node_t* expression = TRI_AQL_NODE_MEMBER(element, 0);
|
||||
|
||||
// check if the sort element is constant
|
||||
if (!expression || !TRI_IsConstantValueNodeAql(expression)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
// sort element is constant so it can be removed
|
||||
TRI_RemoveVectorPointer(&list->_members, i);
|
||||
--n;
|
||||
|
||||
LOG_TRACE("optimised away sort element");
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
// no members left => sort removed
|
||||
LOG_TRACE("optimised away sort");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief optimise a filter expression
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_aql_node_t* OptimiseFilter (TRI_aql_context_t* const context,
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* expression = TRI_AQL_NODE_MEMBER(node, 0);
|
||||
bool result;
|
||||
|
||||
if (!expression || !TRI_IsConstantValueNodeAql(expression)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
result = TRI_GetBooleanNodeValueAql(expression);
|
||||
if (result) {
|
||||
// filter expression is always true => remove it
|
||||
LOG_TRACE("optimised away constant filter");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -159,8 +285,8 @@ static TRI_aql_node_t* OptimiseFcall (TRI_aql_context_t* const context,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_aql_node_t* OptimiseUnaryArithmeticOperation (TRI_aql_context_t* const context,
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* operand = (TRI_aql_node_t*) node->_members._buffer[0];
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* operand = TRI_AQL_NODE_MEMBER(node, 0);
|
||||
|
||||
if (!operand || !TRI_IsConstantValueNodeAql(operand)) {
|
||||
return node;
|
||||
|
@ -195,7 +321,7 @@ static TRI_aql_node_t* OptimiseUnaryArithmeticOperation (TRI_aql_context_t* cons
|
|||
|
||||
static TRI_aql_node_t* OptimiseUnaryLogicalOperation (TRI_aql_context_t* const context,
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* operand = (TRI_aql_node_t*) node->_members._buffer[0];
|
||||
TRI_aql_node_t* operand = TRI_AQL_NODE_MEMBER(node, 0);
|
||||
|
||||
if (!operand || !TRI_IsConstantValueNodeAql(operand)) {
|
||||
return node;
|
||||
|
@ -214,6 +340,8 @@ static TRI_aql_node_t* OptimiseUnaryLogicalOperation (TRI_aql_context_t* const c
|
|||
if (!node) {
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
}
|
||||
|
||||
LOG_TRACE("optimised away unary logical operation");
|
||||
}
|
||||
|
||||
return node;
|
||||
|
@ -225,8 +353,8 @@ static TRI_aql_node_t* OptimiseUnaryLogicalOperation (TRI_aql_context_t* const c
|
|||
|
||||
static TRI_aql_node_t* OptimiseBinaryLogicalOperation (TRI_aql_context_t* const context,
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* lhs = (TRI_aql_node_t*) node->_members._buffer[0];
|
||||
TRI_aql_node_t* rhs = (TRI_aql_node_t*) node->_members._buffer[1];
|
||||
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
|
||||
TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
|
||||
bool isEligibleLhs;
|
||||
bool isEligibleRhs;
|
||||
bool lhsValue;
|
||||
|
@ -257,6 +385,8 @@ static TRI_aql_node_t* OptimiseBinaryLogicalOperation (TRI_aql_context_t* const
|
|||
assert(node->_type == AQL_NODE_OPERATOR_BINARY_AND ||
|
||||
node->_type == AQL_NODE_OPERATOR_BINARY_OR);
|
||||
|
||||
LOG_TRACE("optimised away binary logical operation");
|
||||
|
||||
if (node->_type == AQL_NODE_OPERATOR_BINARY_AND) {
|
||||
if (lhsValue) {
|
||||
// if (true && rhs) => rhs
|
||||
|
@ -281,14 +411,86 @@ static TRI_aql_node_t* OptimiseBinaryLogicalOperation (TRI_aql_context_t* const
|
|||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief optimise a relational operation with two operands
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_aql_node_t* OptimiseBinaryRelationalOperation (TRI_aql_context_t* const context,
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
|
||||
TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
|
||||
TRI_js_exec_context_t* execContext;
|
||||
TRI_string_buffer_t* code;
|
||||
TRI_json_t* json;
|
||||
char* func;
|
||||
|
||||
if (!lhs || !TRI_IsConstantValueNodeAql(lhs) || !rhs || !TRI_IsConstantValueNodeAql(rhs)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (node->_type == AQL_NODE_OPERATOR_BINARY_EQ) {
|
||||
func = "EQUAL";
|
||||
}
|
||||
else if (node->_type == AQL_NODE_OPERATOR_BINARY_NE) {
|
||||
func = "UNEQUAL";
|
||||
}
|
||||
else if (node->_type == AQL_NODE_OPERATOR_BINARY_GT) {
|
||||
func = "GREATER";
|
||||
}
|
||||
else if (node->_type == AQL_NODE_OPERATOR_BINARY_GE) {
|
||||
func = "GREATER_EQUAL";
|
||||
}
|
||||
else if (node->_type == AQL_NODE_OPERATOR_BINARY_LT) {
|
||||
func = "LESS";
|
||||
}
|
||||
else if (node->_type == AQL_NODE_OPERATOR_BINARY_LE) {
|
||||
func = "LESS_EQUAL";
|
||||
}
|
||||
else if (node->_type == AQL_NODE_OPERATOR_BINARY_IN) {
|
||||
func = "IN";
|
||||
}
|
||||
|
||||
code = RelationCode(func, lhs, rhs);
|
||||
if (!code) {
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
return node;
|
||||
}
|
||||
|
||||
// execute the function code
|
||||
execContext = TRI_CreateExecutionContext(code->_buffer);
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, code);
|
||||
|
||||
if (!execContext) {
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
return node;
|
||||
}
|
||||
|
||||
json = TRI_ExecuteResultContext(execContext);
|
||||
TRI_FreeExecutionContext(execContext);
|
||||
if (!json) {
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_SCRIPT, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// use the constant values instead of the function call node
|
||||
node = TRI_JsonNodeAql(context, json);
|
||||
if (!node) {
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
}
|
||||
|
||||
LOG_TRACE("optimised away binary relational operation");
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief optimise an arithmetic operation with two operands
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_aql_node_t* OptimiseBinaryArithmeticOperation (TRI_aql_context_t* const context,
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* lhs = (TRI_aql_node_t*) node->_members._buffer[0];
|
||||
TRI_aql_node_t* rhs = (TRI_aql_node_t*) node->_members._buffer[1];
|
||||
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
|
||||
TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
|
||||
bool isEligibleLhs;
|
||||
bool isEligibleRhs;
|
||||
double value;
|
||||
|
@ -350,6 +552,8 @@ static TRI_aql_node_t* OptimiseBinaryArithmeticOperation (TRI_aql_context_t* con
|
|||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LOG_TRACE("optimised away binary arithmetic operation");
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -374,12 +578,24 @@ static TRI_aql_node_t* ModifyNode (void* data, TRI_aql_node_t* node) {
|
|||
case AQL_NODE_OPERATOR_BINARY_AND:
|
||||
case AQL_NODE_OPERATOR_BINARY_OR:
|
||||
return OptimiseBinaryLogicalOperation(context, node);
|
||||
case AQL_NODE_OPERATOR_BINARY_EQ:
|
||||
case AQL_NODE_OPERATOR_BINARY_NE:
|
||||
case AQL_NODE_OPERATOR_BINARY_LT:
|
||||
case AQL_NODE_OPERATOR_BINARY_LE:
|
||||
case AQL_NODE_OPERATOR_BINARY_GT:
|
||||
case AQL_NODE_OPERATOR_BINARY_GE:
|
||||
case AQL_NODE_OPERATOR_BINARY_IN:
|
||||
return OptimiseBinaryRelationalOperation(context, node);
|
||||
case AQL_NODE_OPERATOR_BINARY_PLUS:
|
||||
case AQL_NODE_OPERATOR_BINARY_MINUS:
|
||||
case AQL_NODE_OPERATOR_BINARY_TIMES:
|
||||
case AQL_NODE_OPERATOR_BINARY_DIV:
|
||||
case AQL_NODE_OPERATOR_BINARY_MOD:
|
||||
return OptimiseBinaryArithmeticOperation(context, node);
|
||||
case AQL_NODE_SORT:
|
||||
return OptimiseSort(context, node);
|
||||
case AQL_NODE_FILTER:
|
||||
return OptimiseFilter(context, node);
|
||||
case AQL_NODE_FCALL:
|
||||
return OptimiseFcall(context, node);
|
||||
default:
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <BasicsC/common.h>
|
||||
#include <BasicsC/strings.h>
|
||||
#include <BasicsC/hashes.h>
|
||||
#include <BasicsC/logging.h>
|
||||
#include <BasicsC/vector.h>
|
||||
#include <BasicsC/associative.h>
|
||||
|
||||
|
|
|
@ -42,11 +42,13 @@
|
|||
|
||||
static TRI_aql_node_t* ModifyNode (TRI_aql_modify_tree_walker_t* const walker,
|
||||
TRI_aql_node_t* node) {
|
||||
TRI_aql_node_t* result = NULL;
|
||||
TRI_aql_node_t* first = NULL;
|
||||
TRI_aql_node_t* last = NULL;
|
||||
|
||||
assert(walker);
|
||||
|
||||
while (node) {
|
||||
TRI_aql_node_t* old;
|
||||
size_t i;
|
||||
size_t n = node->_members._length;
|
||||
|
||||
|
@ -60,19 +62,38 @@ static TRI_aql_node_t* ModifyNode (TRI_aql_modify_tree_walker_t* const walker,
|
|||
|
||||
node->_members._buffer[i] = ModifyNode(walker, member);
|
||||
}
|
||||
|
||||
// keep old node pointer
|
||||
old = node;
|
||||
|
||||
// the visit function might set it to NULL
|
||||
node = walker->visitFunc(walker->_data, node);
|
||||
if (!result) {
|
||||
result = node;
|
||||
if (!first) {
|
||||
// first remaining node in chain
|
||||
first = node;
|
||||
}
|
||||
|
||||
if (last) {
|
||||
// keep node chaining intact
|
||||
last->_next = node;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
last = node;
|
||||
}
|
||||
|
||||
// determine next next in chain
|
||||
if (node == old) {
|
||||
// node did not change
|
||||
node = node->_next;
|
||||
}
|
||||
else if (node != old && old != NULL) {
|
||||
// node changed
|
||||
node = old->_next;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return first;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -99,7 +99,7 @@ ERROR_AVOCADO_DATAFILE_FULL,1300,"datafile full","Will be raised when the datafi
|
|||
################################################################################
|
||||
|
||||
ERROR_QUERY_KILLED,1500,"query killed","Will be raised when a running query is killed by an explicit admin command."
|
||||
ERROR_QUERY_PARSE,1501,"parse error: %s","Will be raised when query is parsed and is found to be syntactially invalid."
|
||||
ERROR_QUERY_PARSE,1501,"%s","Will be raised when query is parsed and is found to be syntactially invalid."
|
||||
ERROR_QUERY_EMPTY,1502,"query is empty","Will be raised when an empty query is specified."
|
||||
ERROR_QUERY_SPECIFICATION_INVALID,1503,"query specification invalid","Will be raised when a query is sent to the server with an incomplete or invalid query specification structure."
|
||||
ERROR_QUERY_NUMBER_OUT_OF_RANGE,1504,"number '%s' is out of range","Will be raised when a numeric value inside a query is out of the allowed value range."
|
||||
|
@ -117,7 +117,7 @@ ERROR_QUERY_BIND_PARAMETER_UNDECLARED,1515,"bind parameter '%s' was not declared
|
|||
ERROR_QUERY_BIND_PARAMETER_VALUE_INVALID,1516,"invalid value for bind parameter '%s'","Will be raised when an invalid value is specified for one of the bind parameters."
|
||||
ERROR_QUERY_BIND_PARAMETER_NUMBER_OUT_OF_RANGE,1517,"bind parameter number '%s' out of range","Will be specified when the numeric index for a bind parameter of type @n is out of the allowed range."
|
||||
ERROR_QUERY_FUNCTION_NAME_UNKNOWN,1518,"usage of unknown function '%s'","Will be raised when an undefined function is called."
|
||||
ERROR_QUERY_RUNTIME_ERROR,1520,"runtime error in query","Will be raised when a Javascript runtime error occurs while executing a query."
|
||||
ERROR_QUERY_RUNTIME_ERROR,1520,"runtime error '%s'","Will be raised when a Javascript runtime error occurs while executing a query."
|
||||
ERROR_QUERY_LIMIT_VALUE_OUT_OF_RANGE,1521,"limit value '%s' is out of range","Will be raised when a limit value in the query is outside the allowed range (e. g. when passing a negative skip value)."
|
||||
ERROR_QUERY_VARIABLE_REDECLARED,1522,"variable '%s' is assigned multiple times","Will be raised when a variable gets re-assigned in a query."
|
||||
ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED,1523,"document attribute '%s' is assigned multiple times","Will be raised when a document attribute is re-assigned."
|
||||
|
|
|
@ -65,7 +65,7 @@ void TRI_InitialiseErrorMessages (void) {
|
|||
REG_ERROR(ERROR_AVOCADO_CAP_CONSTRAINT_ALREADY_DEFINED, "cap constraint already defined");
|
||||
REG_ERROR(ERROR_AVOCADO_DATAFILE_FULL, "datafile full");
|
||||
REG_ERROR(ERROR_QUERY_KILLED, "query killed");
|
||||
REG_ERROR(ERROR_QUERY_PARSE, "parse error: %s");
|
||||
REG_ERROR(ERROR_QUERY_PARSE, "%s");
|
||||
REG_ERROR(ERROR_QUERY_EMPTY, "query is empty");
|
||||
REG_ERROR(ERROR_QUERY_SPECIFICATION_INVALID, "query specification invalid");
|
||||
REG_ERROR(ERROR_QUERY_NUMBER_OUT_OF_RANGE, "number '%s' is out of range");
|
||||
|
@ -83,7 +83,7 @@ void TRI_InitialiseErrorMessages (void) {
|
|||
REG_ERROR(ERROR_QUERY_BIND_PARAMETER_VALUE_INVALID, "invalid value for bind parameter '%s'");
|
||||
REG_ERROR(ERROR_QUERY_BIND_PARAMETER_NUMBER_OUT_OF_RANGE, "bind parameter number '%s' out of range");
|
||||
REG_ERROR(ERROR_QUERY_FUNCTION_NAME_UNKNOWN, "usage of unknown function '%s'");
|
||||
REG_ERROR(ERROR_QUERY_RUNTIME_ERROR, "runtime error in query");
|
||||
REG_ERROR(ERROR_QUERY_RUNTIME_ERROR, "runtime error '%s'");
|
||||
REG_ERROR(ERROR_QUERY_LIMIT_VALUE_OUT_OF_RANGE, "limit value '%s' is out of range");
|
||||
REG_ERROR(ERROR_QUERY_VARIABLE_REDECLARED, "variable '%s' is assigned multiple times");
|
||||
REG_ERROR(ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED, "document attribute '%s' is assigned multiple times");
|
||||
|
|
|
@ -130,7 +130,7 @@ extern "C" {
|
|||
/// - 1500: @CODE{query killed}
|
||||
/// Will be raised when a running query is killed by an explicit admin
|
||||
/// command.
|
||||
/// - 1501: @CODE{parse error: \%s}
|
||||
/// - 1501: @CODE{\%s}
|
||||
/// Will be raised when query is parsed and is found to be syntactially
|
||||
/// invalid.
|
||||
/// - 1502: @CODE{query is empty}
|
||||
|
@ -180,7 +180,7 @@ extern "C" {
|
|||
/// is out of the allowed range.
|
||||
/// - 1518: @CODE{usage of unknown function '\%s'}
|
||||
/// Will be raised when an undefined function is called.
|
||||
/// - 1520: @CODE{runtime error in query}
|
||||
/// - 1520: @CODE{runtime error '\%s'}
|
||||
/// Will be raised when a Javascript runtime error occurs while executing a
|
||||
/// query.
|
||||
/// - 1521: @CODE{limit value '\%s' is out of range}
|
||||
|
@ -891,7 +891,7 @@ void TRI_InitialiseErrorMessages (void);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief 1501: ERROR_QUERY_PARSE
|
||||
///
|
||||
/// parse error: %s
|
||||
/// %s
|
||||
///
|
||||
/// Will be raised when query is parsed and is found to be syntactially invalid.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1083,7 +1083,7 @@ void TRI_InitialiseErrorMessages (void);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief 1520: ERROR_QUERY_RUNTIME_ERROR
|
||||
///
|
||||
/// runtime error in query
|
||||
/// runtime error '%s'
|
||||
///
|
||||
/// Will be raised when a Javascript runtime error occurs while executing a
|
||||
/// query.
|
||||
|
|
|
@ -362,20 +362,31 @@ GeoIndex * GeoIndex_new(void)
|
|||
int i,j;
|
||||
double lat, lon, x, y, z;
|
||||
|
||||
gix = malloc(sizeof(GeoIx));
|
||||
if(gix==NULL) return (GeoIndex *) gix;
|
||||
gix = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(GeoIx), false);
|
||||
|
||||
if(gix == NULL) {
|
||||
return (GeoIndex *) gix;
|
||||
}
|
||||
|
||||
/* try to allocate all the things we need */
|
||||
gix->pots = malloc(GEOPOTSTART*sizeof(GeoPot));
|
||||
gix->gc = malloc(GEOSLOTSTART*sizeof(GeoCoordinate));
|
||||
gix->pots = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, GEOPOTSTART*sizeof(GeoPot), false);
|
||||
gix->gc = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, GEOSLOTSTART*sizeof(GeoCoordinate), false);
|
||||
|
||||
/* if any of them fail, free the ones that succeeded */
|
||||
/* and then return the NULL pointer for our user */
|
||||
if ( ( gix->pots == NULL) ||
|
||||
( gix->gc == NULL) )
|
||||
{
|
||||
if ( gix->pots != NULL) free(gix->pots);
|
||||
if ( gix->gc != NULL) free(gix->gc);
|
||||
free(gix);
|
||||
if ( gix->pots != NULL) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gix->pots);
|
||||
}
|
||||
|
||||
if ( gix->gc != NULL) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gix->gc);
|
||||
}
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gix);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -555,10 +566,15 @@ GeoIndex * GeoIndex_new(void)
|
|||
void GeoIndex_free(GeoIndex * gi)
|
||||
{
|
||||
GeoIx * gix;
|
||||
|
||||
if (gi == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
gix = (GeoIx *) gi;
|
||||
free(gix->gc);
|
||||
free(gix->pots);
|
||||
free(gix);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gix->gc);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gix->pots);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gix);
|
||||
}
|
||||
/* =================================================== */
|
||||
/* GeoMkHilbert routine */
|
||||
|
@ -785,16 +801,30 @@ GeoResults * GeoResultsCons(int alloc)
|
|||
GeoResults * gres;
|
||||
int * sa;
|
||||
double * dd;
|
||||
gres=malloc(sizeof(GeoResults));
|
||||
sa=malloc(alloc*sizeof(int));
|
||||
dd=malloc(alloc*sizeof(double));
|
||||
|
||||
if (alloc <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gres = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(GeoResults), false);
|
||||
sa = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, alloc*sizeof(int), false);
|
||||
dd = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, alloc*sizeof(double), false);
|
||||
if( (gres==NULL) ||
|
||||
(sa==NULL) ||
|
||||
(dd==NULL) )
|
||||
{
|
||||
if(gres!=NULL) free(gres);
|
||||
if(sa!=NULL) free(sa);
|
||||
if(dd!=NULL) free(dd);
|
||||
if(gres!=NULL) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gres);
|
||||
}
|
||||
|
||||
if(sa!=NULL) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, sa);
|
||||
}
|
||||
|
||||
if(dd!=NULL) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, dd);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
gres->pointsct = 0;
|
||||
|
@ -939,15 +969,28 @@ GeoCoordinates * GeoAnswers (GeoIx * gix, GeoResults * gr)
|
|||
GeoCoordinate * gc;
|
||||
int i,j,slot;
|
||||
double mole;
|
||||
ans = malloc(sizeof(GeoCoordinates));
|
||||
gc = malloc(gr->pointsct * sizeof(GeoCoordinate));
|
||||
|
||||
if (gr->pointsct == 0) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gr->slot);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gr->snmd);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ans = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(GeoCoordinates), false);
|
||||
gc = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, gr->pointsct * sizeof(GeoCoordinate), false);
|
||||
|
||||
if( (ans==NULL) || (gc==NULL) )
|
||||
{
|
||||
if(ans!=NULL) free(ans);
|
||||
if(gc!=NULL) free(gc);
|
||||
free(gr->slot);
|
||||
free(gr->snmd);
|
||||
free(gr);
|
||||
if(ans!=NULL) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, ans);
|
||||
}
|
||||
if(gc!=NULL) {
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gc);
|
||||
}
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gr->slot);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gr->snmd);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gr);
|
||||
return NULL;
|
||||
}
|
||||
ans->length = gr->pointsct;
|
||||
|
@ -970,8 +1013,10 @@ GeoCoordinates * GeoAnswers (GeoIx * gix, GeoResults * gr)
|
|||
j++;
|
||||
}
|
||||
ans->distances = gr->snmd;
|
||||
free(gr->slot);
|
||||
free(gr);
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gr->slot);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gr);
|
||||
|
||||
return ans;
|
||||
}
|
||||
/* =================================================== */
|
||||
|
@ -1076,9 +1121,9 @@ GeoCoordinates * GeoIndex_PointsWithinRadius(GeoIndex * gi,
|
|||
r = GeoResultsGrow(gres);
|
||||
if(r==-1)
|
||||
{
|
||||
free(gres->snmd);
|
||||
free(gres->slot);
|
||||
free(gres);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gres->snmd);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gres->slot);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, gres);
|
||||
return NULL;
|
||||
}
|
||||
gres->slot[gres->pointsct]=slot;
|
||||
|
@ -2041,9 +2086,9 @@ int GeoIndex_remove(GeoIndex * gi, GeoCoordinate * c)
|
|||
/* =================================================== */
|
||||
void GeoIndex_CoordinatesFree(GeoCoordinates * clist)
|
||||
{
|
||||
free(clist->coordinates);
|
||||
free(clist->distances);
|
||||
free(clist);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, clist->coordinates);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, clist->distances);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, clist);
|
||||
}
|
||||
/* =================================================== */
|
||||
/* GeoIndex_hint does nothing! */
|
||||
|
|
|
@ -28,14 +28,7 @@
|
|||
/* GeoIndex.h - header file for GeoIndex algorithms */
|
||||
/* Version 2.1 8.1.2012 R. A. Parker */
|
||||
|
||||
#ifdef GEO_STANDALONE
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#else
|
||||
#include "BasicsC/common.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -264,6 +264,7 @@ void runTest (int mode)
|
|||
double la,lo;
|
||||
double d1;
|
||||
int i,j,r;
|
||||
void* nullp = 0;
|
||||
|
||||
errors=0;
|
||||
|
||||
|
@ -332,9 +333,11 @@ void runTest (int mode)
|
|||
/* do both searches with an empty index */
|
||||
|
||||
list1 = GeoIndex_NearestCountPoints(gi,&gcp1,3);
|
||||
gccheck(20,list1, 0,"AAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// gccheck(20,list1,0,"AAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
BOOST_CHECK_EQUAL(nullp, list1); // no results, check against null pointer
|
||||
list1 = GeoIndex_PointsWithinRadius(gi,&gcp1,100000.0);
|
||||
gccheck(21,list1,0,"AAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// gccheck(21,list1,0,"AAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
BOOST_CHECK_EQUAL(nullp, list1); // no results, check against null pointer
|
||||
|
||||
/* stick in Jo'burg */
|
||||
gcp4.data=ix + 4;
|
||||
|
@ -349,9 +352,11 @@ void runTest (int mode)
|
|||
r = GeoIndex_remove(gi,&gcp4);
|
||||
icheck(25,0,r);
|
||||
list1 = GeoIndex_NearestCountPoints(gi,&gcp1,3);
|
||||
gccheck(26,list1, 0,"AAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// gccheck(26,list1, 0,"AAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
BOOST_CHECK_EQUAL(nullp, list1); // no results, check against null pointer
|
||||
list1 = GeoIndex_PointsWithinRadius(gi,&gcp1,100000.0);
|
||||
gccheck(27,list1,0,"AAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// gccheck(27,list1,0,"AAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
BOOST_CHECK_EQUAL(nullp, list1); // no results, check against null pointer
|
||||
|
||||
/* try to delete from an empty index */
|
||||
|
||||
|
@ -1037,7 +1042,10 @@ void runTest (int mode)
|
|||
{
|
||||
coonum(&gcp1,j);
|
||||
list1 = GeoIndex_PointsWithinRadius(gi,&gcp1,127000.0);
|
||||
GeoIndex_CoordinatesFree(list1);
|
||||
if (list1) {
|
||||
// only free if pointer is valid
|
||||
GeoIndex_CoordinatesFree(list1);
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_TEST_MESSAGE("End of timing test");
|
||||
|
@ -1052,7 +1060,10 @@ void runTest (int mode)
|
|||
{
|
||||
coonum(&gcp1,j);
|
||||
list1 = GeoIndex_NearestCountPoints(gi,&gcp1,2);
|
||||
GeoIndex_CoordinatesFree(list1);
|
||||
if (list1) {
|
||||
// only free if pointer is valid
|
||||
GeoIndex_CoordinatesFree(list1);
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_TEST_MESSAGE("End of timing test");
|
||||
|
|
|
@ -279,7 +279,13 @@ static v8::Handle<v8::Object> CreateErrorObject (int errorNumber, string const&
|
|||
|
||||
v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
|
||||
string msg = TRI_errno_string(errorNumber) + string(": ") + message;
|
||||
string msg;
|
||||
if (message.size()) {
|
||||
msg = message;
|
||||
}
|
||||
else {
|
||||
msg = TRI_errno_string(errorNumber) + string(": ") + message;
|
||||
}
|
||||
v8::Handle<v8::String> errorMessage = v8::String::New(msg.c_str());
|
||||
|
||||
v8::Handle<v8::Object> errorObject = v8::Exception::Error(errorMessage)->ToObject();
|
||||
|
@ -287,6 +293,7 @@ static v8::Handle<v8::Object> CreateErrorObject (int errorNumber, string const&
|
|||
|
||||
errorObject->Set(v8::String::New("errorNum"), v8::Number::New(errorNumber));
|
||||
errorObject->Set(v8::String::New("errorMessage"), errorMessage);
|
||||
|
||||
errorObject->SetPrototype(proto);
|
||||
|
||||
return errorObject;
|
||||
|
@ -2930,6 +2937,13 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
|
|||
return scope.Close(WrapGeneralCursor(cursor));
|
||||
}
|
||||
|
||||
if (tryCatch.HasCaught()) {
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_RUNTIME_ERROR, TRI_ObjectToString(tryCatch.Exception()).c_str());
|
||||
v8::Handle<v8::Object> errorObject = CreateErrorObjectAhuacatl(&context->_error);
|
||||
|
||||
return scope.Close(errorObject);
|
||||
}
|
||||
|
||||
return scope.Close(v8::ThrowException(v8::String::New("cannot create cursor")));
|
||||
}
|
||||
|
||||
|
@ -6384,21 +6398,6 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
|
|||
v8g->ToKey = v8::Persistent<v8::String>::New(v8::String::New("_to"));
|
||||
}
|
||||
|
||||
// .............................................................................
|
||||
// generate the query error template
|
||||
// .............................................................................
|
||||
|
||||
ft = v8::FunctionTemplate::New();
|
||||
ft->SetClassName(v8::String::New("AvocadoError"));
|
||||
|
||||
rt = ft->InstanceTemplate();
|
||||
|
||||
v8g->ErrorTempl = v8::Persistent<v8::ObjectTemplate>::New(rt);
|
||||
|
||||
// must come after SetInternalFieldCount
|
||||
context->Global()->Set(v8::String::New("AvocadoError"),
|
||||
ft->GetFunction());
|
||||
|
||||
// .............................................................................
|
||||
// generate the TRI_vocbase_t template
|
||||
// .............................................................................
|
||||
|
|
|
@ -59,7 +59,7 @@ ModuleCache["/internal"].exports.errors = {
|
|||
"ERROR_AVOCADO_CAP_CONSTRAINT_ALREADY_DEFINED" : { "code" : 1215, "message" : "cap constraint already defined" },
|
||||
"ERROR_AVOCADO_DATAFILE_FULL" : { "code" : 1300, "message" : "datafile full" },
|
||||
"ERROR_QUERY_KILLED" : { "code" : 1500, "message" : "query killed" },
|
||||
"ERROR_QUERY_PARSE" : { "code" : 1501, "message" : "parse error: %s" },
|
||||
"ERROR_QUERY_PARSE" : { "code" : 1501, "message" : "%s" },
|
||||
"ERROR_QUERY_EMPTY" : { "code" : 1502, "message" : "query is empty" },
|
||||
"ERROR_QUERY_SPECIFICATION_INVALID" : { "code" : 1503, "message" : "query specification invalid" },
|
||||
"ERROR_QUERY_NUMBER_OUT_OF_RANGE" : { "code" : 1504, "message" : "number '%s' is out of range" },
|
||||
|
@ -77,7 +77,7 @@ ModuleCache["/internal"].exports.errors = {
|
|||
"ERROR_QUERY_BIND_PARAMETER_VALUE_INVALID" : { "code" : 1516, "message" : "invalid value for bind parameter '%s'" },
|
||||
"ERROR_QUERY_BIND_PARAMETER_NUMBER_OUT_OF_RANGE" : { "code" : 1517, "message" : "bind parameter number '%s' out of range" },
|
||||
"ERROR_QUERY_FUNCTION_NAME_UNKNOWN" : { "code" : 1518, "message" : "usage of unknown function '%s'" },
|
||||
"ERROR_QUERY_RUNTIME_ERROR" : { "code" : 1520, "message" : "runtime error in query" },
|
||||
"ERROR_QUERY_RUNTIME_ERROR" : { "code" : 1520, "message" : "runtime error '%s'" },
|
||||
"ERROR_QUERY_LIMIT_VALUE_OUT_OF_RANGE" : { "code" : 1521, "message" : "limit value '%s' is out of range" },
|
||||
"ERROR_QUERY_VARIABLE_REDECLARED" : { "code" : 1522, "message" : "variable '%s' is assigned multiple times" },
|
||||
"ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED" : { "code" : 1523, "message" : "document attribute '%s' is assigned multiple times" },
|
||||
|
|
|
@ -60,7 +60,7 @@ static string JS_common_bootstrap_errors =
|
|||
" \"ERROR_AVOCADO_CAP_CONSTRAINT_ALREADY_DEFINED\" : { \"code\" : 1215, \"message\" : \"cap constraint already defined\" }, \n"
|
||||
" \"ERROR_AVOCADO_DATAFILE_FULL\" : { \"code\" : 1300, \"message\" : \"datafile full\" }, \n"
|
||||
" \"ERROR_QUERY_KILLED\" : { \"code\" : 1500, \"message\" : \"query killed\" }, \n"
|
||||
" \"ERROR_QUERY_PARSE\" : { \"code\" : 1501, \"message\" : \"parse error: %s\" }, \n"
|
||||
" \"ERROR_QUERY_PARSE\" : { \"code\" : 1501, \"message\" : \"%s\" }, \n"
|
||||
" \"ERROR_QUERY_EMPTY\" : { \"code\" : 1502, \"message\" : \"query is empty\" }, \n"
|
||||
" \"ERROR_QUERY_SPECIFICATION_INVALID\" : { \"code\" : 1503, \"message\" : \"query specification invalid\" }, \n"
|
||||
" \"ERROR_QUERY_NUMBER_OUT_OF_RANGE\" : { \"code\" : 1504, \"message\" : \"number '%s' is out of range\" }, \n"
|
||||
|
@ -78,7 +78,7 @@ static string JS_common_bootstrap_errors =
|
|||
" \"ERROR_QUERY_BIND_PARAMETER_VALUE_INVALID\" : { \"code\" : 1516, \"message\" : \"invalid value for bind parameter '%s'\" }, \n"
|
||||
" \"ERROR_QUERY_BIND_PARAMETER_NUMBER_OUT_OF_RANGE\" : { \"code\" : 1517, \"message\" : \"bind parameter number '%s' out of range\" }, \n"
|
||||
" \"ERROR_QUERY_FUNCTION_NAME_UNKNOWN\" : { \"code\" : 1518, \"message\" : \"usage of unknown function '%s'\" }, \n"
|
||||
" \"ERROR_QUERY_RUNTIME_ERROR\" : { \"code\" : 1520, \"message\" : \"runtime error in query\" }, \n"
|
||||
" \"ERROR_QUERY_RUNTIME_ERROR\" : { \"code\" : 1520, \"message\" : \"runtime error '%s'\" }, \n"
|
||||
" \"ERROR_QUERY_LIMIT_VALUE_OUT_OF_RANGE\" : { \"code\" : 1521, \"message\" : \"limit value '%s' is out of range\" }, \n"
|
||||
" \"ERROR_QUERY_VARIABLE_REDECLARED\" : { \"code\" : 1522, \"message\" : \"variable '%s' is assigned multiple times\" }, \n"
|
||||
" \"ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED\" : { \"code\" : 1523, \"message\" : \"document attribute '%s' is assigned multiple times\" }, \n"
|
||||
|
|
Loading…
Reference in New Issue