mirror of https://gitee.com/bigwinds/arangodb
added tests for filter order, not optimization etc.
This commit is contained in:
parent
8aeded5c86
commit
1c935b6ab2
|
@ -1369,7 +1369,7 @@ static RangeInfoMapVec* BuildRangeInfo (ExecutionPlan* plan,
|
|||
}
|
||||
|
||||
// distribute AND into OR
|
||||
return andCombineRangeInfoMapVecs(lhs, rhs);
|
||||
return andCombineRangeInfoMapVecsIgnoreEmpty(lhs, rhs);
|
||||
}
|
||||
|
||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_IN) {
|
||||
|
@ -1512,6 +1512,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
std::string attr;
|
||||
Variable const* enumCollVar = nullptr;
|
||||
auto expression = node->expression()->node();
|
||||
|
||||
// there is an implicit AND between FILTER statements
|
||||
if (_rangeInfoMapVec == nullptr) {
|
||||
// don't yet have anything to AND-combine
|
||||
|
@ -1519,7 +1520,7 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
|
|||
}
|
||||
else {
|
||||
// AND-combine with previous ranges
|
||||
_rangeInfoMapVec = andCombineRangeInfoMapVecs(
|
||||
_rangeInfoMapVec = andCombineRangeInfoMapVecsIgnoreEmpty(
|
||||
_rangeInfoMapVec,
|
||||
BuildRangeInfo(_plan, expression, enumCollVar, attr, _mustNotUseRanges)
|
||||
);
|
||||
|
|
|
@ -669,6 +669,37 @@ RangeInfoMapVec* triagens::aql::andCombineRangeInfoMapVecs (RangeInfoMapVec* lhs
|
|||
return rimv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief andCombineRangeInfoMapVecs: same as before, but will return the
|
||||
/// mapvec even if one side is a nullptr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RangeInfoMapVec* triagens::aql::andCombineRangeInfoMapVecsIgnoreEmpty (RangeInfoMapVec* lhs,
|
||||
RangeInfoMapVec* rhs) {
|
||||
if (lhs == nullptr && rhs == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((lhs == nullptr || lhs->empty()) && rhs != nullptr) {
|
||||
if (lhs != nullptr) {
|
||||
delete lhs;
|
||||
}
|
||||
return rhs;
|
||||
}
|
||||
|
||||
if (lhs != nullptr && (rhs == nullptr || rhs->empty())) {
|
||||
if (rhs != nullptr) {
|
||||
delete rhs;
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
|
||||
TRI_ASSERT(lhs != nullptr);
|
||||
TRI_ASSERT(rhs != nullptr);
|
||||
|
||||
return andCombineRangeInfoMapVecs(lhs, rhs);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief comparison of range infos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -921,6 +921,13 @@ namespace triagens {
|
|||
|
||||
RangeInfoMapVec* andCombineRangeInfoMapVecs (RangeInfoMapVec*, RangeInfoMapVec*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief andCombineRangeInfoMapVecs: same as before, but will return the
|
||||
/// mapvec even if one side is a nullptr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RangeInfoMapVec* andCombineRangeInfoMapVecsIgnoreEmpty (RangeInfoMapVec*, RangeInfoMapVec*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief IndexOrCondition, type for vector of vector of RangeInfo. The meaning
|
||||
/// is: the outer vector means an implicit "OR" between the entries. Each
|
||||
|
|
|
@ -1010,6 +1010,78 @@ function optimizerIndexesTestSuite () {
|
|||
assertTrue(results.stats.scannedIndex > 0);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexOrNoIndexBecauseOfDifferentAttributes : function () {
|
||||
AQL_EXECUTE("FOR i IN " + c.name() + " UPDATE i WITH { value2: i.value, value3: 1 } IN " + c.name());
|
||||
|
||||
var queries = [
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 1 || i.value2 == 2 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 || i.value == 1 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value == 1 || i.value == 2) || i.value2 == 2 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 || (i.value == 1 || i.value == 2) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 1 || (i.value == 2 || i.value2 == 2) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value2 == 2 || i.value == 1) || i.value == 2 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value == 1 && i.value2 == 1) || (i.value == 2 || i.value3 != 1) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value2 == 1 && i.value == 1) || (i.value3 != 1 || i.value == 2) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value == 1 && i.value2 == 1) || (i.value == 2 || i.value3 == 0) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value2 == 1 && i.value == 1) || (i.value3 == 0 || i.value == 2) RETURN i.value"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var plan = AQL_EXPLAIN(query).plan;
|
||||
var nodeTypes = plan.nodes.map(function(node) {
|
||||
return node.type;
|
||||
});
|
||||
|
||||
assertEqual(-1, nodeTypes.indexOf("IndexRangeNode"), query);
|
||||
var results = AQL_EXECUTE(query);
|
||||
assertEqual(2, results.json.length);
|
||||
assertTrue(results.stats.scannedFull > 0);
|
||||
assertEqual(0, results.stats.scannedIndex);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexOrNoIndexBecauseOfOperator : function () {
|
||||
AQL_EXECUTE("FOR i IN " + c.name() + " UPDATE i WITH { value2: i.value, value3: 1 } IN " + c.name());
|
||||
|
||||
var queries = [
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 1 || i.value2 != i.value RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != i.value || i.value == 1 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value != 1 || i.value != 2) && i.value == 3 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 3 && (i.value != 1 || i.value != 2) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value2 != 1 || i.value2 != 2) && i.value == 3 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 3 && (i.value2 != 1 || i.value2 != 2) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value != 1 && PASSTHRU(i.value2) == 2 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER PASSTHRU(i.value2) == 2 && i.value != 1 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 2 && PASSTHRU(i.value) == 1 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER PASSTHRU(i.value) == 1 && i.value2 != 2 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 1 || i.value3 != 1 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value3 != 1 || i.value == 1 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value3 != 1 || i.value2 == 2 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 || i.value3 != 1 RETURN i.value"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var plan = AQL_EXPLAIN(query).plan;
|
||||
var nodeTypes = plan.nodes.map(function(node) {
|
||||
return node.type;
|
||||
});
|
||||
|
||||
assertEqual(-1, nodeTypes.indexOf("IndexRangeNode"), query);
|
||||
var results = AQL_EXECUTE(query);
|
||||
assertEqual(1, results.json.length, query);
|
||||
assertTrue(results.stats.scannedFull > 0);
|
||||
assertEqual(0, results.stats.scannedIndex);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1124,7 +1196,9 @@ function optimizerIndexesTestSuite () {
|
|||
"LET a = PASSTHRU(0) FOR i IN " + c.name() + " FILTER i.value == 1 && a + 1 == 1 RETURN i.value",
|
||||
"LET a = PASSTHRU(0) FOR i IN " + c.name() + " FILTER a + 1 == 1 && i.value == 1 RETURN i.value",
|
||||
"LET a = PASSTHRU(0) FOR i IN " + c.name() + " FILTER i.value == 1 && a IN [ 0, 1 ] RETURN i.value",
|
||||
"LET a = PASSTHRU(0) FOR i IN " + c.name() + " FILTER a IN [ 0, 1 ] && i.value == 1 RETURN i.value"
|
||||
"LET a = PASSTHRU(0) FOR i IN " + c.name() + " FILTER a IN [ 0, 1 ] && i.value == 1 RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 1 && NOT (i.value != 1) RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 1 || NOT NOT (i.value == 1) RETURN i"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
|
@ -1141,6 +1215,35 @@ function optimizerIndexesTestSuite () {
|
|||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexAndDespiteOr : function () {
|
||||
AQL_EXECUTE("FOR i IN " + c.name() + " UPDATE i WITH { value2: i.value, value3: 1 } IN " + c.name());
|
||||
|
||||
var queries = [
|
||||
"FOR i IN " + c.name() + " FILTER (i.value == 1 && i.value2 == 1) || (i.value == 2 && i.value2 == 2) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value2 == 1 && i.value == 1) || (i.value2 == 2 && i.value == 2) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value2 == 1 && i.value == 1) || (i.value3 != 2 && i.value == 2) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value == 1 && i.value2 == 1) || (i.value == 2 && i.value3 != 2) RETURN i.value",
|
||||
"FOR i IN " + c.name() + " FILTER (i.value2 == 1 && i.value == 1) || (i.value3 == 1 && i.value == 2) RETURN i.value"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var plan = AQL_EXPLAIN(query).plan;
|
||||
var nodeTypes = plan.nodes.map(function(node) {
|
||||
return node.type;
|
||||
});
|
||||
|
||||
assertNotEqual(-1, nodeTypes.indexOf("IndexRangeNode"), query);
|
||||
var results = AQL_EXECUTE(query);
|
||||
assertEqual(2, results.json.length, query);
|
||||
assertTrue(results.stats.scannedIndex > 0);
|
||||
assertEqual(0, results.stats.scannedFull);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1304,6 +1407,249 @@ function optimizerIndexesTestSuite () {
|
|||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexAndSkiplistIndexedNonIndexed : function () {
|
||||
// value2 is not indexed
|
||||
AQL_EXECUTE("FOR i IN " + c.name() + " UPDATE i WITH { value2: i.value } IN " + c.name());
|
||||
|
||||
var queries = [
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 FILTER i.value2 == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 && i.value2 == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 FILTER i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 && i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 FILTER i.value2 != 1 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 && i.value2 != 1 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 1 FILTER i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 1 && i.value == 2 RETURN i",
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var plan = AQL_EXPLAIN(query).plan;
|
||||
var nodeTypes = plan.nodes.map(function(node) {
|
||||
return node.type;
|
||||
});
|
||||
|
||||
assertNotEqual(-1, nodeTypes.indexOf("IndexRangeNode"), query);
|
||||
var results = AQL_EXECUTE(query);
|
||||
assertEqual(1, results.json.length);
|
||||
assertEqual(2, results.json[0].value);
|
||||
assertTrue(results.stats.scannedIndex > 0);
|
||||
assertEqual(0, results.stats.scannedFull);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexAndHashIndexedNonIndexed : function () {
|
||||
// drop the skiplist index
|
||||
c.dropIndex(c.getIndexes()[1]);
|
||||
c.ensureHashIndex("value");
|
||||
// value2 is not indexed
|
||||
AQL_EXECUTE("FOR i IN " + c.name() + " UPDATE i WITH { value2: i.value } IN " + c.name());
|
||||
|
||||
var queries = [
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 FILTER i.value2 == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 && i.value2 == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 FILTER i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 && i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 FILTER i.value2 != 1 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 && i.value2 != 1 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 1 FILTER i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 1 && i.value == 2 RETURN i"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var plan = AQL_EXPLAIN(query).plan;
|
||||
var nodeTypes = plan.nodes.map(function(node) {
|
||||
return node.type;
|
||||
});
|
||||
|
||||
assertNotEqual(-1, nodeTypes.indexOf("IndexRangeNode"), query);
|
||||
var results = AQL_EXECUTE(query);
|
||||
assertEqual(1, results.json.length);
|
||||
assertEqual(2, results.json[0].value);
|
||||
assertTrue(results.stats.scannedIndex > 0);
|
||||
assertEqual(0, results.stats.scannedFull);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexAndAlternativeHashAndSkiplistIndexedNonIndexed : function () {
|
||||
// create a competitor index
|
||||
c.ensureHashIndex("value");
|
||||
|
||||
// value2 is not indexed
|
||||
AQL_EXECUTE("FOR i IN " + c.name() + " UPDATE i WITH { value2: i.value } IN " + c.name());
|
||||
|
||||
var queries = [
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 FILTER i.value2 == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 && i.value2 == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 FILTER i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 && i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 FILTER i.value2 != 1 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 && i.value2 != 1 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 1 FILTER i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 1 && i.value == 2 RETURN i"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var plan = AQL_EXPLAIN(query).plan;
|
||||
var nodeTypes = plan.nodes.map(function(node) {
|
||||
return node.type;
|
||||
});
|
||||
|
||||
assertNotEqual(-1, nodeTypes.indexOf("IndexRangeNode"), query);
|
||||
var results = AQL_EXECUTE(query);
|
||||
assertEqual(1, results.json.length);
|
||||
assertEqual(2, results.json[0].value);
|
||||
assertTrue(results.stats.scannedIndex > 0);
|
||||
assertEqual(0, results.stats.scannedFull);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexAndSkiplistPartialIndexedNonIndexed : function () {
|
||||
// drop the skiplist index
|
||||
c.dropIndex(c.getIndexes()[1]);
|
||||
|
||||
// create an alternative index
|
||||
c.ensureSkiplist("value", "value3");
|
||||
|
||||
// value2 is not indexed
|
||||
AQL_EXECUTE("FOR i IN " + c.name() + " UPDATE i WITH { value2: i.value } IN " + c.name());
|
||||
|
||||
var queries = [
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 FILTER i.value2 == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 && i.value2 == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 FILTER i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 && i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 FILTER i.value2 != 1 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 && i.value2 != 1 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 1 FILTER i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 1 && i.value == 2 RETURN i"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var plan = AQL_EXPLAIN(query).plan;
|
||||
var nodeTypes = plan.nodes.map(function(node) {
|
||||
return node.type;
|
||||
});
|
||||
|
||||
assertNotEqual(-1, nodeTypes.indexOf("IndexRangeNode"), query);
|
||||
var results = AQL_EXECUTE(query);
|
||||
assertEqual(1, results.json.length);
|
||||
assertEqual(2, results.json[0].value);
|
||||
assertTrue(results.stats.scannedIndex > 0);
|
||||
assertEqual(0, results.stats.scannedFull);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexAndAlternativeSkiplistPartialIndexedNonIndexed : function () {
|
||||
// create a competitor index
|
||||
c.ensureSkiplist("value", "value3");
|
||||
|
||||
// value2 is not indexed
|
||||
AQL_EXECUTE("FOR i IN " + c.name() + " UPDATE i WITH { value2: i.value } IN " + c.name());
|
||||
|
||||
var queries = [
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 FILTER i.value2 == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 && i.value2 == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 FILTER i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 == 2 && i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 FILTER i.value2 != 1 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value == 2 && i.value2 != 1 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 1 FILTER i.value == 2 RETURN i",
|
||||
"FOR i IN " + c.name() + " FILTER i.value2 != 1 && i.value == 2 RETURN i"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var plan = AQL_EXPLAIN(query).plan;
|
||||
var nodeTypes = plan.nodes.map(function(node) {
|
||||
return node.type;
|
||||
});
|
||||
|
||||
assertNotEqual(-1, nodeTypes.indexOf("IndexRangeNode"), query);
|
||||
var results = AQL_EXECUTE(query);
|
||||
assertEqual(1, results.json.length);
|
||||
assertEqual(2, results.json[0].value);
|
||||
assertTrue(results.stats.scannedIndex > 0);
|
||||
assertEqual(0, results.stats.scannedFull);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexNotNoIndex : function () {
|
||||
c.ensureSkiplist("value2");
|
||||
AQL_EXECUTE("FOR i IN " + c.name() + " UPDATE i WITH { value2: i.value } IN " + c.name());
|
||||
|
||||
var queries = [
|
||||
[ "FOR i IN " + c.name() + " FILTER NOT (i.value == 1 || i.value == 2) RETURN i", 1998 ],
|
||||
[ "FOR i IN " + c.name() + " FILTER NOT (i.value == 1 && i.value == 2) RETURN i", 2000 ],
|
||||
[ "FOR i IN " + c.name() + " FILTER i.value == 1 || NOT (i.value == -1) RETURN i", 2000 ]
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var plan = AQL_EXPLAIN(query[0]).plan;
|
||||
var nodeTypes = plan.nodes.map(function(node) {
|
||||
return node.type;
|
||||
});
|
||||
|
||||
assertEqual(-1, nodeTypes.indexOf("IndexRangeNode"), query);
|
||||
var results = AQL_EXECUTE(query[0]);
|
||||
assertEqual(query[1], results.json.length);
|
||||
assertTrue(results.stats.scannedFull > 0);
|
||||
assertEqual(0, results.stats.scannedIndex);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test index usage
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexNotUseIndex : function () {
|
||||
c.ensureSkiplist("value2");
|
||||
AQL_EXECUTE("FOR i IN " + c.name() + " UPDATE i WITH { value2: i.value } IN " + c.name());
|
||||
|
||||
var queries = [
|
||||
[ "FOR i IN " + c.name() + " FILTER NOT (i.value == 2) && i.value == 1 RETURN i", 1 ],
|
||||
[ "FOR i IN " + c.name() + " FILTER i.value == 1 && NOT (i.value == 2) RETURN i", 1 ],
|
||||
[ "FOR i IN " + c.name() + " FILTER i.value == 1 && NOT (i.value != 1) RETURN i", 1 ],
|
||||
[ "FOR i IN " + c.name() + " FILTER NOT (i.value != 1) && i.value == 1 RETURN i", 1 ],
|
||||
[ "FOR i IN " + c.name() + " FILTER i.value == 1 || NOT (i.value != -1) RETURN i", 1 ]
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var plan = AQL_EXPLAIN(query[0]).plan;
|
||||
var nodeTypes = plan.nodes.map(function(node) {
|
||||
return node.type;
|
||||
});
|
||||
|
||||
assertNotEqual(-1, nodeTypes.indexOf("IndexRangeNode"), query);
|
||||
var results = AQL_EXECUTE(query[0]);
|
||||
assertEqual(query[1], results.json.length);
|
||||
assertTrue(results.stats.scannedIndex > 0);
|
||||
assertEqual(0, results.stats.scannedFull);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue