1
0
Fork 0

preparation work for issue #137

This commit is contained in:
Jan Steemann 2012-08-06 10:30:15 +02:00
parent ac99877f67
commit 8326bb2abf
5 changed files with 208 additions and 275 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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, " ] ");
}

View File

@ -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;
}

View File

@ -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);