mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of ssh://github.com/triAGENS/ArangoDB into devel
This commit is contained in:
commit
5369f08454
|
@ -1915,7 +1915,9 @@ ExecutionNode* AggregateNode::clone (ExecutionPlan* plan,
|
|||
auto aggregateVariables = _aggregateVariables;
|
||||
|
||||
if (withProperties) {
|
||||
outVariable = plan->getAst()->variables()->createVariable(outVariable);
|
||||
if (outVariable != nullptr) {
|
||||
outVariable = plan->getAst()->variables()->createVariable(outVariable);
|
||||
}
|
||||
|
||||
for (auto oneAggregate: _aggregateVariables) {
|
||||
auto in = plan->getAst()->variables()->createVariable(oneAggregate.first);
|
||||
|
@ -2242,7 +2244,9 @@ ExecutionNode* UpdateNode::clone (ExecutionPlan* plan,
|
|||
if (_outVariable != nullptr) {
|
||||
outVariable = plan->getAst()->variables()->createVariable(outVariable);
|
||||
}
|
||||
inKeyVariable = plan->getAst()->variables()->createVariable(inKeyVariable);
|
||||
if (inKeyVariable != nullptr) {
|
||||
inKeyVariable = plan->getAst()->variables()->createVariable(inKeyVariable);
|
||||
}
|
||||
inDocVariable = plan->getAst()->variables()->createVariable(inDocVariable);
|
||||
}
|
||||
|
||||
|
@ -2313,7 +2317,9 @@ ExecutionNode* ReplaceNode::clone (ExecutionPlan* plan,
|
|||
if (_outVariable != nullptr) {
|
||||
outVariable = plan->getAst()->variables()->createVariable(outVariable);
|
||||
}
|
||||
inKeyVariable = plan->getAst()->variables()->createVariable(inKeyVariable);
|
||||
if (inKeyVariable != nullptr) {
|
||||
inKeyVariable = plan->getAst()->variables()->createVariable(inKeyVariable);
|
||||
}
|
||||
inDocVariable = plan->getAst()->variables()->createVariable(inDocVariable);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,686 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests for query language, limit optimisations
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var jsunity = require("jsunity");
|
||||
var internal = require("internal");
|
||||
var helper = require("org/arangodb/aql-helper");
|
||||
var getQueryResults = helper.getQueryResults2;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function ahuacatlQueryOptimiserLimitTestSuite () {
|
||||
var collection = null;
|
||||
var cn = "UnitTestsAhuacatlOptimiserLimit";
|
||||
|
||||
var explain = function (query, params) {
|
||||
return helper.getCompactPlan(AQL_EXPLAIN(query, params, { optimizer: { rules: [ "-all", "+use-index-range" ] } })).map(function(node) { return node.type; });
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setUp : function () {
|
||||
internal.db._drop(cn);
|
||||
collection = internal.db._create(cn);
|
||||
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
collection.save({ "value" : i });
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tearDown : function () {
|
||||
internal.db._drop(cn);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation for non-collection access, limit > 0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNonCollectionNoRestriction : function () {
|
||||
var list = [ ];
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
list.push(i);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
{ offset: 0, limit: 500, expectedLength: 100 },
|
||||
{ offset: 0, limit: 50, expectedLength: 50 },
|
||||
{ offset: 0, limit: 5, expectedLength: 5 },
|
||||
{ offset: 0, limit: 1, expectedLength: 1 },
|
||||
{ offset: 1, limit: 50, expectedLength: 50 },
|
||||
{ offset: 1, limit: 1, expectedLength: 1 },
|
||||
{ offset: 10, limit: 50, expectedLength: 50 },
|
||||
{ offset: 95, limit: 5, expectedLength: 5 },
|
||||
{ offset: 95, limit: 50, expectedLength: 5 },
|
||||
{ offset: 98, limit: 50, expectedLength: 2 },
|
||||
{ offset: 98, limit: 2, expectedLength: 2 },
|
||||
{ offset: 99, limit: 1, expectedLength: 1 },
|
||||
{ offset: 99, limit: 2, expectedLength: 1 },
|
||||
{ offset: 100, limit: 2, expectedLength: 0 }
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
|
||||
var query = "FOR c IN " + JSON.stringify(list) + " LIMIT " + test.offset + ", " + test.limit + " RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(test.expectedLength, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "CalculationNode", "EnumerateListNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation for full collection access, limit > 0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionNoRestriction : function () {
|
||||
var tests = [
|
||||
{ offset: 0, limit: 500, expectedLength: 100 },
|
||||
{ offset: 0, limit: 50, expectedLength: 50 },
|
||||
{ offset: 0, limit: 5, expectedLength: 5 },
|
||||
{ offset: 0, limit: 1, expectedLength: 1 },
|
||||
{ offset: 1, limit: 50, expectedLength: 50 },
|
||||
{ offset: 1, limit: 1, expectedLength: 1 },
|
||||
{ offset: 10, limit: 50, expectedLength: 50 },
|
||||
{ offset: 95, limit: 5, expectedLength: 5 },
|
||||
{ offset: 95, limit: 50, expectedLength: 5 },
|
||||
{ offset: 98, limit: 50, expectedLength: 2 },
|
||||
{ offset: 98, limit: 2, expectedLength: 2 },
|
||||
{ offset: 99, limit: 1, expectedLength: 1 },
|
||||
{ offset: 99, limit: 2, expectedLength: 1 },
|
||||
{ offset: 100, limit: 2, expectedLength: 0 }
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
|
||||
var query = "FOR c IN " + cn + " LIMIT " + test.offset + ", " + test.limit + " RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(test.expectedLength, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "RemoteNode", "GatherNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation for non collection access, limit 0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNonCollectionNoRestrictionEmpty : function () {
|
||||
var list = [ ];
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
list.push(i);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
{ offset: 0, limit: 0 },
|
||||
{ offset: 1, limit: 0 },
|
||||
{ offset: 10, limit: 0 },
|
||||
{ offset: 95, limit: 0 },
|
||||
{ offset: 98, limit: 0 },
|
||||
{ offset: 99, limit: 0 },
|
||||
{ offset: 100, limit: 0 }
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
|
||||
var query = "FOR c IN " + JSON.stringify(list) + " LIMIT " + test.offset + ", " + test.limit + " RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(0, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "CalculationNode", "EnumerateListNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation for full collection access, limit 0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionNoRestrictionEmpty : function () {
|
||||
var tests = [
|
||||
{ offset: 0, limit: 0 },
|
||||
{ offset: 1, limit: 0 },
|
||||
{ offset: 10, limit: 0 },
|
||||
{ offset: 95, limit: 0 },
|
||||
{ offset: 98, limit: 0 },
|
||||
{ offset: 99, limit: 0 },
|
||||
{ offset: 100, limit: 0 }
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
|
||||
var query = "FOR c IN " + cn + " LIMIT " + test.offset + ", " + test.limit + " RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(0, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "RemoteNode", "GatherNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation for non-collection access, limit 0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNonCollectionDoubleLimitEmpty : function () {
|
||||
var list = [ ];
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
list.push(i);
|
||||
}
|
||||
|
||||
var query = "FOR c IN " + JSON.stringify(list) + " LIMIT 10 LIMIT 0 RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(0, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "CalculationNode", "EnumerateListNode", "LimitNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation for full collection access, limit 0
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionDoubleLimitEmpty : function () {
|
||||
var query = "FOR c IN " + cn + " LIMIT 10 LIMIT 0 RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(0, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "RemoteNode", "GatherNode", "LimitNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with 2 limits
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNonCollectionLimitLimit : function () {
|
||||
var list = [ ];
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
list.push(i);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
{ offset: 0, limit: 500, offset2: 0, limit2: 1, expectedLength: 1 },
|
||||
{ offset: 10, limit: 5, offset2: 0, limit2: 1, expectedLength: 1 },
|
||||
{ offset: 10, limit: 5, offset2: 0, limit2: 20, expectedLength: 5 },
|
||||
{ offset: 10, limit: 50, offset2: 1, limit2: 20, expectedLength: 20 },
|
||||
{ offset: 10, limit: 90, offset2: 10, limit2: 20, expectedLength: 20 },
|
||||
{ offset: 90, limit: 10, offset2: 9, limit2: 20, expectedLength: 1 },
|
||||
{ offset: 50, limit: 50, offset2: 0, limit2: 50, expectedLength: 50 },
|
||||
{ offset: 50, limit: 50, offset2: 10, limit2: 50, expectedLength: 40 },
|
||||
{ offset: 50, limit: 50, offset2: 50, limit2: 50, expectedLength: 0 }
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
|
||||
var query = "FOR c IN " + JSON.stringify(list) + " LIMIT " + test.offset + ", " + test.limit + " LIMIT " + test.offset2 + ", " + test.limit2 + " RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(test.expectedLength, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "CalculationNode", "EnumerateListNode", "LimitNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with 2 limits
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionLimitLimit : function () {
|
||||
var tests = [
|
||||
{ offset: 0, limit: 500, offset2: 0, limit2: 1, expectedLength: 1 },
|
||||
{ offset: 10, limit: 5, offset2: 0, limit2: 1, expectedLength: 1 },
|
||||
{ offset: 10, limit: 5, offset2: 0, limit2: 20, expectedLength: 5 },
|
||||
{ offset: 10, limit: 50, offset2: 1, limit2: 20, expectedLength: 20 },
|
||||
{ offset: 10, limit: 90, offset2: 10, limit2: 20, expectedLength: 20 },
|
||||
{ offset: 90, limit: 10, offset2: 9, limit2: 20, expectedLength: 1 },
|
||||
{ offset: 50, limit: 50, offset2: 0, limit2: 50, expectedLength: 50 },
|
||||
{ offset: 50, limit: 50, offset2: 10, limit2: 50, expectedLength: 40 },
|
||||
{ offset: 50, limit: 50, offset2: 50, limit2: 50, expectedLength: 0 }
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
|
||||
var query = "FOR c IN " + cn + " SORT c.value LIMIT " + test.offset + ", " + test.limit + " LIMIT " + test.offset2 + ", " + test.limit2 + " RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(test.expectedLength, actual.length);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation for non-collection access, limit > 0 and
|
||||
/// filter conditions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNonCollectionFilter : function () {
|
||||
var list = [ ];
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
list.push(i);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
{ offset: 0, limit: 500, value: 0, expectedLength: 100 },
|
||||
{ offset: 0, limit: 50, value: 0, expectedLength: 50 },
|
||||
{ offset: 0, limit: 5, value: 0, expectedLength: 5 },
|
||||
{ offset: 0, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 1, limit: 50, value: 0, expectedLength: 50 },
|
||||
{ offset: 1, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 10, limit: 50, value: 0, expectedLength: 50 },
|
||||
{ offset: 95, limit: 5, value: 0, expectedLength: 5 },
|
||||
{ offset: 95, limit: 50, value: 0, expectedLength: 5 },
|
||||
{ offset: 98, limit: 50, value: 0, expectedLength: 2 },
|
||||
{ offset: 98, limit: 2, value: 0, expectedLength: 2 },
|
||||
{ offset: 99, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 99, limit: 2, value: 0, expectedLength: 1 },
|
||||
{ offset: 100, limit: 2, value: 0, expectedLength: 0 },
|
||||
{ offset: 0, limit: 500, value: 10, expectedLength: 90 },
|
||||
{ offset: 0, limit: 50, value: 10, expectedLength: 50 },
|
||||
{ offset: 0, limit: 5, value: 10, expectedLength: 5 },
|
||||
{ offset: 0, limit: 1, value: 10, expectedLength: 1 },
|
||||
{ offset: 50, limit: 1, value: 10, expectedLength: 1 },
|
||||
{ offset: 90, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 89, limit: 1, value: 10, expectedLength: 1 },
|
||||
{ offset: 89, limit: 2, value: 10, expectedLength: 1 },
|
||||
{ offset: 90, limit: 1, value: 10, expectedLength: 0 },
|
||||
{ offset: 50, limit: 5, value: 40, expectedLength: 5 },
|
||||
{ offset: 50, limit: 5, value: 50, expectedLength: 0 }
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
|
||||
var query = "FOR c IN " + JSON.stringify(list) + " FILTER c >= " + test.value + " LIMIT " + test.offset + ", " + test.limit + " RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(test.expectedLength, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "CalculationNode", "EnumerateListNode", "CalculationNode", "FilterNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation for full collection access, limit > 0 and
|
||||
/// filter conditions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionFilter : function () {
|
||||
var tests = [
|
||||
{ offset: 0, limit: 500, value: 0, expectedLength: 100 },
|
||||
{ offset: 0, limit: 50, value: 0, expectedLength: 50 },
|
||||
{ offset: 0, limit: 5, value: 0, expectedLength: 5 },
|
||||
{ offset: 0, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 1, limit: 50, value: 0, expectedLength: 50 },
|
||||
{ offset: 1, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 10, limit: 50, value: 0, expectedLength: 50 },
|
||||
{ offset: 95, limit: 5, value: 0, expectedLength: 5 },
|
||||
{ offset: 95, limit: 50, value: 0, expectedLength: 5 },
|
||||
{ offset: 98, limit: 50, value: 0, expectedLength: 2 },
|
||||
{ offset: 98, limit: 2, value: 0, expectedLength: 2 },
|
||||
{ offset: 99, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 99, limit: 2, value: 0, expectedLength: 1 },
|
||||
{ offset: 100, limit: 2, value: 0, expectedLength: 0 },
|
||||
{ offset: 0, limit: 500, value: 10, expectedLength: 90 },
|
||||
{ offset: 0, limit: 50, value: 10, expectedLength: 50 },
|
||||
{ offset: 0, limit: 5, value: 10, expectedLength: 5 },
|
||||
{ offset: 0, limit: 1, value: 10, expectedLength: 1 },
|
||||
{ offset: 50, limit: 1, value: 10, expectedLength: 1 },
|
||||
{ offset: 90, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 89, limit: 1, value: 10, expectedLength: 1 },
|
||||
{ offset: 89, limit: 2, value: 10, expectedLength: 1 },
|
||||
{ offset: 90, limit: 1, value: 10, expectedLength: 0 },
|
||||
{ offset: 50, limit: 5, value: 40, expectedLength: 5 },
|
||||
{ offset: 50, limit: 5, value: 50, expectedLength: 0 }
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
|
||||
var query = "FOR c IN " + cn + " FILTER c.value >= " + test.value + " LIMIT " + test.offset + ", " + test.limit + " RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(test.expectedLength, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "RemoteNode", "GatherNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation for full collection access, limit > 0 and
|
||||
/// filter conditions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFilterFilterCollectionFilter : function () {
|
||||
var tests = [
|
||||
{ offset: 0, limit: 500, value: 0, expectedLength: 100 },
|
||||
{ offset: 0, limit: 50, value: 0, expectedLength: 50 },
|
||||
{ offset: 0, limit: 5, value: 0, expectedLength: 5 },
|
||||
{ offset: 0, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 1, limit: 50, value: 0, expectedLength: 50 },
|
||||
{ offset: 1, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 10, limit: 50, value: 0, expectedLength: 50 },
|
||||
{ offset: 95, limit: 5, value: 0, expectedLength: 5 },
|
||||
{ offset: 95, limit: 50, value: 0, expectedLength: 5 },
|
||||
{ offset: 98, limit: 50, value: 0, expectedLength: 2 },
|
||||
{ offset: 98, limit: 2, value: 0, expectedLength: 2 },
|
||||
{ offset: 99, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 99, limit: 2, value: 0, expectedLength: 1 },
|
||||
{ offset: 100, limit: 2, value: 0, expectedLength: 0 },
|
||||
{ offset: 0, limit: 500, value: 10, expectedLength: 90 },
|
||||
{ offset: 0, limit: 50, value: 10, expectedLength: 50 },
|
||||
{ offset: 0, limit: 5, value: 10, expectedLength: 5 },
|
||||
{ offset: 0, limit: 1, value: 10, expectedLength: 1 },
|
||||
{ offset: 50, limit: 1, value: 10, expectedLength: 1 },
|
||||
{ offset: 90, limit: 1, value: 0, expectedLength: 1 },
|
||||
{ offset: 89, limit: 1, value: 10, expectedLength: 1 },
|
||||
{ offset: 89, limit: 2, value: 10, expectedLength: 1 },
|
||||
{ offset: 90, limit: 1, value: 10, expectedLength: 0 },
|
||||
{ offset: 50, limit: 5, value: 40, expectedLength: 5 },
|
||||
{ offset: 50, limit: 5, value: 50, expectedLength: 0 }
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
|
||||
var query = "FOR c IN " + cn + " FILTER c.value >= " + test.value + " FILTER c.value <= 9999 LIMIT " + test.offset + ", " + test.limit + " RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(test.expectedLength, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "CalculationNode", "FilterNode", "RemoteNode", "GatherNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionHashIndex1 : function () {
|
||||
collection.ensureHashIndex("value");
|
||||
|
||||
var query = "FOR c IN " + cn + " FILTER c.value == 23 || c.value == 24 LIMIT 0, 10 SORT c.value RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(2, actual.length);
|
||||
assertEqual(23, actual[0].value);
|
||||
assertEqual(24, actual[1].value);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "RemoteNode", "GatherNode", "LimitNode", "CalculationNode", "SortNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionHashIndex2 : function () {
|
||||
collection.ensureHashIndex("value");
|
||||
|
||||
var query = "FOR c IN " + cn + " FILTER c.value >= 20 && c.value < 30 LIMIT 0, 10 SORT c.value RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(10, actual.length);
|
||||
assertEqual(20, actual[0].value);
|
||||
assertEqual(21, actual[1].value);
|
||||
assertEqual(29, actual[9].value);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "RemoteNode", "GatherNode", "LimitNode", "CalculationNode", "SortNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFilterFilterCollectionHashIndex : function () {
|
||||
collection.ensureHashIndex("value");
|
||||
|
||||
var query = "FOR c IN " + cn + " FILTER c.value >= 20 && c.value < 30 FILTER c.value <= 9999 LIMIT 0, 10 SORT c.value RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(10, actual.length);
|
||||
assertEqual(20, actual[0].value);
|
||||
assertEqual(21, actual[1].value);
|
||||
assertEqual(29, actual[9].value);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "CalculationNode", "FilterNode", "RemoteNode", "GatherNode", "LimitNode", "CalculationNode", "SortNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionSkiplistIndex1 : function () {
|
||||
collection.ensureSkiplist("value");
|
||||
|
||||
var query = "FOR c IN " + cn + " FILTER c.value == 23 || c.value == 24 LIMIT 0, 10 SORT c.value RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(2, actual.length);
|
||||
assertEqual(23, actual[0].value);
|
||||
assertEqual(24, actual[1].value);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "RemoteNode", "GatherNode", "LimitNode", "CalculationNode", "SortNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionSkiplistIndex2 : function () {
|
||||
collection.ensureSkiplist("value");
|
||||
|
||||
var query = "FOR c IN " + cn + " FILTER c.value >= 20 && c.value < 30 LIMIT 0, 10 SORT c.value RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(10, actual.length);
|
||||
assertEqual(20, actual[0].value);
|
||||
assertEqual(21, actual[1].value);
|
||||
assertEqual(29, actual[9].value);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "IndexRangeNode", "CalculationNode", "FilterNode", "RemoteNode", "GatherNode", "LimitNode", "CalculationNode", "SortNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFilterFilterSkiplistIndex : function () {
|
||||
collection.ensureSkiplist("value");
|
||||
|
||||
var query = "FOR c IN " + cn + " FILTER c.value >= 20 && c.value < 30 FILTER c.value <= 9999 LIMIT 0, 10 SORT c.value RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(10, actual.length);
|
||||
assertEqual(20, actual[0].value);
|
||||
assertEqual(21, actual[1].value);
|
||||
assertEqual(29, actual[9].value);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "IndexRangeNode", "CalculationNode", "FilterNode", "CalculationNode", "FilterNode", "RemoteNode", "GatherNode", "LimitNode", "CalculationNode", "SortNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with sort
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionSort1 : function () {
|
||||
var query = "FOR c IN " + cn + " FILTER c.value >= 20 && c.value < 30 LIMIT 0, 10 SORT c.value RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(10, actual.length);
|
||||
assertEqual(20, actual[0].value);
|
||||
assertEqual(21, actual[1].value);
|
||||
assertEqual(29, actual[9].value);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "RemoteNode", "GatherNode", "LimitNode", "CalculationNode", "SortNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with sort
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionSort2 : function () {
|
||||
var query = "FOR c IN " + cn + " FILTER c.value >= 20 && c.value < 30 LIMIT 0, 10 SORT c.value RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(10, actual.length);
|
||||
|
||||
assertEqual(20, actual[0].value);
|
||||
assertEqual(21, actual[1].value);
|
||||
assertEqual(22, actual[2].value);
|
||||
assertEqual(29, actual[9].value);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "RemoteNode", "GatherNode", "LimitNode", "CalculationNode", "SortNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with sort
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionSort3 : function () {
|
||||
var query = "FOR c IN " + cn + " SORT c.value LIMIT 0, 10 FILTER c.value >= 20 && c.value < 30 RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(0, actual.length);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "SortNode", "RemoteNode", "GatherNode", "LimitNode", "CalculationNode", "FilterNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit optimisation with sort
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitFullCollectionSort4 : function () {
|
||||
var query = "FOR c IN " + cn + " FILTER c.value >= 20 && c.value < 30 SORT c.value LIMIT 0, 10 RETURN c";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual(10, actual.length);
|
||||
|
||||
assertEqual(20, actual[0].value);
|
||||
assertEqual(21, actual[1].value);
|
||||
assertEqual(22, actual[2].value);
|
||||
assertEqual(29, actual[9].value);
|
||||
|
||||
assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "CalculationNode", "SortNode", "RemoteNode", "GatherNode", "LimitNode", "ReturnNode" ], explain(query));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit in nested loops
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNested1 : function () {
|
||||
var query = "FOR o IN [ 1, 2, 3 ] FOR i IN [ 5, 6, 7 ] LIMIT 2 RETURN { o: o, i: i }";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual([ { i: 5, o: 1 }, { i: 6, o: 1 } ], actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit in nested loops
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNested2 : function () {
|
||||
var query = "FOR o IN [ 1, 2, 3 ] FOR i IN [ 5, 6, 7 ] LIMIT 0, 1 RETURN { o: o, i: i }";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual([ { i: 5, o: 1 } ], actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit in nested loops
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNested3 : function () {
|
||||
var query = "FOR o IN [ 1, 2, 3 ] FOR i IN [ 5, 6, 7 ] SORT o, i LIMIT 1, 1 RETURN { o: o, i: i }";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual([ { i: 6, o: 1 } ], actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit in nested loops
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNested4 : function () {
|
||||
var query = "FOR o IN [ 1, 2, 3 ] LIMIT 1 FOR i IN [ 5, 6, 7 ] RETURN { o: o, i: i }";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual([ { i: 5, o: 1 }, { i: 6, o: 1 }, { i: 7, o: 1 } ], actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit in nested loops
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNested5 : function () {
|
||||
var query = "FOR o IN [ 1, 2, 3 ] LIMIT 1, 1 FOR i IN [ 5, 6, 7 ] RETURN { o: o, i: i }";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual([ { i: 5, o: 2 }, { i: 6, o: 2 }, { i: 7, o: 2 } ], actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check limit in nested loops
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testLimitNested6 : function () {
|
||||
var query = "FOR o IN [ 1, 2, 3 ] LIMIT 1 FOR i IN [ 5, 6, 7 ] LIMIT 2 RETURN { o: o, i: i }";
|
||||
|
||||
var actual = getQueryResults(query);
|
||||
assertEqual([ { i: 5, o: 1 }, { i: 6, o: 1 } ], actual);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsunity.run(ahuacatlQueryOptimiserLimitTestSuite);
|
||||
|
||||
return jsunity.done();
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
Loading…
Reference in New Issue