1
0
Fork 0

Merge branch 'devel' of github.com:arangodb/arangodb into devel

* 'devel' of github.com:arangodb/arangodb:
  grunt build [ci skip]
  aql tabular output
  fixed issue #1949
  fixed issue #1950
This commit is contained in:
Jan Christoph Uhde 2016-07-20 09:11:01 +00:00
commit 95b5c3b50c
14 changed files with 225 additions and 72 deletions

View File

@ -32,6 +32,10 @@ devel
v3.0.4 (XXXX-XX-XX)
-------------------
* fixed issue #1950
* fixed issue #1949
* fixed segfault in V8, by backporting https://bugs.chromium.org/p/v8/issues/detail?id=5033
* Foxx OAuth2 module now correctly passes the `access_token` to the OAuth2 server

View File

@ -1239,12 +1239,12 @@ class arangodb::aql::RedundantCalculationsReplacer final
public:
explicit RedundantCalculationsReplacer(
std::unordered_map<VariableId, Variable const*> const& replacements)
: _replacements(replacements) {}
: _replacements(replacements) {
}
template <typename T>
void replaceInVariable(ExecutionNode* en) {
auto node = static_cast<T*>(en);
node->_inVariable = Variable::replace(node->_inVariable, _replacements);
}
@ -1252,7 +1252,7 @@ class arangodb::aql::RedundantCalculationsReplacer final
auto node = static_cast<CalculationNode*>(en);
std::unordered_set<Variable const*> variables;
node->expression()->variables(variables);
// check if the calculation uses any of the variables that we want to
// replace
for (auto const& it : variables) {
@ -3784,6 +3784,14 @@ void arangodb::aql::inlineSubqueriesRule(Optimizer* opt,
auto queryVariables = plan->getAst()->variables();
std::vector<ExecutionNode*> subNodes(subqueryNode->getSubquery()->getDependencyChain(true));
// check if the subquery result variable is used after the FOR loop as well
std::unordered_set<Variable const*> varsUsedLater(listNode->getVarsUsedLater());
if (varsUsedLater.find(listNode->inVariable()) != varsUsedLater.end()) {
// exit the loop
current = nullptr;
break;
}
TRI_ASSERT(! subNodes.empty());
auto returnNode = static_cast<ReturnNode*>(subNodes[0]);
TRI_ASSERT(returnNode->getType() == EN::RETURN);

File diff suppressed because one or more lines are too long

View File

@ -2270,7 +2270,14 @@ if (list.length > 0) {
<div class="pull-right">
<span class="action"><i class="fa fa-close" element="outputEditor<%= counter %>" style="display: none"></i></span>
</div>
<div class="pull-right"> <% if (type === 'Query') { %> <span class="switchAce" counter="<%=counter%>" style="display: none">Result</span> <% } else { %> <span class="switchAce" counter="<%=counter%>">AQL</span> <% } %> </div>
<div class="pull-right">
<div class="switchAce" counter="<%=counter%>">
<span id="json-switch" val="JSON" counter="<%=counter%>">JSON</span>
<span id="table-switch" val="Table" counter="<%=counter%>" style="display: none">Table</span>
<span id="graph-switch" val="Graph" counter="<%=counter%>" style="display: none">Graph</span>
<span id="aql-switch" val="AQL" counter="<%=counter%>">AQL</span>
</div>
</div>
</div>
<div id="outputEditor<%= counter %>" style="opacity: 0.5"></div>
<div id="sentWrapper<%= counter %>" class="sentWrapper" style="display: none">
@ -2698,4 +2705,4 @@ var cutByResolution = function (str) {
</div>
<div id="workMonitorContent" class="innerContent">
</div></script></head><body><nav class="navbar" style="display: none"><div class="primary"><div class="navlogo"><a class="logo big" href="#"><img class="arangodbLogo" src="img/arangodb_logo_big.png"></a><a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a><a class="version"><span>VERSION: </span><span id="currentVersion"></span></a></div><div class="statmenu" id="statisticBar"></div><div class="navmenu" id="navigationBar"></div></div></nav><div id="modalPlaceholder"></div><div class="bodyWrapper" style="display: none"><div class="centralRow"><div id="navbar2" class="navbarWrapper secondary"><div class="subnavmenu" id="subNavigationBar"></div></div><div class="resizecontainer contentWrapper"><div id="loadingScreen" class="loadingScreen" style="display: none"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw margin-bottom"></i> <span class="sr-only">Loading...</span></div><div id="content" class="centralContent"></div><footer class="footer"><div id="footerBar"></div></footer></div></div></div><div id="progressPlaceholder" style="display:none"></div><div id="spotlightPlaceholder" style="display:none"></div><div id="graphSettingsContent" style="display: none"></div><div id="offlinePlaceholder" style="display:none"><div class="offline-div"><div class="pure-u"><div class="pure-u-1-4"></div><div class="pure-u-1-2 offline-window"><div class="offline-header"><h3>You have been disconnected from the server</h3></div><div class="offline-body"><p>The connection to the server has been lost. The server may be under heavy load.</p><p>Trying to reconnect in <span id="offlineSeconds">10</span> seconds.</p><p class="animation_state"><span><button class="button-success">Reconnect now</button></span></p></div></div><div class="pure-u-1-4"></div></div></div></div><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="libs.js?version=1468931748660"></script><script src="app.js?version=1468931748660"></script></body></html>
</div></script></head><body><nav class="navbar" style="display: none"><div class="primary"><div class="navlogo"><a class="logo big" href="#"><img class="arangodbLogo" src="img/arangodb_logo_big.png"></a><a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a><a class="version"><span>VERSION: </span><span id="currentVersion"></span></a></div><div class="statmenu" id="statisticBar"></div><div class="navmenu" id="navigationBar"></div></div></nav><div id="modalPlaceholder"></div><div class="bodyWrapper" style="display: none"><div class="centralRow"><div id="navbar2" class="navbarWrapper secondary"><div class="subnavmenu" id="subNavigationBar"></div></div><div class="resizecontainer contentWrapper"><div id="loadingScreen" class="loadingScreen" style="display: none"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw margin-bottom"></i> <span class="sr-only">Loading...</span></div><div id="content" class="centralContent"></div><footer class="footer"><div id="footerBar"></div></footer></div></div></div><div id="progressPlaceholder" style="display:none"></div><div id="spotlightPlaceholder" style="display:none"></div><div id="graphSettingsContent" style="display: none"></div><div id="offlinePlaceholder" style="display:none"><div class="offline-div"><div class="pure-u"><div class="pure-u-1-4"></div><div class="pure-u-1-2 offline-window"><div class="offline-header"><h3>You have been disconnected from the server</h3></div><div class="offline-body"><p>The connection to the server has been lost. The server may be under heavy load.</p><p>Trying to reconnect in <span id="offlineSeconds">10</span> seconds.</p><p class="animation_state"><span><button class="button-success">Reconnect now</button></span></p></div></div><div class="pure-u-1-4"></div></div></div></div><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="libs.js?version=1469003996721"></script><script src="app.js?version=1469003996721"></script></body></html>

File diff suppressed because one or more lines are too long

View File

@ -194,7 +194,7 @@
// fetch just the first 25 attributes of the document
// this number is arbitrary, but may reduce HTTP traffic a bit
query = 'FOR x IN @@collection LET att = SLICE(ATTRIBUTES(x), 0, 25)';
query = 'FOR x IN @@collection LET att = APPEND(SLICE(ATTRIBUTES(x), 0, 25), "_key", true)';
query += this.setFiltersForQuery(bindVars);
// Sort result, only useful for a small number of docs
if (this.getTotal() < this.MAX_SORT) {

View File

@ -1475,13 +1475,19 @@
var result = self.analyseQuery(data.result);
console.log('Using ' + result.defaultType + ' as data format.');
if (result.defaultType === 'table') {
$('#outputEditorWrapper' + counter).append('<div id="outputTable' + counter + '"></div>');
$('#outputEditorWrapper' + counter + ' .arangoToolbarTop').after('<div id="outputTable' + counter + '"></div>');
$('#outputTable' + counter).show();
self.renderOutputTable(result, counter);
// apply max height for table output dynamically
var maxHeight = $('.centralRow').height() - 250;
$('.outputEditorWrapper .tableWrapper').css('max-height', maxHeight);
$('#outputEditor' + counter).hide();
} else if (result.defaultType === 'graph') {
$('#outputEditorWrapper' + counter).append('<div id="outputGraph' + counter + '"></div>');
$('#outputEditorWrapper' + counter + ' .arangoToolbarTop').after('<div id="outputGraph' + counter + '"></div>');
$('#outputGraph' + counter).show();
self.renderOutputGraph(result, data);
$('#outputEditor' + counter).hide();
}
@ -1618,82 +1624,92 @@
// check if result could be displayed as graph
// case a) result has keys named vertices and edges
if (result[0].vertices && result[0].edges) {
var hitsa = 0;
var totala = 0;
if (result[0]) {
if (result[0].vertices && result[0].edges) {
var hitsa = 0;
var totala = 0;
_.each(result, function (obj) {
if (obj.edges) {
totala += obj.edges.length;
_.each(result, function (obj) {
if (obj.edges) {
totala += obj.edges.length;
_.each(obj.edges, function (edge) {
if (edge._from && edge._to) {
hitsa++;
}
});
_.each(obj.edges, function (edge) {
if (edge._from && edge._to) {
hitsa++;
}
});
}
});
var percentagea = hitsa / totala * 100;
if (percentagea >= 95) {
found = true;
toReturn.defaultType = 'graph';
}
});
} else {
// case b) 95% have _from and _to attribute
var hitsb = 0;
var totalb = result.length;
var percentagea = hitsa / totala * 100;
_.each(result, function (obj) {
if (obj._from && obj._to) {
hitsb++;
}
});
if (percentagea >= 95) {
found = true;
toReturn.defaultType = 'graph';
}
} else {
// case b) 95% have _from and _to attribute
var hitsb = 0;
var totalb = result.length;
var percentageb = hitsb / totalb * 100;
_.each(result, function (obj) {
if (obj._from && obj._to) {
hitsb++;
if (percentageb >= 95) {
found = true;
toReturn.defaultType = 'graph';
// then display as graph
}
});
var percentageb = hitsb / totalb * 100;
if (percentageb >= 95) {
found = true;
toReturn.defaultType = 'graph';
// then display as graph
}
}
// check if result could be displayed as table
if (!found) {
var maxAttributeCount = 0;
var check = true;
var length;
var attributes = {};
_.each(result, function (obj) {
length = _.keys(obj).length;
if (result.length <= 1) {
check = false;
}
if (length > maxAttributeCount) {
maxAttributeCount = length;
}
if (check) {
_.each(result, function (obj) {
length = _.keys(obj).length;
_.each(obj, function (value, key) {
if (attributes[key]) {
attributes[key] = attributes[key] + 1;
} else {
attributes[key] = 1;
if (length > maxAttributeCount) {
maxAttributeCount = length;
}
_.each(obj, function (value, key) {
if (attributes[key]) {
attributes[key] = attributes[key] + 1;
} else {
attributes[key] = 1;
}
});
});
var rate;
console.log(attributes);
_.each(attributes, function (val, key) {
rate = (val / result.length) * 100;
console.log(rate);
if (check !== false) {
if (rate <= 95) {
check = false;
}
}
});
});
var rate;
var check = true;
_.each(attributes, function (val, key) {
rate = (val / result.length) * 100;
if (check !== false) {
if (rate <= 95) {
check = false;
}
}
});
}
if (check) {
found = true;
@ -1784,6 +1800,42 @@
});
},
renderOutputTable: function (data, counter) {
var tableDescription = {
id: 'outputTableData' + counter,
titles: [],
rows: []
};
var first = true;
var part = [];
// self.tableDescription.rows.push(;
_.each(data.original, function (obj) {
if (first === true) {
tableDescription.titles = Object.keys(obj);
first = false;
}
_.each(obj, function (val) {
if (typeof val === 'object') {
val = JSON.stringify(val);
}
part.push(val);
});
tableDescription.rows.push(part);
part = [];
});
console.log(counter);
$('#outputTable' + counter).append(this.table.render({content: tableDescription}));
console.log(tableDescription.titles);
console.log(tableDescription.rows);
},
renderOutputGraph: function () {
},
getAQL: function (originCallback) {
var self = this;

View File

@ -328,7 +328,6 @@
.ui-resizable-e {
cursor: ew-resize;
}
}
.queryContent {
@ -356,6 +355,16 @@
padding-top: 20px;
width: 100%;
.tableWrapper {
max-width: 100%;
overflow-x: scroll;
.arango-table {
border-left: 1px solid $c-content-border;
border-right: 1px solid $c-content-border;
}
}
.switchAce {
background-color: rgba(0, 0, 0, .6);
border-radius: 3px;

View File

@ -469,6 +469,12 @@ function removeClusterNodes (nodeTypes) {
});
}
function removeClusterNodesFromPlan (nodes) {
return nodes.filter(function (node) {
return ([ 'ScatterNode', 'GatherNode', 'DistributeNode', 'RemoteNode' ].indexOf(node.type) === -1);
});
}
exports.isEqual = isEqual;
exports.getParseResults = getParseResults;
exports.assertParseError = assertParseError;
@ -487,3 +493,4 @@ exports.findReferencedNodes = findReferencedNodes;
exports.getQueryMultiplePlansAndExecutions = getQueryMultiplePlansAndExecutions;
exports.removeAlwaysOnClusterRules = removeAlwaysOnClusterRules;
exports.removeClusterNodes = removeClusterNodes;
exports.removeClusterNodesFromPlan = removeClusterNodesFromPlan;

View File

@ -31,14 +31,14 @@
var jsunity = require("jsunity");
var helper = require("@arangodb/aql-helper");
var isEqual = helper.isEqual;
var db = require("@arangodb").db;
var ruleName = "inline-subqueries";
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function optimizerRuleTestSuite () {
var ruleName = "inline-subqueries";
// various choices to control the optimizer:
var paramNone = { optimizer: { rules: [ "-all" ] } };
var paramEnabled = { optimizer: { rules: [ "-all", "+" + ruleName ] }, inspectSimplePlans: true };
@ -161,8 +161,73 @@ function optimizerRuleTestSuite () {
result = AQL_EXECUTE(query[0]).json;
assertEqual(query[1], result, query);
});
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function optimizerRuleCollectionTestSuite () {
var c = null;
var cn = "UnitTestsOptimizer";
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
db._drop(cn);
c = db._create(cn);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
db._drop(cn);
c = null;
},
testSpecificPlan1 : function () {
var query = "LET x = (FOR doc IN @@cn RETURN doc) FOR doc2 IN x RETURN doc2";
var result = AQL_EXPLAIN(query, { "@cn" : cn });
assertNotEqual(-1, result.plan.rules.indexOf(ruleName), query);
var nodes = helper.removeClusterNodesFromPlan(result.plan.nodes);
assertEqual(3, nodes.length);
assertEqual("ReturnNode", nodes[nodes.length - 1].type);
assertEqual("doc2", nodes[nodes.length - 1].inVariable.name);
assertEqual("EnumerateCollectionNode", nodes[nodes.length - 2].type);
assertEqual(cn, nodes[nodes.length - 2].collection);
},
testSpecificPlan2 : function () {
var query = "LET x = (FOR doc IN @@cn FILTER doc.foo == 'bar' RETURN doc) FOR doc2 IN x RETURN doc2";
var result = AQL_EXPLAIN(query, { "@cn" : cn });
assertNotEqual(-1, result.plan.rules.indexOf(ruleName), query);
var nodes = helper.removeClusterNodesFromPlan(result.plan.nodes);
assertEqual(5, nodes.length);
assertEqual("ReturnNode", nodes[nodes.length - 1].type);
assertEqual("doc2", nodes[nodes.length - 1].inVariable.name);
assertEqual("FilterNode", nodes[nodes.length - 2].type);
assertEqual("CalculationNode", nodes[nodes.length - 3].type);
assertEqual("EnumerateCollectionNode", nodes[nodes.length - 4].type);
assertEqual(cn, nodes[nodes.length - 4].collection);
},
testSpecificPlan3 : function () {
var query = "LET x = (FOR doc IN @@cn RETURN doc) FOR doc2 IN x RETURN x";
var result = AQL_EXPLAIN(query, { "@cn" : cn });
assertEqual(-1, result.plan.rules.indexOf(ruleName), query); // no optimization
}
};
}
@ -171,5 +236,6 @@ function optimizerRuleTestSuite () {
////////////////////////////////////////////////////////////////////////////////
jsunity.run(optimizerRuleTestSuite);
jsunity.run(optimizerRuleCollectionTestSuite);
return jsunity.done();