mirror of https://gitee.com/bigwinds/arangodb
preparation work for issue #137
This commit is contained in:
parent
ac99877f67
commit
8326bb2abf
|
@ -57,10 +57,8 @@ static char* AccessName (const TRI_aql_access_e type) {
|
|||
return "single range";
|
||||
case TRI_AQL_ACCESS_RANGE_DOUBLE:
|
||||
return "double range";
|
||||
case TRI_AQL_ACCESS_REFERENCE_EXACT:
|
||||
return "eq reference";
|
||||
case TRI_AQL_ACCESS_REFERENCE_RANGE:
|
||||
return "range reference";
|
||||
case TRI_AQL_ACCESS_REFERENCE:
|
||||
return "reference";
|
||||
case TRI_AQL_ACCESS_ALL:
|
||||
return "all";
|
||||
}
|
||||
|
@ -123,8 +121,7 @@ static void FreeAccessMembers (TRI_aql_field_access_t* const fieldAccess) {
|
|||
break;
|
||||
}
|
||||
|
||||
case TRI_AQL_ACCESS_REFERENCE_EXACT:
|
||||
case TRI_AQL_ACCESS_REFERENCE_RANGE:
|
||||
case TRI_AQL_ACCESS_REFERENCE:
|
||||
case TRI_AQL_ACCESS_ALL:
|
||||
case TRI_AQL_ACCESS_IMPOSSIBLE: {
|
||||
// nada
|
||||
|
@ -317,8 +314,7 @@ static TRI_aql_field_access_t* MergeAndExact (TRI_aql_context_t* const context,
|
|||
return rhs;
|
||||
}
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_EXACT ||
|
||||
rhs->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
// for simplicity, always return the const access
|
||||
TRI_FreeAccessAql(rhs);
|
||||
return lhs;
|
||||
|
@ -445,8 +441,7 @@ static TRI_aql_field_access_t* MergeAndList (TRI_aql_context_t* const context,
|
|||
return lhs;
|
||||
}
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_EXACT ||
|
||||
rhs->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
// for simplicity, always return the const access
|
||||
TRI_FreeAccessAql(rhs);
|
||||
return lhs;
|
||||
|
@ -790,8 +785,7 @@ static TRI_aql_field_access_t* MergeAndRangeSingle (TRI_aql_context_t* const con
|
|||
return lhs;
|
||||
}
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_EXACT ||
|
||||
rhs->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
// for simplicity, always return the const access
|
||||
TRI_FreeAccessAql(rhs);
|
||||
return lhs;
|
||||
|
@ -859,8 +853,7 @@ static TRI_aql_field_access_t* MergeAndRangeDouble (TRI_aql_context_t* const con
|
|||
return lhs;
|
||||
}
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_EXACT ||
|
||||
rhs->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
// for simplicity, always return the const access
|
||||
TRI_FreeAccessAql(rhs);
|
||||
return lhs;
|
||||
|
@ -880,112 +873,98 @@ static TRI_aql_field_access_t* MergeAndRangeDouble (TRI_aql_context_t* const con
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief merge two access structures using a logical AND
|
||||
///
|
||||
/// left hand operand is a reference, so it will always be returned
|
||||
/// left hand operand is a reference
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_aql_field_access_t* MergeAndReferenceExact (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_EXACT);
|
||||
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);
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_EXACT) {
|
||||
if (TRI_EqualString(lhs->_value._name,
|
||||
rhs->_value._name)) {
|
||||
// reference to the same variable/attribute, no special treatment here
|
||||
// fall-through
|
||||
}
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
TRI_aql_node_type_e lhsType = lhs->_value._reference._type;
|
||||
TRI_aql_node_type_e rhsType = rhs->_value._reference._type;
|
||||
bool isSameAttribute = TRI_EqualString(lhs->_value._reference._name, rhs->_value._reference._name);
|
||||
bool possible;
|
||||
|
||||
// reference to different variable/attribute
|
||||
TRI_FreeAccessAql(rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
if (TRI_EqualString(lhs->_value._name,
|
||||
rhs->_value._referenceRange._name)) {
|
||||
// reference to the same variable/attribute
|
||||
|
||||
if (rhs->_value._referenceRange._type == TRI_AQL_NODE_OPERATOR_BINARY_LT ||
|
||||
rhs->_value._referenceRange._type == TRI_AQL_NODE_OPERATOR_BINARY_GT) {
|
||||
// == && > or == && < => impossible
|
||||
TRI_FreeAccessAql(rhs);
|
||||
FreeAccessMembers(lhs);
|
||||
lhs->_type = TRI_AQL_ACCESS_IMPOSSIBLE;
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// everything else results in lhs
|
||||
// == && >= or == && <=
|
||||
if (!isSameAttribute) {
|
||||
// different attribute names are referred to. we can return either
|
||||
TRI_FreeAccessAql(rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// reference to different variable/attribute, no special treatment here
|
||||
}
|
||||
|
||||
TRI_FreeAccessAql(rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @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* MergeAndReferenceRange (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_RANGE);
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
if (TRI_EqualString(lhs->_value._referenceRange._name,
|
||||
rhs->_value._referenceRange._name)) {
|
||||
// both references refer to the same variable, now compare their operators
|
||||
TRI_aql_node_type_e lhsType = lhs->_value._referenceRange._type;
|
||||
TRI_aql_node_type_e rhsType = rhs->_value._referenceRange._type;
|
||||
bool possible = true;
|
||||
|
||||
if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT &&
|
||||
(rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GE || rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT)) {
|
||||
// lhs < ref && (lhs >= ref || lhs > ref) => impossible
|
||||
possible = false;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE &&
|
||||
rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT) {
|
||||
// lhs <= ref && lhs > ref => impossible
|
||||
possible = false;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT &&
|
||||
(rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE || rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT)) {
|
||||
// lhs > ref && (lhs <= ref || lhs < ref) => impossible
|
||||
possible = false;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GE &&
|
||||
rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT) {
|
||||
// lhs >= ref && lhs < ref => impossible
|
||||
possible = false;
|
||||
}
|
||||
|
||||
if (!possible) {
|
||||
// return the impossible range
|
||||
TRI_FreeAccessAql(rhs);
|
||||
FreeAccessMembers(lhs);
|
||||
lhs->_type = TRI_AQL_ACCESS_IMPOSSIBLE;
|
||||
// both references refer to the same variable, now compare their operators
|
||||
assert(isSameAttribute);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
if (lhsType == rhsType) {
|
||||
// same operator, i.e. the two references are absolutely identical
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
// fall-through
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// return either side (we pick lhs, but it does not matter)
|
||||
if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE) {
|
||||
// < && <=, merge to <
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
if (rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT && lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE) {
|
||||
// <= && <, merge to <
|
||||
TRI_FreeAccessAql(lhs);
|
||||
|
||||
return rhs;
|
||||
}
|
||||
|
||||
possible = true;
|
||||
|
||||
if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_EQ &&
|
||||
(rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT ||
|
||||
rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT)) {
|
||||
// lhs == ref && (lhs < ref || lhs > ref)
|
||||
possible = false;
|
||||
}
|
||||
else if (rhsType == TRI_AQL_NODE_OPERATOR_BINARY_EQ &&
|
||||
(lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT ||
|
||||
lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT)) {
|
||||
// (lhs < ref || lhs > ref) && lhs == ref
|
||||
possible = false;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT &&
|
||||
(rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GE || rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT)) {
|
||||
// lhs < ref && (lhs >= ref || lhs > ref) => impossible
|
||||
possible = false;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE &&
|
||||
rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT) {
|
||||
// lhs <= ref && lhs > ref => impossible
|
||||
possible = false;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT &&
|
||||
(rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE || rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT)) {
|
||||
// lhs > ref && (lhs <= ref || lhs < ref) => impossible
|
||||
possible = false;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GE &&
|
||||
rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT) {
|
||||
// lhs >= ref && lhs < ref => impossible
|
||||
possible = false;
|
||||
}
|
||||
|
||||
if (!possible) {
|
||||
// return the impossible range
|
||||
TRI_FreeAccessAql(rhs);
|
||||
FreeAccessMembers(lhs);
|
||||
lhs->_type = TRI_AQL_ACCESS_IMPOSSIBLE;
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// everything else results in lhs
|
||||
TRI_FreeAccessAql(rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_ALL) {
|
||||
TRI_FreeAccessAql(rhs);
|
||||
return lhs;
|
||||
|
@ -1157,8 +1136,7 @@ static TRI_aql_field_access_t* MergeOrExact (TRI_aql_context_t* const context,
|
|||
return rhs;
|
||||
}
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_EXACT ||
|
||||
rhs->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
// reference cannot be ORed with anything else
|
||||
TRI_FreeAccessAql(rhs);
|
||||
FreeAccessMembers(lhs);
|
||||
|
@ -1374,8 +1352,7 @@ static TRI_aql_field_access_t* MergeOrRangeDouble (TRI_aql_context_t* const cont
|
|||
return lhs;
|
||||
}
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_EXACT ||
|
||||
rhs->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
// reference cannot be ORed with anything else
|
||||
TRI_FreeAccessAql(rhs);
|
||||
FreeAccessMembers(lhs);
|
||||
|
@ -1401,117 +1378,63 @@ static TRI_aql_field_access_t* MergeOrRangeDouble (TRI_aql_context_t* const cont
|
|||
/// left hand operand is reference access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_aql_field_access_t* MergeOrReferenceExact (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_EXACT);
|
||||
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_EXACT) {
|
||||
if (TRI_EqualString(lhs->_value._name,
|
||||
rhs->_value._name)) {
|
||||
// both references refer to the same variable
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
TRI_aql_node_type_e lhsType = lhs->_value._reference._type;
|
||||
TRI_aql_node_type_e rhsType = rhs->_value._reference._type;
|
||||
bool isSameAttribute = TRI_EqualString(lhs->_value._reference._name, rhs->_value._reference._name);
|
||||
|
||||
if (!isSameAttribute) {
|
||||
// references refer to different attributes
|
||||
TRI_FreeAccessAql(rhs);
|
||||
FreeAccessMembers(lhs);
|
||||
lhs->_type = TRI_AQL_ACCESS_ALL;
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// both references refer to the same thing, now compare their operators
|
||||
assert(isSameAttribute);
|
||||
|
||||
if (lhsType == rhsType) {
|
||||
// same operator, i.e. the two references are identical
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
// fall-through
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE) {
|
||||
// < || <=, merge to <=
|
||||
TRI_FreeAccessAql(lhs);
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
if (TRI_EqualString(lhs->_value._name,
|
||||
rhs->_value._referenceRange._name)) {
|
||||
// both references refer to the same variable
|
||||
TRI_aql_node_type_e lhsType = lhs->_value._referenceRange._type;
|
||||
TRI_aql_node_type_e rhsType = rhs->_value._referenceRange._type;
|
||||
|
||||
if (lhsType == rhsType) {
|
||||
// same operation
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE) {
|
||||
TRI_FreeAccessAql(lhs);
|
||||
|
||||
return rhs;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT) {
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GE) {
|
||||
TRI_FreeAccessAql(lhs);
|
||||
|
||||
return rhs;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GE && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT) {
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
return rhs;
|
||||
}
|
||||
// fall-through
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT) {
|
||||
// <= || <, merge to <=
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
// 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
|
||||
///
|
||||
/// left hand operand is reference access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_aql_field_access_t* MergeOrReferenceRange (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_RANGE);
|
||||
|
||||
if (rhs->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
if (TRI_EqualString(lhs->_value._referenceRange._name,
|
||||
rhs->_value._referenceRange._name)) {
|
||||
// both references refer to the same variable
|
||||
TRI_aql_node_type_e lhsType = lhs->_value._referenceRange._type;
|
||||
TRI_aql_node_type_e rhsType = rhs->_value._referenceRange._type;
|
||||
|
||||
if (lhsType == rhsType) {
|
||||
// same operation
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE) {
|
||||
TRI_FreeAccessAql(lhs);
|
||||
|
||||
return rhs;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_LE && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_LT) {
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GE) {
|
||||
TRI_FreeAccessAql(lhs);
|
||||
|
||||
return rhs;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GE && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT) {
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GE) {
|
||||
// > || >=, merge to >=
|
||||
TRI_FreeAccessAql(lhs);
|
||||
|
||||
return rhs;
|
||||
}
|
||||
else if (lhsType == TRI_AQL_NODE_OPERATOR_BINARY_GE && rhsType == TRI_AQL_NODE_OPERATOR_BINARY_GT) {
|
||||
// >= || >, merge to >=
|
||||
TRI_FreeAccessAql(rhs);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
// fall-through
|
||||
}
|
||||
|
||||
|
||||
// for everything else, we have to use the ALL range unfortunately
|
||||
TRI_FreeAccessAql(rhs);
|
||||
FreeAccessMembers(lhs);
|
||||
|
@ -1553,10 +1476,8 @@ static TRI_aql_field_access_t* MergeAttributeAccessAnd (TRI_aql_context_t* const
|
|||
return MergeAndRangeSingle(context, lhs, rhs);
|
||||
case TRI_AQL_ACCESS_RANGE_DOUBLE:
|
||||
return MergeAndRangeDouble(context, lhs, rhs);
|
||||
case TRI_AQL_ACCESS_REFERENCE_EXACT:
|
||||
return MergeAndReferenceExact(context, lhs, rhs);
|
||||
case TRI_AQL_ACCESS_REFERENCE_RANGE:
|
||||
return MergeAndReferenceRange(context, lhs, rhs);
|
||||
case TRI_AQL_ACCESS_REFERENCE:
|
||||
return MergeAndReference(context, lhs, rhs);
|
||||
case TRI_AQL_ACCESS_ALL:
|
||||
return MergeAndAll(context, lhs, rhs);
|
||||
}
|
||||
|
@ -1598,10 +1519,8 @@ static TRI_aql_field_access_t* MergeAttributeAccessOr (TRI_aql_context_t* const
|
|||
return MergeOrRangeSingle(context, lhs, rhs);
|
||||
case TRI_AQL_ACCESS_RANGE_DOUBLE:
|
||||
return MergeOrRangeDouble(context, lhs, rhs);
|
||||
case TRI_AQL_ACCESS_REFERENCE_EXACT:
|
||||
return MergeOrReferenceExact(context, lhs, rhs);
|
||||
case TRI_AQL_ACCESS_REFERENCE_RANGE:
|
||||
return MergeOrReferenceRange(context, lhs, rhs);
|
||||
case TRI_AQL_ACCESS_REFERENCE:
|
||||
return MergeOrReference(context, lhs, rhs);
|
||||
case TRI_AQL_ACCESS_ALL:
|
||||
return MergeOrAll(context, lhs, rhs);
|
||||
}
|
||||
|
@ -1897,15 +1816,9 @@ static TRI_aql_field_access_t* CreateAccessForNode (TRI_aql_context_t* const con
|
|||
|
||||
if (node->_type == TRI_AQL_NODE_REFERENCE) {
|
||||
// create the reference access
|
||||
if (operator == TRI_AQL_NODE_OPERATOR_BINARY_EQ) {
|
||||
fieldAccess->_type = TRI_AQL_ACCESS_REFERENCE_EXACT;
|
||||
fieldAccess->_value._name = TRI_AQL_NODE_STRING(node);
|
||||
}
|
||||
else {
|
||||
fieldAccess->_type = TRI_AQL_ACCESS_REFERENCE_RANGE;
|
||||
fieldAccess->_value._referenceRange._type = operator;
|
||||
fieldAccess->_value._referenceRange._name = TRI_AQL_NODE_STRING(node);
|
||||
}
|
||||
fieldAccess->_type = TRI_AQL_ACCESS_REFERENCE;
|
||||
fieldAccess->_value._reference._type = operator;
|
||||
fieldAccess->_value._reference._name = TRI_AQL_NODE_STRING(node);
|
||||
|
||||
return fieldAccess;
|
||||
}
|
||||
|
@ -2325,14 +2238,9 @@ TRI_aql_field_access_t* TRI_CloneAccessAql (TRI_aql_context_t* const context,
|
|||
break;
|
||||
}
|
||||
|
||||
case TRI_AQL_ACCESS_REFERENCE_EXACT: {
|
||||
fieldAccess->_value._name = source->_value._name;
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_AQL_ACCESS_REFERENCE_RANGE: {
|
||||
fieldAccess->_value._referenceRange._type = source->_value._referenceRange._type;
|
||||
fieldAccess->_value._referenceRange._name = source->_value._referenceRange._name;
|
||||
case TRI_AQL_ACCESS_REFERENCE: {
|
||||
fieldAccess->_value._reference._type = source->_value._reference._type;
|
||||
fieldAccess->_value._reference._name = source->_value._reference._name;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,8 +73,8 @@ typedef enum {
|
|||
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_EXACT, // a reference can be used for eq access (a.x == b.x)
|
||||
TRI_AQL_ACCESS_REFERENCE_RANGE, // a reference can be used for rahe access (a.x > b.x)
|
||||
TRI_AQL_ACCESS_REFERENCE, // a reference can be used for eq access (a.x == b.x)
|
||||
// or range access (a.x > b.x)
|
||||
TRI_AQL_ACCESS_ALL // all values must be accessed (full scan)
|
||||
}
|
||||
TRI_aql_access_e;
|
||||
|
@ -118,12 +118,11 @@ typedef struct TRI_aql_field_access_s {
|
|||
TRI_aql_range_t _upper; // upper bound
|
||||
}
|
||||
_between; // used for TRI_AQL_ACCESS_RANGE_DOUBLE
|
||||
char* _name; // used for TRI_AQL_ACCESS_REFERENCE_EXACT
|
||||
struct {
|
||||
char* _name;
|
||||
TRI_aql_node_type_e _type;
|
||||
}
|
||||
_referenceRange; // used for TRI_AQL_ACCESS_REFERENCE_RANGE
|
||||
_reference; // used for TRI_AQL_ACCESS_REFERENCE
|
||||
}
|
||||
_value;
|
||||
}
|
||||
|
|
|
@ -884,7 +884,8 @@ static void GeneratePrimaryAccess (TRI_aql_codegen_js_t* const generator,
|
|||
|
||||
assert(fieldAccess->_type == TRI_AQL_ACCESS_EXACT ||
|
||||
fieldAccess->_type == TRI_AQL_ACCESS_LIST ||
|
||||
fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE_EXACT);
|
||||
(fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE &&
|
||||
fieldAccess->_value._reference._type == TRI_AQL_NODE_OPERATOR_BINARY_EQ));
|
||||
|
||||
if (fieldAccess->_type == TRI_AQL_ACCESS_LIST) {
|
||||
ScopeOutput(generator, "AHUACATL_GET_DOCUMENTS_PRIMARY_LIST('");
|
||||
|
@ -897,8 +898,10 @@ static void GeneratePrimaryAccess (TRI_aql_codegen_js_t* const generator,
|
|||
ScopeOutput(generator, "', ");
|
||||
ScopeOutputIndexId(generator, collection, idx);
|
||||
ScopeOutput(generator, ", ");
|
||||
if (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE_EXACT) {
|
||||
ScopeOutputRegister(generator, LookupSymbol(generator, fieldAccess->_value._name));
|
||||
if (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
assert(fieldAccess->_value._reference._type == TRI_AQL_NODE_OPERATOR_BINARY_EQ);
|
||||
|
||||
ScopeOutputRegister(generator, LookupSymbol(generator, fieldAccess->_value._reference._name));
|
||||
}
|
||||
else {
|
||||
ScopeOutputJson(generator, fieldAccess->_value._value);
|
||||
|
@ -949,7 +952,8 @@ static void GenerateHashAccess (TRI_aql_codegen_js_t* const generator,
|
|||
TRI_aql_field_access_t* fieldAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(idx->_fieldAccesses, i);
|
||||
|
||||
assert(fieldAccess->_type == TRI_AQL_ACCESS_EXACT ||
|
||||
fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE_EXACT);
|
||||
(fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE &&
|
||||
fieldAccess->_value._reference._type == TRI_AQL_NODE_OPERATOR_BINARY_EQ));
|
||||
|
||||
if (i > 0) {
|
||||
ScopeOutput(generator, ", ");
|
||||
|
@ -957,8 +961,10 @@ static void GenerateHashAccess (TRI_aql_codegen_js_t* const generator,
|
|||
|
||||
ScopeOutputQuoted2(generator, fieldAccess->_fullName + fieldAccess->_variableNameLength + 1);
|
||||
ScopeOutput(generator, " : ");
|
||||
if (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE_EXACT) {
|
||||
ScopeOutputRegister(generator, LookupSymbol(generator, fieldAccess->_value._name));
|
||||
if (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
assert(fieldAccess->_value._reference._type == TRI_AQL_NODE_OPERATOR_BINARY_EQ);
|
||||
|
||||
ScopeOutputRegister(generator, LookupSymbol(generator, fieldAccess->_value._reference._name));
|
||||
}
|
||||
else {
|
||||
ScopeOutputJson(generator, fieldAccess->_value._value);
|
||||
|
@ -1013,8 +1019,7 @@ static void GenerateSkiplistAccess (TRI_aql_codegen_js_t* const generator,
|
|||
assert(fieldAccess->_type == TRI_AQL_ACCESS_EXACT ||
|
||||
fieldAccess->_type == TRI_AQL_ACCESS_RANGE_SINGLE ||
|
||||
fieldAccess->_type == TRI_AQL_ACCESS_RANGE_DOUBLE ||
|
||||
fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE_EXACT ||
|
||||
fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE_RANGE);
|
||||
fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE);
|
||||
|
||||
if (i > 0) {
|
||||
ScopeOutput(generator, ", ");
|
||||
|
@ -1048,16 +1053,11 @@ static void GenerateSkiplistAccess (TRI_aql_codegen_js_t* const generator,
|
|||
ScopeOutputJson(generator, fieldAccess->_value._between._upper._value);
|
||||
ScopeOutput(generator, " ] ");
|
||||
}
|
||||
else if (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE_EXACT) {
|
||||
ScopeOutput(generator, " [ \"==\", ");
|
||||
ScopeOutputRegister(generator, LookupSymbol(generator, fieldAccess->_value._name));
|
||||
ScopeOutput(generator, " ] ");
|
||||
}
|
||||
else if (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
else if (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE) {
|
||||
ScopeOutput(generator, " [ \"");
|
||||
ScopeOutput(generator, TRI_RangeOperatorAql(fieldAccess->_value._singleRange._type));
|
||||
ScopeOutput(generator, TRI_RangeOperatorAql(fieldAccess->_value._reference._type));
|
||||
ScopeOutput(generator, "\", ");
|
||||
ScopeOutputRegister(generator, LookupSymbol(generator, fieldAccess->_value._name));
|
||||
ScopeOutputRegister(generator, LookupSymbol(generator, fieldAccess->_value._reference._name));
|
||||
ScopeOutput(generator, " ] ");
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,9 @@
|
|||
/// @brief log information about the used index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void LogIndexString (TRI_index_t const* idx,
|
||||
#ifdef TRI_DEBUG_AQL
|
||||
static void LogIndexString (const char* const what,
|
||||
TRI_index_t const* idx,
|
||||
char const* collectionName) {
|
||||
TRI_string_buffer_t* buffer = TRI_CreateStringBuffer(TRI_UNKNOWN_MEM_ZONE);
|
||||
size_t i;
|
||||
|
@ -60,13 +62,39 @@ static void LogIndexString (TRI_index_t const* idx,
|
|||
TRI_AppendStringStringBuffer(buffer, idx->_fields._buffer[i]);
|
||||
}
|
||||
|
||||
TRI_AQL_LOG("using %s index (%s) for '%s'",
|
||||
TRI_AQL_LOG("%s %s index (%s) for '%s'",
|
||||
what,
|
||||
TRI_TypeNameIndex(idx),
|
||||
buffer->_buffer,
|
||||
collectionName);
|
||||
|
||||
TRI_FreeStringBuffer(TRI_UNKNOWN_MEM_ZONE, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether a field access candidate is an exact access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool isExactCandidate (const TRI_aql_field_access_t* const candidate) {
|
||||
if (candidate->_type == TRI_AQL_ACCESS_EXACT) {
|
||||
// ==
|
||||
return true;
|
||||
}
|
||||
|
||||
if (candidate->_type == TRI_AQL_ACCESS_LIST) {
|
||||
// in (...)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (candidate->_type == TRI_AQL_ACCESS_REFERENCE &&
|
||||
candidate->_value._reference._type == TRI_AQL_NODE_OPERATOR_BINARY_EQ) {
|
||||
// == ref
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief pick or replace an index
|
||||
|
@ -165,14 +193,14 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
n = availableIndexes->_length;
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_index_t* idx = (TRI_index_t*) availableIndexes->_buffer[i];
|
||||
TRI_aql_access_e lastType;
|
||||
size_t numIndexFields = idx->_fields._length;
|
||||
bool lastTypeWasExact;
|
||||
|
||||
if (numIndexFields == 0) {
|
||||
// index should contain at least one field
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// we'll use a switch here so the compiler warns if new index types are added elsewhere but not here
|
||||
switch (idx->_type) {
|
||||
case TRI_IDX_TYPE_GEO1_INDEX:
|
||||
|
@ -188,10 +216,14 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
// these indexes are valid candidates
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef TRI_DEBUG_AQL
|
||||
LogIndexString("checking", idx, collectionName);
|
||||
#endif
|
||||
|
||||
TRI_ClearVectorPointer(&matches);
|
||||
|
||||
lastType = TRI_AQL_ACCESS_EXACT;
|
||||
lastTypeWasExact = true;
|
||||
|
||||
// now loop over all index fields, from left to right
|
||||
// index field order is important because skiplists can be used with leftmost prefixes as well,
|
||||
|
@ -221,9 +253,7 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
// attribute is used in index
|
||||
|
||||
if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX) {
|
||||
if (candidate->_type != TRI_AQL_ACCESS_EXACT &&
|
||||
candidate->_type != TRI_AQL_ACCESS_LIST &&
|
||||
candidate->_type != TRI_AQL_ACCESS_REFERENCE_EXACT) {
|
||||
if (!isExactCandidate(candidate)) {
|
||||
// wrong access type for primary index
|
||||
continue;
|
||||
}
|
||||
|
@ -231,9 +261,7 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
TRI_PushBackVectorPointer(&matches, candidate);
|
||||
}
|
||||
else if (idx->_type == TRI_IDX_TYPE_HASH_INDEX) {
|
||||
if (candidate->_type != TRI_AQL_ACCESS_EXACT &&
|
||||
candidate->_type != TRI_AQL_ACCESS_LIST &&
|
||||
candidate->_type != TRI_AQL_ACCESS_REFERENCE_EXACT) {
|
||||
if (!isExactCandidate(candidate)) {
|
||||
// wrong access type for hash index
|
||||
continue;
|
||||
}
|
||||
|
@ -247,14 +275,12 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
}
|
||||
else if (idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
|
||||
bool candidateIsExact;
|
||||
bool lastIsExact;
|
||||
|
||||
if (candidate->_type != TRI_AQL_ACCESS_EXACT &&
|
||||
candidate->_type != TRI_AQL_ACCESS_LIST &&
|
||||
candidate->_type != TRI_AQL_ACCESS_RANGE_SINGLE &&
|
||||
candidate->_type != TRI_AQL_ACCESS_RANGE_DOUBLE &&
|
||||
candidate->_type != TRI_AQL_ACCESS_REFERENCE_EXACT &&
|
||||
candidate->_type != TRI_AQL_ACCESS_REFERENCE_RANGE) {
|
||||
candidate->_type != TRI_AQL_ACCESS_REFERENCE) {
|
||||
// wrong access type for skiplists
|
||||
continue;
|
||||
}
|
||||
|
@ -264,17 +290,16 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
continue;
|
||||
}
|
||||
|
||||
candidateIsExact = (candidate->_type == TRI_AQL_ACCESS_EXACT || candidate->_type == TRI_AQL_ACCESS_REFERENCE_EXACT);
|
||||
lastIsExact = (lastType == TRI_AQL_ACCESS_EXACT || lastType == TRI_AQL_ACCESS_REFERENCE_EXACT);
|
||||
candidateIsExact = isExactCandidate(candidate);
|
||||
|
||||
if ((candidateIsExact && !lastIsExact) ||
|
||||
(!candidateIsExact && !lastIsExact)) {
|
||||
if ((candidateIsExact && !lastTypeWasExact) ||
|
||||
(!candidateIsExact && !lastTypeWasExact)) {
|
||||
// if we already had a range query, we cannot check for equality after that
|
||||
// if we already had a range query, we cannot check another range after that
|
||||
continue;
|
||||
}
|
||||
|
||||
lastType = candidate->_type;
|
||||
lastTypeWasExact = candidateIsExact;
|
||||
|
||||
TRI_PushBackVectorPointer(&matches, candidate);
|
||||
}
|
||||
|
@ -305,9 +330,11 @@ TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
|
|||
|
||||
TRI_DestroyVectorPointer(&matches);
|
||||
|
||||
#ifdef TRI_DEBUG_AQL
|
||||
if (picked) {
|
||||
LogIndexString(picked->_idx, collectionName);
|
||||
LogIndexString("using", picked->_idx, collectionName);
|
||||
}
|
||||
#endif
|
||||
|
||||
return picked;
|
||||
}
|
||||
|
|
|
@ -943,8 +943,7 @@ static void PatchVariables (TRI_aql_statement_walker_t* const walker) {
|
|||
return;
|
||||
}
|
||||
|
||||
isReference = (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE_EXACT ||
|
||||
fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE_RANGE);
|
||||
isReference = (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE);
|
||||
|
||||
variable = TRI_GetVariableStatementWalkerAql(walker, variableName, &scopeCount);
|
||||
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, variableName);
|
||||
|
|
Loading…
Reference in New Issue