1
0
Fork 0

refactored range optimizer

This commit is contained in:
Jan Steemann 2012-05-09 11:16:37 +02:00
parent 4174b215f7
commit 926a158a99
5 changed files with 293 additions and 315 deletions

View File

@ -37,41 +37,29 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief hash a field name /// @brief create a vector with an attribute access struct in it
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static uint64_t HashFieldAccess (TRI_associative_pointer_t* array, static TRI_vector_pointer_t* Vectorize (TRI_aql_context_t* const context,
void const* element) { TRI_aql_field_access_t* fieldAccess) {
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) element; TRI_vector_pointer_t* vector;
return TRI_FnvHashString(fieldAccess->_fieldName); assert(context);
if (!fieldAccess) {
return NULL;
} }
//////////////////////////////////////////////////////////////////////////////// vector = (TRI_vector_pointer_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_vector_pointer_t), false);
/// @brief comparison function used to determine field name equality if (!vector) {
//////////////////////////////////////////////////////////////////////////////// // OOM
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
static bool EqualFieldAccess (TRI_associative_pointer_t* array, return NULL;
void const* key,
void const* element) {
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) element;
return TRI_EqualString(key, fieldAccess->_fieldName);
} }
//////////////////////////////////////////////////////////////////////////////// TRI_InitVectorPointer(vector, TRI_UNKNOWN_MEM_ZONE);
/// @brief return the logical type for a sub operation TRI_PushBackVectorPointer(vector, fieldAccess);
////////////////////////////////////////////////////////////////////////////////
static inline TRI_aql_logical_e SubOperator (const TRI_aql_logical_e preferredType, return vector;
const TRI_aql_logical_e parentType) {
if (parentType == TRI_AQL_LOGICAL_NOT) {
// logical NOT is sticky
return parentType;
}
// all other operators are not
return preferredType;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -146,24 +134,6 @@ static void FreeAccess (TRI_aql_context_t* const context,
TRI_Free(TRI_UNKNOWN_MEM_ZONE, fieldAccess); TRI_Free(TRI_UNKNOWN_MEM_ZONE, fieldAccess);
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief merge two access structures using a logical NOT
///
/// this always returns the all items range because we cannot evaluate the
/// negated condition
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_field_access_t* MergeNot (TRI_aql_context_t* const context,
TRI_aql_field_access_t* lhs,
TRI_aql_field_access_t* rhs) {
// always returns all
FreeAccess(context, rhs);
FreeAccessMembers(lhs);
lhs->_type = TRI_AQL_ACCESS_ALL;
return lhs;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief merge two access structures using a logical AND /// @brief merge two access structures using a logical AND
@ -1105,28 +1075,20 @@ static TRI_aql_field_access_t* MergeOrRangeDouble (TRI_aql_context_t* const cont
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief merge two access structures using either logical AND or OR /// @brief free access structure with its members and the pointer
///
/// TODO: fix docs
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static TRI_aql_field_access_t* MergeAccess (TRI_aql_context_t* const context, static TRI_aql_field_access_t* MergeAttributeAccessAnd (TRI_aql_context_t* const context,
const TRI_aql_logical_e logicalType,
TRI_aql_field_access_t* lhs, TRI_aql_field_access_t* lhs,
TRI_aql_field_access_t* rhs) { TRI_aql_field_access_t* rhs) {
assert(context); assert(context);
assert(lhs); assert(lhs);
assert(rhs); assert(rhs);
assert(logicalType == TRI_AQL_LOGICAL_AND ||
logicalType == TRI_AQL_LOGICAL_OR ||
logicalType == TRI_AQL_LOGICAL_NOT);
assert(lhs->_fieldName != NULL); assert(lhs->_fieldName != NULL);
assert(rhs->_fieldName != NULL); assert(rhs->_fieldName != NULL);
if (logicalType == TRI_AQL_LOGICAL_NOT) {
// logical NOT is simple. we simply turn everything into an all range
return MergeNot(context, lhs, rhs);
}
if (lhs->_type > rhs->_type) { if (lhs->_type > rhs->_type) {
// swap operands so they are always sorted // swap operands so they are always sorted
TRI_aql_field_access_t* tmp = lhs; TRI_aql_field_access_t* tmp = lhs;
@ -1136,8 +1098,6 @@ static TRI_aql_field_access_t* MergeAccess (TRI_aql_context_t* const context,
assert(lhs->_type <= rhs->_type); assert(lhs->_type <= rhs->_type);
if (logicalType == TRI_AQL_LOGICAL_AND) {
// logical AND
switch (lhs->_type) { switch (lhs->_type) {
case TRI_AQL_ACCESS_IMPOSSIBLE: case TRI_AQL_ACCESS_IMPOSSIBLE:
return MergeAndImpossible(context, lhs, rhs); return MergeAndImpossible(context, lhs, rhs);
@ -1152,9 +1112,35 @@ static TRI_aql_field_access_t* MergeAccess (TRI_aql_context_t* const context,
case TRI_AQL_ACCESS_RANGE_DOUBLE: case TRI_AQL_ACCESS_RANGE_DOUBLE:
return MergeAndRangeDouble(context, lhs, rhs); return MergeAndRangeDouble(context, lhs, rhs);
} }
assert(false);
return NULL;
} }
else {
// logical OR ////////////////////////////////////////////////////////////////////////////////
/// @brief free access structure with its members and the pointer
///
/// TODO: fix docs
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_field_access_t* MergeAttributeAccessOr (TRI_aql_context_t* const context,
TRI_aql_field_access_t* lhs,
TRI_aql_field_access_t* rhs) {
assert(context);
assert(lhs);
assert(rhs);
assert(lhs->_fieldName != NULL);
assert(rhs->_fieldName != NULL);
if (lhs->_type > rhs->_type) {
// swap operands so they are always sorted
TRI_aql_field_access_t* tmp = lhs;
lhs = rhs;
rhs = tmp;
}
assert(lhs->_type <= rhs->_type);
switch (lhs->_type) { switch (lhs->_type) {
case TRI_AQL_ACCESS_IMPOSSIBLE: case TRI_AQL_ACCESS_IMPOSSIBLE:
return MergeOrImpossible(context, lhs, rhs); return MergeOrImpossible(context, lhs, rhs);
@ -1169,12 +1155,119 @@ static TRI_aql_field_access_t* MergeAccess (TRI_aql_context_t* const context,
case TRI_AQL_ACCESS_RANGE_DOUBLE: case TRI_AQL_ACCESS_RANGE_DOUBLE:
return MergeOrRangeDouble(context, lhs, rhs); return MergeOrRangeDouble(context, lhs, rhs);
} }
}
assert(false); assert(false);
return NULL; return NULL;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief process a logical NOT
///
/// TODO: fix docs
////////////////////////////////////////////////////////////////////////////////
static TRI_vector_pointer_t* MakeAllVector (TRI_aql_context_t* const context,
TRI_vector_pointer_t* const fieldAccesses) {
size_t i, n;
if (!fieldAccesses) {
return NULL;
}
n = fieldAccesses->_length;
for (i = 0; i < n; ++i) {
// turn all field access values into an all items access
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(fieldAccesses, i);
// modify the element in place
FreeAccessMembers(fieldAccess);
fieldAccess->_type = TRI_AQL_ACCESS_ALL;
}
return fieldAccesses;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief process a logical OR
///
/// TODO: fix docs
////////////////////////////////////////////////////////////////////////////////
static TRI_vector_pointer_t* MergeVectors (TRI_aql_context_t* const context,
const TRI_aql_logical_e logicalType,
TRI_vector_pointer_t* const lhs,
TRI_vector_pointer_t* const rhs) {
TRI_vector_pointer_t* result;
size_t i, n;
assert(context);
assert(logicalType == TRI_AQL_LOGICAL_AND || logicalType == TRI_AQL_LOGICAL_OR);
// if one of the vectors is empty, simply return the other one
if (!lhs) {
return rhs;
}
if (!rhs) {
return lhs;
}
// both vectors are non empty
result = (TRI_vector_pointer_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_vector_pointer_t), false);
if (!result) {
// OOM
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
TRI_InitVectorPointer(result, TRI_UNKNOWN_MEM_ZONE);
// copy elements from lhs into result vector
n = lhs->_length;
for (i = 0; i < n; ++i) {
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(lhs, i);
TRI_PushBackVectorPointer(result, fieldAccess);
}
// can now free lhs vector
TRI_Free(TRI_UNKNOWN_MEM_ZONE, lhs);
// copy elements from rhs into result vector
n = rhs->_length;
for (i = 0; i < n; ++i) {
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(rhs, i);
size_t j, len;
bool found = false;
// check if element is in result vector already
len = result->_length;
for (j = 0; j < len; ++j) {
TRI_aql_field_access_t* compareAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(result, j);
if (TRI_EqualString(fieldAccess->_fieldName, compareAccess->_fieldName)) {
// found the element
if (logicalType == TRI_AQL_LOGICAL_AND) {
result->_buffer[i] = MergeAttributeAccessAnd(context, fieldAccess, compareAccess);
}
else {
result->_buffer[i] = MergeAttributeAccessOr(context, fieldAccess, compareAccess);
}
found = true;
break;
}
}
if (!found) {
TRI_PushBackVectorPointer(result, fieldAccess);
}
}
// can now free rhs vector
TRI_Free(TRI_UNKNOWN_MEM_ZONE, rhs);
return result;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief create an access structure for the given node and operator /// @brief create an access structure for the given node and operator
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1216,6 +1309,10 @@ static TRI_aql_field_access_t* CreateAccessForNode (TRI_aql_context_t* const con
fieldAccess->_type = TRI_AQL_ACCESS_EXACT; fieldAccess->_type = TRI_AQL_ACCESS_EXACT;
fieldAccess->_value._value = value; fieldAccess->_value._value = value;
} }
else if (operator == AQL_NODE_OPERATOR_BINARY_NE) {
// create an all items access
fieldAccess->_type = TRI_AQL_ACCESS_ALL;
}
else if (operator == AQL_NODE_OPERATOR_BINARY_LT) { else if (operator == AQL_NODE_OPERATOR_BINARY_LT) {
// create a single range access // create a single range access
fieldAccess->_type = TRI_AQL_ACCESS_RANGE_SINGLE; fieldAccess->_type = TRI_AQL_ACCESS_RANGE_SINGLE;
@ -1264,57 +1361,32 @@ static TRI_aql_field_access_t* CreateAccessForNode (TRI_aql_context_t* const con
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief create an access structure for the given node and operator, /// @brief create an access structure for the given node and operator,
/// merge it with potential others already found for the same variable /// merge it with potential others already found for the same variable
///
/// TODO fix docs
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static void NoteAttributeAccess (TRI_aql_context_t* const context, static TRI_aql_field_access_t* GetAttributeAccess (TRI_aql_context_t* const context,
const TRI_aql_logical_e logicalType,
const TRI_aql_attribute_name_t* const field, const TRI_aql_attribute_name_t* const field,
const TRI_aql_node_type_e operator, const TRI_aql_node_type_e operator,
const TRI_aql_node_t* const node) { const TRI_aql_node_t* const node) {
TRI_aql_field_access_t* previous;
TRI_aql_field_access_t* fieldAccess; TRI_aql_field_access_t* fieldAccess;
assert(context); assert(context);
assert(logicalType == TRI_AQL_LOGICAL_AND ||
logicalType == TRI_AQL_LOGICAL_OR ||
logicalType == TRI_AQL_LOGICAL_NOT);
assert(node); assert(node);
if (!field || !field->_name._buffer) { if (!field || !field->_name._buffer) {
return; // this is ok if the node type is not supported
return NULL;
} }
fieldAccess = CreateAccessForNode(context, field, operator, node); fieldAccess = CreateAccessForNode(context, field, operator, node);
if (!fieldAccess) { if (!fieldAccess) {
// OOM // OOM
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return; return NULL;
} }
// look up previous range first return fieldAccess;
previous = (TRI_aql_field_access_t*) TRI_LookupByKeyAssociativePointer(context->_ranges, fieldAccess->_fieldName);
if (previous) {
TRI_aql_field_access_t* merged;
// previous range exists, now merge new access type with previous one
// remove from hash first
TRI_RemoveKeyAssociativePointer(context->_ranges, fieldAccess->_fieldName);
// MergeAccess() will free previous and/or fieldAccess
merged = MergeAccess(context, logicalType, fieldAccess, previous);
if (!merged) {
// OOM
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return;
}
TRI_InsertKeyAssociativePointer(context->_ranges, merged->_fieldName, merged, true);
}
else {
// no previous access exists, no need to merge
TRI_InsertKeyAssociativePointer(context->_ranges, fieldAccess->_fieldName, fieldAccess, false);
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1360,67 +1432,85 @@ static TRI_aql_attribute_name_t* GetAttributeName (TRI_aql_context_t* const cont
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @} /// @brief inspect a condition node
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------- static TRI_vector_pointer_t* ProcessNode (TRI_aql_context_t* const context,
// --SECTION-- constructors / destructors TRI_aql_node_t* node) {
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief init the optimizer
////////////////////////////////////////////////////////////////////////////////
bool TRI_InitOptimizerAql (TRI_aql_context_t* const context) {
assert(context); assert(context);
assert(context->_ranges == NULL); assert(node);
context->_ranges = (TRI_associative_pointer_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_associative_pointer_t), false); if (node->_type == AQL_NODE_OPERATOR_UNARY_NOT) {
if (!context->_ranges) { TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return false; assert(lhs);
return MakeAllVector(context, ProcessNode(context, lhs));
} }
TRI_InitAssociativePointer(context->_ranges, if (node->_type == AQL_NODE_OPERATOR_BINARY_OR) {
TRI_UNKNOWN_MEM_ZONE, TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
&TRI_HashStringKeyAssociativePointer, TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
&HashFieldAccess,
&EqualFieldAccess,
NULL);
return true; assert(lhs);
assert(rhs);
// recurse into next level
return MergeVectors(context,
TRI_AQL_LOGICAL_OR,
ProcessNode(context, lhs),
ProcessNode(context, rhs));
} }
//////////////////////////////////////////////////////////////////////////////// if (node->_type == AQL_NODE_OPERATOR_BINARY_AND) {
/// @brief shutdown the optimizer TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
//////////////////////////////////////////////////////////////////////////////// TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
void TRI_FreeOptimizerAql (TRI_aql_context_t* const context) { assert(lhs);
assert(context); assert(rhs);
if (context->_ranges) { // recurse into next level
size_t i, n; return MergeVectors(context,
TRI_AQL_LOGICAL_AND,
// free all remaining access elements ProcessNode(context, lhs),
n = context->_ranges->_nrAlloc; ProcessNode(context, rhs));
for (i = 0; i < n; ++i) {
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) context->_ranges->_table[i];
if (!fieldAccess) {
continue;
} }
FreeAccess(context, fieldAccess); if (node->_type == AQL_NODE_OPERATOR_BINARY_EQ ||
node->_type == AQL_NODE_OPERATOR_BINARY_NE ||
node->_type == AQL_NODE_OPERATOR_BINARY_LT ||
node->_type == AQL_NODE_OPERATOR_BINARY_LE ||
node->_type == AQL_NODE_OPERATOR_BINARY_GT ||
node->_type == AQL_NODE_OPERATOR_BINARY_GE ||
node->_type == AQL_NODE_OPERATOR_BINARY_IN) {
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
if (lhs->_type == AQL_NODE_ATTRIBUTE_ACCESS) {
TRI_aql_attribute_name_t* field = GetAttributeName(context, lhs);
if (field) {
TRI_aql_field_access_t* attributeAccess = GetAttributeAccess(context, field, node->_type, rhs);
TRI_DestroyStringBuffer(&field->_name);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, field);
return Vectorize(context, attributeAccess);
}
}
else if (rhs->_type == AQL_NODE_ATTRIBUTE_ACCESS) {
TRI_aql_attribute_name_t* field = GetAttributeName(context, rhs);
if (field) {
TRI_aql_field_access_t* attributeAccess = GetAttributeAccess(context, field, node->_type, lhs);
TRI_DestroyStringBuffer(&field->_name);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, field);
return Vectorize(context, attributeAccess);
}
}
} }
// free hash array return NULL;
TRI_FreeAssociativePointer(TRI_UNKNOWN_MEM_ZONE, context->_ranges);
context->_ranges = NULL;
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1440,17 +1530,14 @@ void TRI_FreeOptimizerAql (TRI_aql_context_t* const context) {
/// @brief dump ranges found for debugging purposes /// @brief dump ranges found for debugging purposes
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_DumpRangesAql (TRI_aql_context_t* const context) { void TRI_DumpRangesAql (const TRI_vector_pointer_t* const ranges) {
size_t i; size_t i, n;
assert(context); assert(ranges);
for (i = 0; i < context->_ranges->_nrAlloc; ++i) { n = ranges->_length;
TRI_aql_field_access_t* fieldAccess = context->_ranges->_table[i]; for (i = 0; i < n; ++i) {
TRI_aql_field_access_t* fieldAccess = TRI_AtVectorPointer(ranges, i);
if (!fieldAccess) {
continue;
}
printf("\nFIELD ACCESS\n- FIELD: %s\n",fieldAccess->_fieldName); printf("\nFIELD ACCESS\n- FIELD: %s\n",fieldAccess->_fieldName);
printf("- TYPE: %s\n", AccessName(fieldAccess->_type)); printf("- TYPE: %s\n", AccessName(fieldAccess->_type));
@ -1487,82 +1574,10 @@ void TRI_DumpRangesAql (TRI_aql_context_t* const context) {
/// @brief inspect a condition and note all accesses found for it /// @brief inspect a condition and note all accesses found for it
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_InspectConditionAql (TRI_aql_context_t* const context, TRI_vector_pointer_t* TRI_InspectConditionAql (TRI_aql_context_t* const context,
const TRI_aql_logical_e logicalType, TRI_aql_node_t* node,
TRI_aql_node_t* node) { const TRI_vector_pointer_t* const parentRestrictions) {
assert(context); return ProcessNode(context, node);
assert(logicalType == TRI_AQL_LOGICAL_AND ||
logicalType == TRI_AQL_LOGICAL_OR ||
logicalType == TRI_AQL_LOGICAL_NOT);
if (node->_type == AQL_NODE_OPERATOR_UNARY_NOT) {
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
assert(lhs);
TRI_InspectConditionAql(context, TRI_AQL_LOGICAL_NOT, lhs);
return;
}
if (node->_type == AQL_NODE_OPERATOR_BINARY_OR) {
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
TRI_aql_logical_e nextOperator;
assert(lhs);
assert(rhs);
// recurse into next level
nextOperator = SubOperator(TRI_AQL_LOGICAL_OR, logicalType);
TRI_InspectConditionAql(context, nextOperator, lhs);
TRI_InspectConditionAql(context, nextOperator, rhs);
return;
}
if (node->_type == AQL_NODE_OPERATOR_BINARY_AND) {
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
TRI_aql_logical_e nextOperator;
assert(lhs);
assert(rhs);
// recurse into next level
nextOperator = SubOperator(TRI_AQL_LOGICAL_AND, logicalType);
TRI_InspectConditionAql(context, nextOperator, lhs);
TRI_InspectConditionAql(context, nextOperator, rhs);
return;
}
if (node->_type == AQL_NODE_OPERATOR_BINARY_EQ ||
// node->_type == AQL_NODE_OPERATOR_BINARY_NE ||
node->_type == AQL_NODE_OPERATOR_BINARY_LT ||
node->_type == AQL_NODE_OPERATOR_BINARY_LE ||
node->_type == AQL_NODE_OPERATOR_BINARY_GT ||
node->_type == AQL_NODE_OPERATOR_BINARY_GE ||
node->_type == AQL_NODE_OPERATOR_BINARY_IN) {
TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0);
TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1);
if (lhs->_type == AQL_NODE_ATTRIBUTE_ACCESS) {
TRI_aql_attribute_name_t* field = GetAttributeName(context, lhs);
if (field) {
NoteAttributeAccess(context, logicalType, field, node->_type, rhs);
TRI_DestroyStringBuffer(&field->_name);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, field);
}
}
else if (rhs->_type == AQL_NODE_ATTRIBUTE_ACCESS) {
TRI_aql_attribute_name_t* field = GetAttributeName(context, rhs);
if (field) {
NoteAttributeAccess(context, logicalType, field, node->_type, lhs);
TRI_DestroyStringBuffer(&field->_name);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, field);
}
}
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -59,8 +59,7 @@ extern "C" {
typedef enum { typedef enum {
TRI_AQL_LOGICAL_AND, TRI_AQL_LOGICAL_AND,
TRI_AQL_LOGICAL_OR, TRI_AQL_LOGICAL_OR
TRI_AQL_LOGICAL_NOT
} }
TRI_aql_logical_e; TRI_aql_logical_e;
@ -135,31 +134,6 @@ TRI_aql_attribute_name_t;
/// @} /// @}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief init the optimizer
////////////////////////////////////////////////////////////////////////////////
bool TRI_InitOptimizerAql (TRI_aql_context_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief shutdown the optimizer
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeOptimizerAql (TRI_aql_context_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- public functions // --SECTION-- public functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -173,15 +147,15 @@ void TRI_FreeOptimizerAql (TRI_aql_context_t* const);
/// @brief dump ranges found for debugging purposes /// @brief dump ranges found for debugging purposes
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_DumpRangesAql (TRI_aql_context_t* const); void TRI_DumpRangesAql (const TRI_vector_pointer_t* const);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief inspect a condition and note all accesses found for it /// @brief inspect a condition and note all accesses found for it
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_InspectConditionAql (TRI_aql_context_t* const, TRI_vector_pointer_t* TRI_InspectConditionAql (TRI_aql_context_t* const,
const TRI_aql_logical_e, TRI_aql_node_t*,
TRI_aql_node_t*); const TRI_vector_pointer_t* const);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @} /// @}

View File

@ -268,7 +268,12 @@ static TRI_aql_node_t* OptimiseFilter (TRI_aql_context_t* const context,
if (!TRI_IsConstantValueNodeAql(expression)) { if (!TRI_IsConstantValueNodeAql(expression)) {
#ifdef RANGE_OPTIMIZER #ifdef RANGE_OPTIMIZER
TRI_InspectConditionAql(context, TRI_AQL_LOGICAL_AND, expression); TRI_vector_pointer_t* ranges = TRI_InspectConditionAql(context, expression, NULL);
if (ranges) {
TRI_DumpRangesAql(ranges);
TRI_FreeVectorPointer(TRI_UNKNOWN_MEM_ZONE, ranges);
}
#endif #endif
return node; return node;
} }
@ -663,13 +668,6 @@ TRI_aql_node_t* TRI_FoldConstantsAql (TRI_aql_context_t* const context,
TRI_aql_node_t* node) { TRI_aql_node_t* node) {
TRI_aql_modify_tree_walker_t* walker; TRI_aql_modify_tree_walker_t* walker;
#ifdef RANGE_OPTIMIZER
if (!TRI_InitOptimizerAql(context)) {
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return node;
}
#endif
walker = TRI_CreateModifyTreeWalkerAql((void*) context, &ModifyNode); walker = TRI_CreateModifyTreeWalkerAql((void*) context, &ModifyNode);
if (!walker) { if (!walker) {
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
@ -680,10 +678,6 @@ TRI_aql_node_t* TRI_FoldConstantsAql (TRI_aql_context_t* const context,
TRI_FreeModifyTreeWalkerAql(walker); TRI_FreeModifyTreeWalkerAql(walker);
#ifdef RANGE_OPTIMIZER
TRI_DumpRangesAql(context);
#endif
return node; return node;
} }

View File

@ -78,7 +78,6 @@ TRI_aql_context_t* TRI_CreateContextAql (TRI_vocbase_t* vocbase,
} }
context->_vocbase = vocbase; context->_vocbase = vocbase;
context->_ranges = NULL;
context->_variableIndex = 0; context->_variableIndex = 0;
@ -164,9 +163,6 @@ void TRI_FreeContextAql (TRI_aql_context_t* const context) {
} }
TRI_DestroyVectorPointer(&context->_scopes); TRI_DestroyVectorPointer(&context->_scopes);
// free range optimizer
TRI_FreeOptimizerAql(context);
// free all strings registered // free all strings registered
i = context->_strings._length; i = context->_strings._length;
while (i--) { while (i--) {

View File

@ -82,7 +82,6 @@ typedef struct TRI_aql_context_s {
TRI_associative_pointer_t _parameterValues; TRI_associative_pointer_t _parameterValues;
TRI_associative_pointer_t _parameterNames; TRI_associative_pointer_t _parameterNames;
TRI_associative_pointer_t _collectionNames; TRI_associative_pointer_t _collectionNames;
TRI_associative_pointer_t* _ranges;
size_t _variableIndex; size_t _variableIndex;
void* _first; void* _first;
char* _query; char* _query;