From 926a158a99c0a13068801b0eba82d70bfea5c8d0 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Wed, 9 May 2012 11:16:37 +0200 Subject: [PATCH] refactored range optimizer --- Ahuacatl/ahuacatl-access-optimizer.c | 547 ++++++++++++++------------- Ahuacatl/ahuacatl-access-optimizer.h | 36 +- Ahuacatl/ahuacatl-constant-folder.c | 20 +- Ahuacatl/ahuacatl-context.c | 4 - Ahuacatl/ahuacatl-context.h | 1 - 5 files changed, 293 insertions(+), 315 deletions(-) diff --git a/Ahuacatl/ahuacatl-access-optimizer.c b/Ahuacatl/ahuacatl-access-optimizer.c index 71ee0f7842..90b675c208 100644 --- a/Ahuacatl/ahuacatl-access-optimizer.c +++ b/Ahuacatl/ahuacatl-access-optimizer.c @@ -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, - void const* element) { - TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) element; +static TRI_vector_pointer_t* Vectorize (TRI_aql_context_t* const context, + TRI_aql_field_access_t* fieldAccess) { + TRI_vector_pointer_t* vector; - return TRI_FnvHashString(fieldAccess->_fieldName); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief comparison function used to determine field name equality -//////////////////////////////////////////////////////////////////////////////// - -static bool EqualFieldAccess (TRI_associative_pointer_t* array, - void const* key, - void const* element) { - TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) element; - - return TRI_EqualString(key, fieldAccess->_fieldName); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief return the logical type for a sub operation -//////////////////////////////////////////////////////////////////////////////// - -static inline TRI_aql_logical_e SubOperator (const TRI_aql_logical_e preferredType, - const TRI_aql_logical_e parentType) { - if (parentType == TRI_AQL_LOGICAL_NOT) { - // logical NOT is sticky - return parentType; + assert(context); + if (!fieldAccess) { + return NULL; } - // all other operators are not - return preferredType; + vector = (TRI_vector_pointer_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_vector_pointer_t), false); + if (!vector) { + // OOM + TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); + return NULL; + } + + TRI_InitVectorPointer(vector, TRI_UNKNOWN_MEM_ZONE); + TRI_PushBackVectorPointer(vector, fieldAccess); + + return vector; } //////////////////////////////////////////////////////////////////////////////// @@ -146,25 +134,7 @@ static void FreeAccess (TRI_aql_context_t* const context, 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 /// @@ -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, - const TRI_aql_logical_e logicalType, - TRI_aql_field_access_t* lhs, - TRI_aql_field_access_t* rhs) { - assert(context); - assert(lhs); - assert(rhs); - assert(logicalType == TRI_AQL_LOGICAL_AND || - logicalType == TRI_AQL_LOGICAL_OR || - logicalType == TRI_AQL_LOGICAL_NOT); - +static TRI_aql_field_access_t* MergeAttributeAccessAnd (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 (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) { // swap operands so they are always sorted TRI_aql_field_access_t* tmp = lhs; @@ -1136,45 +1098,176 @@ static TRI_aql_field_access_t* MergeAccess (TRI_aql_context_t* const context, assert(lhs->_type <= rhs->_type); - if (logicalType == TRI_AQL_LOGICAL_AND) { - // logical AND - switch (lhs->_type) { - case TRI_AQL_ACCESS_IMPOSSIBLE: - return MergeAndImpossible(context, lhs, rhs); - case TRI_AQL_ACCESS_ALL: - return MergeAndAll(context, lhs, rhs); - case TRI_AQL_ACCESS_EXACT: - return MergeAndExact(context, lhs, rhs); - case TRI_AQL_ACCESS_LIST: - return MergeAndList(context, lhs, rhs); - case TRI_AQL_ACCESS_RANGE_SINGLE: - return MergeAndRangeSingle(context, lhs, rhs); - case TRI_AQL_ACCESS_RANGE_DOUBLE: - return MergeAndRangeDouble(context, lhs, rhs); - } - } - else { - // logical OR - switch (lhs->_type) { - case TRI_AQL_ACCESS_IMPOSSIBLE: - return MergeOrImpossible(context, lhs, rhs); - case TRI_AQL_ACCESS_ALL: - return MergeOrAll(context, lhs, rhs); - case TRI_AQL_ACCESS_EXACT: - return MergeOrExact(context, lhs, rhs); - case TRI_AQL_ACCESS_LIST: - return MergeOrList(context, lhs, rhs); - case TRI_AQL_ACCESS_RANGE_SINGLE: - return MergeOrRangeSingle(context, lhs, rhs); - case TRI_AQL_ACCESS_RANGE_DOUBLE: - return MergeOrRangeDouble(context, lhs, rhs); - } + switch (lhs->_type) { + case TRI_AQL_ACCESS_IMPOSSIBLE: + return MergeAndImpossible(context, lhs, rhs); + case TRI_AQL_ACCESS_ALL: + return MergeAndAll(context, lhs, rhs); + case TRI_AQL_ACCESS_EXACT: + return MergeAndExact(context, lhs, rhs); + case TRI_AQL_ACCESS_LIST: + return MergeAndList(context, lhs, rhs); + case TRI_AQL_ACCESS_RANGE_SINGLE: + return MergeAndRangeSingle(context, lhs, rhs); + case TRI_AQL_ACCESS_RANGE_DOUBLE: + return MergeAndRangeDouble(context, lhs, rhs); } assert(false); return NULL; } +//////////////////////////////////////////////////////////////////////////////// +/// @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) { + case TRI_AQL_ACCESS_IMPOSSIBLE: + return MergeOrImpossible(context, lhs, rhs); + case TRI_AQL_ACCESS_ALL: + return MergeOrAll(context, lhs, rhs); + case TRI_AQL_ACCESS_EXACT: + return MergeOrExact(context, lhs, rhs); + case TRI_AQL_ACCESS_LIST: + return MergeOrList(context, lhs, rhs); + case TRI_AQL_ACCESS_RANGE_SINGLE: + return MergeOrRangeSingle(context, lhs, rhs); + case TRI_AQL_ACCESS_RANGE_DOUBLE: + return MergeOrRangeDouble(context, lhs, rhs); + } + + assert(false); + 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 //////////////////////////////////////////////////////////////////////////////// @@ -1216,6 +1309,10 @@ static TRI_aql_field_access_t* CreateAccessForNode (TRI_aql_context_t* const con fieldAccess->_type = TRI_AQL_ACCESS_EXACT; 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) { // create a single range access 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, /// merge it with potential others already found for the same variable +/// +/// TODO fix docs //////////////////////////////////////////////////////////////////////////////// -static void NoteAttributeAccess (TRI_aql_context_t* const context, - const TRI_aql_logical_e logicalType, - const TRI_aql_attribute_name_t* const field, - const TRI_aql_node_type_e operator, - const TRI_aql_node_t* const node) { - TRI_aql_field_access_t* previous; +static TRI_aql_field_access_t* GetAttributeAccess (TRI_aql_context_t* const context, + const TRI_aql_attribute_name_t* const field, + const TRI_aql_node_type_e operator, + const TRI_aql_node_t* const node) { TRI_aql_field_access_t* fieldAccess; assert(context); - assert(logicalType == TRI_AQL_LOGICAL_AND || - logicalType == TRI_AQL_LOGICAL_OR || - logicalType == TRI_AQL_LOGICAL_NOT); assert(node); if (!field || !field->_name._buffer) { - return; + // this is ok if the node type is not supported + return NULL; } fieldAccess = CreateAccessForNode(context, field, operator, node); if (!fieldAccess) { // OOM TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); - return; + return NULL; } - // look up previous range first - 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); - } + return fieldAccess; } //////////////////////////////////////////////////////////////////////////////// @@ -1360,67 +1432,85 @@ static TRI_aql_attribute_name_t* GetAttributeName (TRI_aql_context_t* const cont } //////////////////////////////////////////////////////////////////////////////// -/// @} +/// @brief inspect a condition node //////////////////////////////////////////////////////////////////////////////// -// ----------------------------------------------------------------------------- -// --SECTION-- constructors / destructors -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup Ahuacatl -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @brief init the optimizer -//////////////////////////////////////////////////////////////////////////////// - -bool TRI_InitOptimizerAql (TRI_aql_context_t* const context) { +static TRI_vector_pointer_t* ProcessNode (TRI_aql_context_t* const context, + TRI_aql_node_t* node) { 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 (!context->_ranges) { - TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); - return false; + if (node->_type == AQL_NODE_OPERATOR_UNARY_NOT) { + TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0); + + assert(lhs); + + return MakeAllVector(context, ProcessNode(context, lhs)); } - TRI_InitAssociativePointer(context->_ranges, - TRI_UNKNOWN_MEM_ZONE, - &TRI_HashStringKeyAssociativePointer, - &HashFieldAccess, - &EqualFieldAccess, - NULL); + 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); - return true; -} + assert(lhs); + assert(rhs); -//////////////////////////////////////////////////////////////////////////////// -/// @brief shutdown the optimizer -//////////////////////////////////////////////////////////////////////////////// + // recurse into next level + return MergeVectors(context, + TRI_AQL_LOGICAL_OR, + ProcessNode(context, lhs), + ProcessNode(context, rhs)); + } -void TRI_FreeOptimizerAql (TRI_aql_context_t* const context) { - assert(context); + 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); + + assert(lhs); + assert(rhs); - if (context->_ranges) { - size_t i, n; + // recurse into next level + return MergeVectors(context, + TRI_AQL_LOGICAL_AND, + ProcessNode(context, lhs), + ProcessNode(context, rhs)); + } - // free all remaining access elements - n = context->_ranges->_nrAlloc; - for (i = 0; i < n; ++i) { - TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) context->_ranges->_table[i]; - if (!fieldAccess) { - continue; + 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); } - - FreeAccess(context, fieldAccess); } + else if (rhs->_type == AQL_NODE_ATTRIBUTE_ACCESS) { + TRI_aql_attribute_name_t* field = GetAttributeName(context, rhs); - // free hash array - TRI_FreeAssociativePointer(TRI_UNKNOWN_MEM_ZONE, context->_ranges); - context->_ranges = NULL; + 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); + } + } } + + return NULL; } //////////////////////////////////////////////////////////////////////////////// @@ -1440,17 +1530,14 @@ void TRI_FreeOptimizerAql (TRI_aql_context_t* const context) { /// @brief dump ranges found for debugging purposes //////////////////////////////////////////////////////////////////////////////// -void TRI_DumpRangesAql (TRI_aql_context_t* const context) { - size_t i; +void TRI_DumpRangesAql (const TRI_vector_pointer_t* const ranges) { + size_t i, n; - assert(context); + assert(ranges); - for (i = 0; i < context->_ranges->_nrAlloc; ++i) { - TRI_aql_field_access_t* fieldAccess = context->_ranges->_table[i]; - - if (!fieldAccess) { - continue; - } + n = ranges->_length; + for (i = 0; i < n; ++i) { + TRI_aql_field_access_t* fieldAccess = TRI_AtVectorPointer(ranges, i); printf("\nFIELD ACCESS\n- FIELD: %s\n",fieldAccess->_fieldName); printf("- TYPE: %s\n", AccessName(fieldAccess->_type)); @@ -1482,89 +1569,17 @@ void TRI_DumpRangesAql (TRI_aql_context_t* const context) { } } } - + //////////////////////////////////////////////////////////////////////////////// /// @brief inspect a condition and note all accesses found for it //////////////////////////////////////////////////////////////////////////////// -void TRI_InspectConditionAql (TRI_aql_context_t* const context, - const TRI_aql_logical_e logicalType, - TRI_aql_node_t* node) { - assert(context); - 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); - } - } - } +TRI_vector_pointer_t* TRI_InspectConditionAql (TRI_aql_context_t* const context, + TRI_aql_node_t* node, + const TRI_vector_pointer_t* const parentRestrictions) { + return ProcessNode(context, node); } - + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/Ahuacatl/ahuacatl-access-optimizer.h b/Ahuacatl/ahuacatl-access-optimizer.h index 610ea367dc..25c667274e 100644 --- a/Ahuacatl/ahuacatl-access-optimizer.h +++ b/Ahuacatl/ahuacatl-access-optimizer.h @@ -59,8 +59,7 @@ extern "C" { typedef enum { TRI_AQL_LOGICAL_AND, - TRI_AQL_LOGICAL_OR, - TRI_AQL_LOGICAL_NOT + TRI_AQL_LOGICAL_OR } 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 // ----------------------------------------------------------------------------- @@ -173,15 +147,15 @@ void TRI_FreeOptimizerAql (TRI_aql_context_t* const); /// @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 //////////////////////////////////////////////////////////////////////////////// -void TRI_InspectConditionAql (TRI_aql_context_t* const, - const TRI_aql_logical_e, - TRI_aql_node_t*); +TRI_vector_pointer_t* TRI_InspectConditionAql (TRI_aql_context_t* const, + TRI_aql_node_t*, + const TRI_vector_pointer_t* const); //////////////////////////////////////////////////////////////////////////////// /// @} diff --git a/Ahuacatl/ahuacatl-constant-folder.c b/Ahuacatl/ahuacatl-constant-folder.c index fb5f44886f..1fc11e36e7 100644 --- a/Ahuacatl/ahuacatl-constant-folder.c +++ b/Ahuacatl/ahuacatl-constant-folder.c @@ -31,7 +31,7 @@ #include "V8/v8-execution.h" -#undef RANGE_OPTIMIZER +#undef RANGE_OPTIMIZER // ----------------------------------------------------------------------------- // --SECTION-- private functions @@ -268,7 +268,12 @@ static TRI_aql_node_t* OptimiseFilter (TRI_aql_context_t* const context, if (!TRI_IsConstantValueNodeAql(expression)) { #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 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_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); if (!walker) { 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); -#ifdef RANGE_OPTIMIZER - TRI_DumpRangesAql(context); -#endif - return node; } diff --git a/Ahuacatl/ahuacatl-context.c b/Ahuacatl/ahuacatl-context.c index c97234917b..d7eb794adc 100644 --- a/Ahuacatl/ahuacatl-context.c +++ b/Ahuacatl/ahuacatl-context.c @@ -78,7 +78,6 @@ TRI_aql_context_t* TRI_CreateContextAql (TRI_vocbase_t* vocbase, } context->_vocbase = vocbase; - context->_ranges = NULL; context->_variableIndex = 0; @@ -164,9 +163,6 @@ void TRI_FreeContextAql (TRI_aql_context_t* const context) { } TRI_DestroyVectorPointer(&context->_scopes); - // free range optimizer - TRI_FreeOptimizerAql(context); - // free all strings registered i = context->_strings._length; while (i--) { diff --git a/Ahuacatl/ahuacatl-context.h b/Ahuacatl/ahuacatl-context.h index 3890f93f83..b72a2b0732 100644 --- a/Ahuacatl/ahuacatl-context.h +++ b/Ahuacatl/ahuacatl-context.h @@ -82,7 +82,6 @@ typedef struct TRI_aql_context_s { TRI_associative_pointer_t _parameterValues; TRI_associative_pointer_t _parameterNames; TRI_associative_pointer_t _collectionNames; - TRI_associative_pointer_t* _ranges; size_t _variableIndex; void* _first; char* _query;