1
0
Fork 0

1st steps for reference access optimisations

This commit is contained in:
Jan Steemann 2012-06-12 17:58:30 +02:00
parent 2d7505a598
commit 3cb8b653cd
3 changed files with 102 additions and 20 deletions

View File

@ -49,6 +49,8 @@ static char* AccessName (const TRI_aql_access_e type) {
switch (type) {
case TRI_AQL_ACCESS_ALL:
return "all";
case TRI_AQL_ACCESS_REFERENCE:
return "reference";
case TRI_AQL_ACCESS_IMPOSSIBLE:
return "impossible";
case TRI_AQL_ACCESS_EXACT:
@ -59,9 +61,10 @@ static char* AccessName (const TRI_aql_access_e type) {
return "single range";
case TRI_AQL_ACCESS_RANGE_DOUBLE:
return "double range";
default:
return "unknown";
}
assert(false);
return NULL;
}
#endif
@ -94,17 +97,21 @@ static void FreeAccessMembers (TRI_aql_field_access_t* const fieldAccess) {
switch (fieldAccess->_type) {
case TRI_AQL_ACCESS_EXACT:
case TRI_AQL_ACCESS_LIST:
case TRI_AQL_ACCESS_LIST: {
if (fieldAccess->_value._value) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_value._value);
}
break;
case TRI_AQL_ACCESS_RANGE_SINGLE:
}
case TRI_AQL_ACCESS_RANGE_SINGLE: {
if (fieldAccess->_value._singleRange._value) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_value._singleRange._value);
}
break;
case TRI_AQL_ACCESS_RANGE_DOUBLE:
}
case TRI_AQL_ACCESS_RANGE_DOUBLE: {
if (fieldAccess->_value._between._lower._value) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_value._between._lower._value);
}
@ -112,11 +119,19 @@ static void FreeAccessMembers (TRI_aql_field_access_t* const fieldAccess) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_value._between._upper._value);
}
break;
}
case TRI_AQL_ACCESS_REFERENCE: {
if (fieldAccess->_value._value) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_value._value);
}
break;
}
case TRI_AQL_ACCESS_ALL:
case TRI_AQL_ACCESS_IMPOSSIBLE:
default: {
case TRI_AQL_ACCESS_IMPOSSIBLE: {
// nada
break;
}
}
}
@ -198,6 +213,23 @@ static TRI_aql_field_access_t* MergeAndAll (TRI_aql_context_t* const context,
return rhs;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief merge two access structures using a logical AND
///
/// left hand operand is a reference, so it will always be returned
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_field_access_t* MergeAndReference (TRI_aql_context_t* const context,
TRI_aql_field_access_t* lhs,
TRI_aql_field_access_t* rhs) {
assert(lhs->_type == TRI_AQL_ACCESS_REFERENCE);
// reference always wins
TRI_FreeAccessAql(rhs);
return lhs;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief merge two access structures using a logical AND
///
@ -808,6 +840,35 @@ static TRI_aql_field_access_t* MergeOrAll (TRI_aql_context_t* const context,
return lhs;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief merge two access structures using a logical OR
///
/// left hand operand is reference access
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_field_access_t* MergeOrReference (TRI_aql_context_t* const context,
TRI_aql_field_access_t* lhs,
TRI_aql_field_access_t* rhs) {
assert(lhs->_type == TRI_AQL_ACCESS_REFERENCE);
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE) {
// if rhs is also a reference, we can keep it if both refer to the same value
if (TRI_EqualString(lhs->_value._value->_value._string.data, rhs->_value._value->_value._string.data)) {
TRI_FreeAccessAql(rhs);
return lhs;
}
}
// for everything else, we have to use the ALL range unfortunately
TRI_FreeAccessAql(rhs);
FreeAccessMembers(lhs);
lhs->_type = TRI_AQL_ACCESS_ALL;
return lhs;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief merge two access structures using a logical OR
///
@ -1131,6 +1192,8 @@ static TRI_aql_field_access_t* MergeAttributeAccessAnd (TRI_aql_context_t* const
return MergeAndImpossible(context, lhs, rhs);
case TRI_AQL_ACCESS_ALL:
return MergeAndAll(context, lhs, rhs);
case TRI_AQL_ACCESS_REFERENCE:
return MergeAndReference(context, lhs, rhs);
case TRI_AQL_ACCESS_EXACT:
return MergeAndExact(context, lhs, rhs);
case TRI_AQL_ACCESS_LIST:
@ -1172,6 +1235,8 @@ static TRI_aql_field_access_t* MergeAttributeAccessOr (TRI_aql_context_t* const
return MergeOrImpossible(context, lhs, rhs);
case TRI_AQL_ACCESS_ALL:
return MergeOrAll(context, lhs, rhs);
case TRI_AQL_ACCESS_REFERENCE:
return MergeOrReference(context, lhs, rhs);
case TRI_AQL_ACCESS_EXACT:
return MergeOrExact(context, lhs, rhs);
case TRI_AQL_ACCESS_LIST:
@ -1451,6 +1516,7 @@ static TRI_aql_field_access_t* CreateAccessForNode (TRI_aql_context_t* const con
if (fieldAccess == NULL) {
// OOM
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
@ -1458,6 +1524,7 @@ static TRI_aql_field_access_t* CreateAccessForNode (TRI_aql_context_t* const con
if (fieldAccess->_fullName == NULL) {
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, fieldAccess);
return NULL;
}
SetNameLength(fieldAccess);
@ -1465,13 +1532,15 @@ static TRI_aql_field_access_t* CreateAccessForNode (TRI_aql_context_t* const con
if (operator == TRI_AQL_NODE_OPERATOR_BINARY_NE) {
// create an all items access, and we're done
fieldAccess->_type = TRI_AQL_ACCESS_ALL;
return fieldAccess;
}
// all other operation types require a value...
value = TRI_NodeJsonAql(context, node);
if (!value) {
if (value == NULL) {
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
@ -1859,14 +1928,16 @@ TRI_aql_field_access_t* TRI_CloneAccessAql (TRI_aql_context_t* const context,
switch (source->_type) {
case TRI_AQL_ACCESS_EXACT:
case TRI_AQL_ACCESS_LIST:
case TRI_AQL_ACCESS_LIST: {
fieldAccess->_value._value = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, source->_value._value);
if (fieldAccess->_value._value == NULL) {
// OOM
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
}
break;
case TRI_AQL_ACCESS_RANGE_SINGLE:
}
case TRI_AQL_ACCESS_RANGE_SINGLE: {
fieldAccess->_value._singleRange._type = source->_value._singleRange._type;
fieldAccess->_value._singleRange._value = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, source->_value._singleRange._value);
if (fieldAccess->_value._singleRange._value == NULL) {
@ -1874,7 +1945,9 @@ TRI_aql_field_access_t* TRI_CloneAccessAql (TRI_aql_context_t* const context,
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
}
break;
case TRI_AQL_ACCESS_RANGE_DOUBLE:
}
case TRI_AQL_ACCESS_RANGE_DOUBLE: {
fieldAccess->_value._between._lower._type = source->_value._between._lower._type;
fieldAccess->_value._between._upper._type = source->_value._between._upper._type;
fieldAccess->_value._between._lower._value = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, source->_value._between._lower._value);
@ -1885,12 +1958,19 @@ TRI_aql_field_access_t* TRI_CloneAccessAql (TRI_aql_context_t* const context,
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
}
break;
}
case TRI_AQL_ACCESS_REFERENCE: {
// TODO
break;
}
case TRI_AQL_ACCESS_ALL:
case TRI_AQL_ACCESS_IMPOSSIBLE:
default:
case TRI_AQL_ACCESS_IMPOSSIBLE: {
// nada
break;
}
}
return fieldAccess;
}

View File

@ -68,12 +68,13 @@ TRI_aql_logical_e;
////////////////////////////////////////////////////////////////////////////////
typedef enum {
TRI_AQL_ACCESS_IMPOSSIBLE, // no values must be accessed
TRI_AQL_ACCESS_EXACT, // one value must be accessed
TRI_AQL_ACCESS_LIST, // a list of values must be accessed
TRI_AQL_ACCESS_RANGE_SINGLE, // a range with one bound must be accessed
TRI_AQL_ACCESS_RANGE_DOUBLE, // a two bounded range must be accessed
TRI_AQL_ACCESS_ALL // all values must be accessed
TRI_AQL_ACCESS_IMPOSSIBLE, // no value needs to be accessed (impossible range)
TRI_AQL_ACCESS_EXACT, // one value is accessed
TRI_AQL_ACCESS_LIST, // a list of values is accessed
TRI_AQL_ACCESS_RANGE_SINGLE, // a range with one boundary is accessed
TRI_AQL_ACCESS_RANGE_DOUBLE, // a two bounded range is accessed
TRI_AQL_ACCESS_REFERENCE, // a reference can be used for access (a.x == b.x)
TRI_AQL_ACCESS_ALL // all values must be accessed (full scan)
}
TRI_aql_access_e;

View File

@ -26,6 +26,7 @@
////////////////////////////////////////////////////////////////////////////////
#include "Ahuacatl/ahuacatl-explain.h"
#include "Ahuacatl/ahuacatl-collections.h"
#include "Ahuacatl/ahuacatl-conversions.h"
#include "Ahuacatl/ahuacatl-scope.h"
#include "Ahuacatl/ahuacatl-statement-walker.h"