mirror of https://gitee.com/bigwinds/arangodb
1st steps for reference access optimisations
This commit is contained in:
parent
2d7505a598
commit
3cb8b653cd
|
@ -49,6 +49,8 @@ static char* AccessName (const TRI_aql_access_e type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TRI_AQL_ACCESS_ALL:
|
case TRI_AQL_ACCESS_ALL:
|
||||||
return "all";
|
return "all";
|
||||||
|
case TRI_AQL_ACCESS_REFERENCE:
|
||||||
|
return "reference";
|
||||||
case TRI_AQL_ACCESS_IMPOSSIBLE:
|
case TRI_AQL_ACCESS_IMPOSSIBLE:
|
||||||
return "impossible";
|
return "impossible";
|
||||||
case TRI_AQL_ACCESS_EXACT:
|
case TRI_AQL_ACCESS_EXACT:
|
||||||
|
@ -59,9 +61,10 @@ static char* AccessName (const TRI_aql_access_e type) {
|
||||||
return "single range";
|
return "single range";
|
||||||
case TRI_AQL_ACCESS_RANGE_DOUBLE:
|
case TRI_AQL_ACCESS_RANGE_DOUBLE:
|
||||||
return "double range";
|
return "double range";
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -94,17 +97,21 @@ static void FreeAccessMembers (TRI_aql_field_access_t* const fieldAccess) {
|
||||||
|
|
||||||
switch (fieldAccess->_type) {
|
switch (fieldAccess->_type) {
|
||||||
case TRI_AQL_ACCESS_EXACT:
|
case TRI_AQL_ACCESS_EXACT:
|
||||||
case TRI_AQL_ACCESS_LIST:
|
case TRI_AQL_ACCESS_LIST: {
|
||||||
if (fieldAccess->_value._value) {
|
if (fieldAccess->_value._value) {
|
||||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_value._value);
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_value._value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRI_AQL_ACCESS_RANGE_SINGLE:
|
}
|
||||||
|
|
||||||
|
case TRI_AQL_ACCESS_RANGE_SINGLE: {
|
||||||
if (fieldAccess->_value._singleRange._value) {
|
if (fieldAccess->_value._singleRange._value) {
|
||||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_value._singleRange._value);
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_value._singleRange._value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRI_AQL_ACCESS_RANGE_DOUBLE:
|
}
|
||||||
|
|
||||||
|
case TRI_AQL_ACCESS_RANGE_DOUBLE: {
|
||||||
if (fieldAccess->_value._between._lower._value) {
|
if (fieldAccess->_value._between._lower._value) {
|
||||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, 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);
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_value._between._upper._value);
|
||||||
}
|
}
|
||||||
break;
|
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_ALL:
|
||||||
case TRI_AQL_ACCESS_IMPOSSIBLE:
|
case TRI_AQL_ACCESS_IMPOSSIBLE: {
|
||||||
default: {
|
|
||||||
// nada
|
// nada
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +145,7 @@ static TRI_aql_field_access_t* CreateFieldAccess (TRI_aql_context_t* const conte
|
||||||
const char* const fullName) {
|
const char* const fullName) {
|
||||||
TRI_aql_field_access_t* fieldAccess;
|
TRI_aql_field_access_t* fieldAccess;
|
||||||
|
|
||||||
fieldAccess = (TRI_aql_field_access_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_field_access_t), false);
|
fieldAccess = (TRI_aql_field_access_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_field_access_t), false);
|
||||||
if (fieldAccess == NULL) {
|
if (fieldAccess == NULL) {
|
||||||
// OOM
|
// OOM
|
||||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||||
|
@ -198,6 +213,23 @@ static TRI_aql_field_access_t* MergeAndAll (TRI_aql_context_t* const context,
|
||||||
return rhs;
|
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
|
/// @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;
|
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
|
/// @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);
|
return MergeAndImpossible(context, lhs, rhs);
|
||||||
case TRI_AQL_ACCESS_ALL:
|
case TRI_AQL_ACCESS_ALL:
|
||||||
return MergeAndAll(context, lhs, rhs);
|
return MergeAndAll(context, lhs, rhs);
|
||||||
|
case TRI_AQL_ACCESS_REFERENCE:
|
||||||
|
return MergeAndReference(context, lhs, rhs);
|
||||||
case TRI_AQL_ACCESS_EXACT:
|
case TRI_AQL_ACCESS_EXACT:
|
||||||
return MergeAndExact(context, lhs, rhs);
|
return MergeAndExact(context, lhs, rhs);
|
||||||
case TRI_AQL_ACCESS_LIST:
|
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);
|
return MergeOrImpossible(context, lhs, rhs);
|
||||||
case TRI_AQL_ACCESS_ALL:
|
case TRI_AQL_ACCESS_ALL:
|
||||||
return MergeOrAll(context, lhs, rhs);
|
return MergeOrAll(context, lhs, rhs);
|
||||||
|
case TRI_AQL_ACCESS_REFERENCE:
|
||||||
|
return MergeOrReference(context, lhs, rhs);
|
||||||
case TRI_AQL_ACCESS_EXACT:
|
case TRI_AQL_ACCESS_EXACT:
|
||||||
return MergeOrExact(context, lhs, rhs);
|
return MergeOrExact(context, lhs, rhs);
|
||||||
case TRI_AQL_ACCESS_LIST:
|
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) {
|
if (fieldAccess == NULL) {
|
||||||
// OOM
|
// OOM
|
||||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1458,6 +1524,7 @@ static TRI_aql_field_access_t* CreateAccessForNode (TRI_aql_context_t* const con
|
||||||
if (fieldAccess->_fullName == NULL) {
|
if (fieldAccess->_fullName == NULL) {
|
||||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, fieldAccess);
|
TRI_Free(TRI_UNKNOWN_MEM_ZONE, fieldAccess);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
SetNameLength(fieldAccess);
|
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) {
|
if (operator == TRI_AQL_NODE_OPERATOR_BINARY_NE) {
|
||||||
// create an all items access, and we're done
|
// create an all items access, and we're done
|
||||||
fieldAccess->_type = TRI_AQL_ACCESS_ALL;
|
fieldAccess->_type = TRI_AQL_ACCESS_ALL;
|
||||||
|
|
||||||
return fieldAccess;
|
return fieldAccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all other operation types require a value...
|
// all other operation types require a value...
|
||||||
value = TRI_NodeJsonAql(context, node);
|
value = TRI_NodeJsonAql(context, node);
|
||||||
if (!value) {
|
if (value == NULL) {
|
||||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1859,14 +1928,16 @@ TRI_aql_field_access_t* TRI_CloneAccessAql (TRI_aql_context_t* const context,
|
||||||
|
|
||||||
switch (source->_type) {
|
switch (source->_type) {
|
||||||
case TRI_AQL_ACCESS_EXACT:
|
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);
|
fieldAccess->_value._value = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, source->_value._value);
|
||||||
if (fieldAccess->_value._value == NULL) {
|
if (fieldAccess->_value._value == NULL) {
|
||||||
// OOM
|
// OOM
|
||||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRI_AQL_ACCESS_RANGE_SINGLE:
|
}
|
||||||
|
|
||||||
|
case TRI_AQL_ACCESS_RANGE_SINGLE: {
|
||||||
fieldAccess->_value._singleRange._type = source->_value._singleRange._type;
|
fieldAccess->_value._singleRange._type = source->_value._singleRange._type;
|
||||||
fieldAccess->_value._singleRange._value = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, source->_value._singleRange._value);
|
fieldAccess->_value._singleRange._value = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, source->_value._singleRange._value);
|
||||||
if (fieldAccess->_value._singleRange._value == NULL) {
|
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);
|
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||||
}
|
}
|
||||||
break;
|
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._lower._type = source->_value._between._lower._type;
|
||||||
fieldAccess->_value._between._upper._type = source->_value._between._upper._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);
|
fieldAccess->_value._between._lower._value = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, source->_value._between._lower._value);
|
||||||
|
@ -1885,11 +1958,18 @@ TRI_aql_field_access_t* TRI_CloneAccessAql (TRI_aql_context_t* const context,
|
||||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TRI_AQL_ACCESS_REFERENCE: {
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case TRI_AQL_ACCESS_ALL:
|
case TRI_AQL_ACCESS_ALL:
|
||||||
case TRI_AQL_ACCESS_IMPOSSIBLE:
|
case TRI_AQL_ACCESS_IMPOSSIBLE: {
|
||||||
default:
|
|
||||||
// nada
|
// nada
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fieldAccess;
|
return fieldAccess;
|
||||||
|
|
|
@ -68,12 +68,13 @@ TRI_aql_logical_e;
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TRI_AQL_ACCESS_IMPOSSIBLE, // no values must be accessed
|
TRI_AQL_ACCESS_IMPOSSIBLE, // no value needs to be accessed (impossible range)
|
||||||
TRI_AQL_ACCESS_EXACT, // one value must be accessed
|
TRI_AQL_ACCESS_EXACT, // one value is accessed
|
||||||
TRI_AQL_ACCESS_LIST, // a list of values must be accessed
|
TRI_AQL_ACCESS_LIST, // a list of values is accessed
|
||||||
TRI_AQL_ACCESS_RANGE_SINGLE, // a range with one bound must be accessed
|
TRI_AQL_ACCESS_RANGE_SINGLE, // a range with one boundary is accessed
|
||||||
TRI_AQL_ACCESS_RANGE_DOUBLE, // a two bounded range must be accessed
|
TRI_AQL_ACCESS_RANGE_DOUBLE, // a two bounded range is accessed
|
||||||
TRI_AQL_ACCESS_ALL // all values must be 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;
|
TRI_aql_access_e;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "Ahuacatl/ahuacatl-explain.h"
|
#include "Ahuacatl/ahuacatl-explain.h"
|
||||||
|
#include "Ahuacatl/ahuacatl-collections.h"
|
||||||
#include "Ahuacatl/ahuacatl-conversions.h"
|
#include "Ahuacatl/ahuacatl-conversions.h"
|
||||||
#include "Ahuacatl/ahuacatl-scope.h"
|
#include "Ahuacatl/ahuacatl-scope.h"
|
||||||
#include "Ahuacatl/ahuacatl-statement-walker.h"
|
#include "Ahuacatl/ahuacatl-statement-walker.h"
|
||||||
|
|
Loading…
Reference in New Issue