/*global require, assertEqual */ //////////////////////////////////////////////////////////////////////////////// /// @brief test the statement class /// /// @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 arangodb = require("org/arangodb"); var ArangoStatement = require("org/arangodb/arango-statement").ArangoStatement; var db = arangodb.db; var ERRORS = arangodb.errors; //// var helper = require("org/arangodb/aql-helper"); function getLinearizedPlan (explainResult) { var nodes = explainResult.plan.nodes, i; var lookup = { }, deps = { }; for (i = 0; i < nodes.length; ++i) { var node = nodes[i]; lookup[node.id] = node; var dependency = -1; if (node.dependencies.length > 0) { dependency = node.dependencies[0]; } deps[dependency] = node.id; } var current = -1; var out = [ ]; while (true) { if (! deps.hasOwnProperty(current)) { break; } var n = lookup[deps[current]]; current = n.id; out.push(n); } return out; } function getCompactPlan (explainResult) { var out = [ ]; function buildExpression (node) { var out = node.type; if (node.hasOwnProperty("name")) { out += "[" + node.name + "]"; } if (node.hasOwnProperty("value")) { out += "[" + node.value + "]"; } if (Array.isArray(node.subNodes)) { out += "("; node.subNodes.forEach(function (node, i) { if (i > 0) { out += ", "; } out += buildExpression(node); }); out += ")"; } return out; } getLinearizedPlan(explainResult).forEach(function (node) { var data = { type: node.type }; if (node.expression) { data.expression = buildExpression(node.expression); } if (node.outVariable) { data.outVariable = node.outVariable.name; } out.push(data); }); return out; } // ----------------------------------------------------------------------------- // --SECTION-- explain tests // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief test suite //////////////////////////////////////////////////////////////////////////////// function ExplainSuite () { var cn = "UnitTestsExplain"; var explain = function (result) { return getCompactPlan(result).map(function(node) { return node.type; }); }; return { //////////////////////////////////////////////////////////////////////////////// /// @brief set up //////////////////////////////////////////////////////////////////////////////// setUp : function () { db._drop(cn); db._create(cn); }, //////////////////////////////////////////////////////////////////////////////// /// @brief tear down //////////////////////////////////////////////////////////////////////////////// tearDown : function () { db._drop(cn); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainError : function () { var st = new ArangoStatement(db, { query : "for u in" }); try { st.explain(); } catch (e) { assertEqual(ERRORS.ERROR_QUERY_PARSE.code, e.errorNum); } }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainNoBindError : function () { var st = new ArangoStatement(db, { query : "for i in [ 1 ] return @f" }); try { st.explain(); } catch (e) { assertEqual(ERRORS.ERROR_QUERY_BIND_PARAMETER_MISSING.code, e.errorNum); } }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainWithBind : function () { var st = new ArangoStatement(db, { query : "for i in [ 1 ] return @f", bindVars: { f : 99 } }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("CalculationNode", node.type); node = nodes[2]; assertEqual("CalculationNode", node.type); node = nodes[3]; assertEqual("EnumerateListNode", node.type); node = nodes[4]; assertEqual("ReturnNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainWithBindCollection : function () { var st = new ArangoStatement(db, { query : "for i in @@cn return i", bindVars: { "@cn": cn } }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("i", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("RemoteNode", node.type); node = nodes[3]; assertEqual("GatherNode", node.type); node = nodes[4]; assertEqual("ReturnNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainOk1 : function () { var st = new ArangoStatement(db, { query : "for u in [ 1, 2, 3 ] return u" }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("CalculationNode", node.type); node = nodes[2]; assertEqual("EnumerateListNode", node.type); assertEqual("u", node.outVariable.name); node = nodes[3]; assertEqual("ReturnNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainOk2 : function () { var st = new ArangoStatement(db, { query : "for u in [ 1, 2, 3 ] filter u != 1 for f in u return f" }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("CalculationNode", node.type); node = nodes[2]; assertEqual("EnumerateListNode", node.type); node = nodes[3]; assertEqual("CalculationNode", node.type); node = nodes[4]; assertEqual("FilterNode", node.type); node = nodes[5]; assertEqual("EnumerateListNode", node.type); node = nodes[6]; assertEqual("ReturnNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainRemove1 : function () { var st = new ArangoStatement(db, { query : "for u in " + cn + " remove u in " + cn }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("RemoveNode", node.type); assertEqual(cn, node.collection); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainRemove2 : function () { var st = new ArangoStatement(db, { query : "for u in @@cn remove u in @@cn", bindVars: { "@cn" : cn } }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("RemoveNode", node.type); assertEqual(cn, node.collection); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainInsert1 : function () { var st = new ArangoStatement(db, { query : "for u in @@cn insert u in @@cn", bindVars: { "@cn": cn } }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("RemoteNode", node.type); node = nodes[3]; assertEqual("GatherNode", node.type); node = nodes[4]; assertEqual("DistributeNode", node.type); node = nodes[5]; assertEqual("RemoteNode", node.type); node = nodes[6]; assertEqual("InsertNode", node.type); assertEqual(cn, node.collection); node = nodes[7]; assertEqual("RemoteNode", node.type); node = nodes[8]; assertEqual("GatherNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainInsert2 : function () { var st = new ArangoStatement(db, { query : "for u in " + cn + " insert u in " + cn }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("RemoteNode", node.type); node = nodes[3]; assertEqual("GatherNode", node.type); node = nodes[4]; assertEqual("DistributeNode", node.type); node = nodes[5]; assertEqual("RemoteNode", node.type); node = nodes[6]; assertEqual("InsertNode", node.type); assertEqual(cn, node.collection); node = nodes[7]; assertEqual("RemoteNode", node.type); node = nodes[8]; assertEqual("GatherNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainUpdate1 : function () { var st = new ArangoStatement(db, { query : "for u in @@cn update u._key with u in @@cn", bindVars: { "@cn": cn } }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("CalculationNode", node.type); node = nodes[3]; assertEqual("RemoteNode", node.type); node = nodes[4]; assertEqual("GatherNode", node.type); node = nodes[5]; assertEqual("ScatterNode", node.type); node = nodes[6]; assertEqual("RemoteNode", node.type); node = nodes[7]; assertEqual("UpdateNode", node.type); assertEqual(cn, node.collection); node = nodes[8]; assertEqual("RemoteNode", node.type); node = nodes[9]; assertEqual("GatherNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainUpdate2 : function () { var st = new ArangoStatement(db, { query : "for u in " + cn + " update u._key with u in " + cn }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("CalculationNode", node.type); node = nodes[3]; assertEqual("RemoteNode", node.type); node = nodes[4]; assertEqual("GatherNode", node.type); node = nodes[5]; assertEqual("ScatterNode", node.type); node = nodes[6]; assertEqual("RemoteNode", node.type); node = nodes[7]; assertEqual("UpdateNode", node.type); assertEqual(cn, node.collection); node = nodes[8]; assertEqual("RemoteNode", node.type); node = nodes[9]; assertEqual("GatherNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainUpdate3 : function () { var st = new ArangoStatement(db, { query : "for u in @@cn update u in @@cn", bindVars: { "@cn": cn } }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("RemoteNode", node.type); node = nodes[3]; assertEqual("GatherNode", node.type); node = nodes[4]; assertEqual("ScatterNode", node.type); node = nodes[5]; assertEqual("RemoteNode", node.type); node = nodes[6]; assertEqual("UpdateNode", node.type); assertEqual(cn, node.collection); node = nodes[7]; assertEqual("RemoteNode", node.type); node = nodes[8]; assertEqual("GatherNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainUpdate4 : function () { var st = new ArangoStatement(db, { query : "for u in " + cn + " update u in " + cn }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("RemoteNode", node.type); node = nodes[3]; assertEqual("GatherNode", node.type); node = nodes[4]; assertEqual("ScatterNode", node.type); node = nodes[5]; assertEqual("RemoteNode", node.type); node = nodes[6]; assertEqual("UpdateNode", node.type); assertEqual(cn, node.collection); node = nodes[7]; assertEqual("RemoteNode", node.type); node = nodes[8]; assertEqual("GatherNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainReplace1 : function () { var st = new ArangoStatement(db, { query : "for u in @@cn replace u._key with u in @@cn", bindVars: { "@cn": cn } }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("CalculationNode", node.type); node = nodes[3]; assertEqual("RemoteNode", node.type); node = nodes[4]; assertEqual("GatherNode", node.type); node = nodes[5]; assertEqual("ScatterNode", node.type); node = nodes[6]; assertEqual("RemoteNode", node.type); node = nodes[7]; assertEqual("ReplaceNode", node.type); assertEqual(cn, node.collection); node = nodes[8]; assertEqual("RemoteNode", node.type); node = nodes[9]; assertEqual("GatherNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainReplace2 : function () { var st = new ArangoStatement(db, { query : "for u in " + cn + " replace u._key with u in " + cn }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("CalculationNode", node.type); node = nodes[3]; assertEqual("RemoteNode", node.type); node = nodes[4]; assertEqual("GatherNode", node.type); node = nodes[5]; assertEqual("ScatterNode", node.type); node = nodes[6]; assertEqual("RemoteNode", node.type); node = nodes[7]; assertEqual("ReplaceNode", node.type); assertEqual(cn, node.collection); node = nodes[8]; assertEqual("RemoteNode", node.type); node = nodes[9]; assertEqual("GatherNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainReplace3 : function () { var st = new ArangoStatement(db, { query : "for u in @@cn replace u in @@cn", bindVars: { "@cn": cn } }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("RemoteNode", node.type); node = nodes[3]; assertEqual("GatherNode", node.type); node = nodes[4]; assertEqual("ScatterNode", node.type); node = nodes[5]; assertEqual("RemoteNode", node.type); node = nodes[6]; assertEqual("ReplaceNode", node.type); assertEqual(cn, node.collection); node = nodes[7]; assertEqual("RemoteNode", node.type); node = nodes[8]; assertEqual("GatherNode", node.type); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test explain method //////////////////////////////////////////////////////////////////////////////// testExplainReplace4 : function () { var st = new ArangoStatement(db, { query : "for u in " + cn + " replace u in " + cn }); var nodes = st.explain().plan.nodes, node; node = nodes[0]; assertEqual("SingletonNode", node.type); node = nodes[1]; assertEqual("EnumerateCollectionNode", node.type); assertEqual("u", node.outVariable.name); assertEqual(cn, node.collection); node = nodes[2]; assertEqual("RemoteNode", node.type); node = nodes[3]; assertEqual("GatherNode", node.type); node = nodes[4]; assertEqual("ScatterNode", node.type); node = nodes[5]; assertEqual("RemoteNode", node.type); node = nodes[6]; assertEqual("ReplaceNode", node.type); assertEqual(cn, node.collection); node = nodes[7]; assertEqual("RemoteNode", node.type); node = nodes[8]; assertEqual("GatherNode", node.type); } }; } // ----------------------------------------------------------------------------- // --SECTION-- main // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @brief executes the test suite //////////////////////////////////////////////////////////////////////////////// jsunity.run(ExplainSuite); return jsunity.done(); // Local Variables: // mode: outline-minor // outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" // End: