1
0
Fork 0

Merge branch 'devel' of github.com:triAGENS/AvocadoDB into devel

This commit is contained in:
Heiko Kernbach 2012-05-07 15:12:53 +02:00
commit 22f4bc3651
13 changed files with 377 additions and 90 deletions

View File

@ -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;

View File

@ -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:

View File

@ -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>

View File

@ -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;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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."

View File

@ -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");

View File

@ -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.

View File

@ -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! */

View File

@ -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" {

View File

@ -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");

View File

@ -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
// .............................................................................

View File

@ -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" },

View File

@ -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"