mirror of https://gitee.com/bigwinds/arangodb
286 lines
10 KiB
JavaScript
286 lines
10 KiB
JavaScript
/*jshint globalstrict:false, strict:false, maxlen: 500 */
|
|
/*global fail, assertEqual, assertTrue, assertFalse, AQL_EXPLAIN */
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief tests for optimizer rules
|
|
///
|
|
/// @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 errors = require("internal").errors;
|
|
var db = require("@arangodb").db;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief test suite
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
function explainSuite () {
|
|
var cn = "UnitTestsAhuacatlExplain";
|
|
var c;
|
|
|
|
return {
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief set up
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
setUpAll : function () {
|
|
db._drop(cn);
|
|
c = db._create(cn);
|
|
},
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief tear down
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
tearDownAll : function () {
|
|
db._drop(cn);
|
|
},
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief test bind parameters
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
testExplainBindMissing : function () {
|
|
var actual;
|
|
var query = "RETURN @foo";
|
|
|
|
try {
|
|
actual = AQL_EXPLAIN(query);
|
|
fail();
|
|
} catch (err) {
|
|
assertEqual(err.errorNum, errors.ERROR_QUERY_BIND_PARAMETER_MISSING.code);
|
|
}
|
|
},
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief test bind parameters
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
testExplainBindPresent : function () {
|
|
var actual;
|
|
var query = "RETURN @foo";
|
|
|
|
actual = AQL_EXPLAIN(query, { foo: "bar" });
|
|
assertEqual(3, actual.plan.nodes.length);
|
|
assertEqual("SingletonNode", actual.plan.nodes[0].type);
|
|
assertEqual("CalculationNode", actual.plan.nodes[1].type);
|
|
assertEqual("ReturnNode", actual.plan.nodes[2].type);
|
|
},
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief test verbosity w/ single plan
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
testExplainVerbosity : function () {
|
|
var actual;
|
|
var query = "FOR i IN " + cn + " FOR j IN " + cn + " RETURN i";
|
|
|
|
// single plan, no options
|
|
actual = AQL_EXPLAIN(query);
|
|
assertTrue(actual.hasOwnProperty("plan"));
|
|
assertFalse(Array.isArray(actual.plan));
|
|
assertTrue(actual.plan.hasOwnProperty("nodes"));
|
|
assertTrue(Array.isArray(actual.plan.nodes));
|
|
assertTrue(actual.plan.hasOwnProperty("rules"));
|
|
assertTrue(Array.isArray(actual.plan.rules));
|
|
assertTrue(actual.plan.hasOwnProperty("estimatedCost"));
|
|
|
|
actual.plan.nodes.forEach(function(node) {
|
|
assertTrue(node.hasOwnProperty("type"));
|
|
assertFalse(node.hasOwnProperty("typeID")); // deactivated if not verbose
|
|
assertTrue(node.hasOwnProperty("dependencies"));
|
|
assertTrue(Array.isArray(node.dependencies));
|
|
assertFalse(node.hasOwnProperty("parents")); // deactivated if not verbose
|
|
assertTrue(node.hasOwnProperty("id"));
|
|
assertTrue(node.hasOwnProperty("estimatedCost"));
|
|
});
|
|
|
|
// single plan, verbose options
|
|
actual = AQL_EXPLAIN(query, { }, { verbosePlans: true });
|
|
assertTrue(actual.hasOwnProperty("plan"));
|
|
assertFalse(Array.isArray(actual.plan));
|
|
assertTrue(actual.plan.hasOwnProperty("nodes"));
|
|
assertTrue(Array.isArray(actual.plan.nodes));
|
|
assertTrue(actual.plan.hasOwnProperty("rules"));
|
|
assertTrue(Array.isArray(actual.plan.rules));
|
|
|
|
actual.plan.nodes.forEach(function(node) {
|
|
assertTrue(node.hasOwnProperty("type"));
|
|
assertTrue(node.hasOwnProperty("typeID"));
|
|
assertTrue(node.hasOwnProperty("dependencies"));
|
|
assertTrue(Array.isArray(node.dependencies));
|
|
assertTrue(node.hasOwnProperty("parents"));
|
|
assertTrue(Array.isArray(node.parents));
|
|
assertTrue(node.hasOwnProperty("id"));
|
|
assertTrue(node.hasOwnProperty("estimatedCost"));
|
|
});
|
|
},
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief test explain w/ a signle plan vs. all plans
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
testExplainAllPlansVsSingle : function () {
|
|
var actual;
|
|
var query = "FOR i IN " + cn + " FOR j IN " + cn + " RETURN i";
|
|
|
|
// single plan
|
|
actual = AQL_EXPLAIN(query, { }, { verbosePlans: true });
|
|
assertTrue(actual.hasOwnProperty("plan"));
|
|
assertFalse(actual.hasOwnProperty("plans"));
|
|
assertFalse(Array.isArray(actual.plan));
|
|
|
|
assertTrue(actual.plan.hasOwnProperty("nodes"));
|
|
assertTrue(Array.isArray(actual.plan.nodes));
|
|
|
|
actual.plan.nodes.forEach(function(node) {
|
|
assertTrue(node.hasOwnProperty("type"));
|
|
assertTrue(node.hasOwnProperty("typeID"));
|
|
assertTrue(node.hasOwnProperty("dependencies"));
|
|
assertTrue(Array.isArray(node.dependencies));
|
|
assertTrue(node.hasOwnProperty("parents"));
|
|
assertTrue(node.hasOwnProperty("id"));
|
|
assertTrue(node.hasOwnProperty("estimatedCost"));
|
|
});
|
|
|
|
assertTrue(actual.plan.hasOwnProperty("rules"));
|
|
assertTrue(Array.isArray(actual.plan.rules));
|
|
|
|
|
|
// multiple plans
|
|
actual = AQL_EXPLAIN(query, { }, { allPlans: true, verbosePlans: true });
|
|
assertFalse(actual.hasOwnProperty("plan"));
|
|
assertTrue(actual.hasOwnProperty("plans"));
|
|
assertTrue(Array.isArray(actual.plans));
|
|
|
|
actual.plans.forEach(function (plan) {
|
|
assertTrue(plan.hasOwnProperty("nodes"));
|
|
assertTrue(Array.isArray(plan.nodes));
|
|
|
|
plan.nodes.forEach(function(node) {
|
|
assertTrue(node.hasOwnProperty("type"));
|
|
assertTrue(node.hasOwnProperty("typeID"));
|
|
assertTrue(node.hasOwnProperty("dependencies"));
|
|
assertTrue(Array.isArray(node.dependencies));
|
|
assertTrue(node.hasOwnProperty("parents"));
|
|
assertTrue(node.hasOwnProperty("id"));
|
|
assertTrue(node.hasOwnProperty("estimatedCost"));
|
|
});
|
|
|
|
assertTrue(plan.hasOwnProperty("rules"));
|
|
assertTrue(Array.isArray(plan.rules));
|
|
});
|
|
},
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief test nodes in plan
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
testNodes : function () {
|
|
var actual;
|
|
var query = "FOR i IN " + cn + " FILTER i.value > 1 LET a = i.value / 2 SORT a DESC COLLECT x = a INTO g RETURN x";
|
|
|
|
actual = AQL_EXPLAIN(query, null, { optimizer: { rules: [ "-all" ] } });
|
|
var nodes = actual.plan.nodes, node;
|
|
|
|
node = nodes[0];
|
|
assertEqual("SingletonNode", node.type);
|
|
assertEqual([ ], node.dependencies);
|
|
assertEqual(1, node.id);
|
|
|
|
node = nodes[1];
|
|
assertEqual("EnumerateCollectionNode", node.type);
|
|
assertEqual([ 1 ], node.dependencies);
|
|
assertEqual(2, node.id);
|
|
assertEqual("_system", node.database);
|
|
assertEqual(cn, node.collection);
|
|
assertEqual("i", node.outVariable.name);
|
|
|
|
node = nodes[2];
|
|
assertEqual("CalculationNode", node.type);
|
|
assertEqual([ 2 ], node.dependencies);
|
|
assertEqual(3, node.id);
|
|
assertTrue(node.hasOwnProperty("expression"));
|
|
assertFalse(node.canThrow);
|
|
var out = node.outVariable.name;
|
|
|
|
node = nodes[3];
|
|
assertEqual("FilterNode", node.type);
|
|
assertEqual([ 3 ], node.dependencies);
|
|
assertEqual(4, node.id);
|
|
assertEqual(out, node.inVariable.name);
|
|
|
|
node = nodes[4];
|
|
assertEqual("CalculationNode", node.type);
|
|
assertEqual([ 4 ], node.dependencies);
|
|
assertEqual(5, node.id);
|
|
assertTrue(node.hasOwnProperty("expression"));
|
|
assertEqual("a", node.outVariable.name);
|
|
assertFalse(node.canThrow);
|
|
|
|
node = nodes[5];
|
|
assertEqual("SortNode", node.type);
|
|
assertEqual([ 5 ], node.dependencies);
|
|
assertEqual(6, node.id);
|
|
assertEqual(1, node.elements.length);
|
|
assertEqual("a", node.elements[0].inVariable.name);
|
|
assertFalse(node.stable);
|
|
|
|
node = nodes[6];
|
|
assertEqual("SortNode", node.type);
|
|
assertEqual([ 6 ], node.dependencies);
|
|
assertEqual(9, node.id);
|
|
assertEqual(1, node.elements.length);
|
|
assertEqual("a", node.elements[0].inVariable.name);
|
|
assertTrue(node.stable);
|
|
|
|
node = nodes[7];
|
|
assertEqual("CollectNode", node.type);
|
|
assertEqual([ 9 ], node.dependencies);
|
|
assertEqual(7, node.id);
|
|
assertEqual(1, node.groups.length);
|
|
assertEqual("a", node.groups[0].inVariable.name);
|
|
assertEqual("x", node.groups[0].outVariable.name);
|
|
assertEqual("g", node.outVariable.name);
|
|
|
|
node = nodes[8];
|
|
assertEqual("ReturnNode", node.type);
|
|
assertEqual([ 7 ], node.dependencies);
|
|
assertEqual(8, node.id);
|
|
assertEqual("x", node.inVariable.name);
|
|
}
|
|
|
|
};
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief executes the test suite
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
jsunity.run(explainSuite);
|
|
|
|
return jsunity.done();
|
|
|