1
0
Fork 0

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

This commit is contained in:
Jan Steemann 2015-12-17 14:41:24 +01:00
commit 1faaaa0632
4 changed files with 149 additions and 23 deletions

View File

@ -251,6 +251,7 @@ class Builder {
std::shared_ptr<Buffer<uint8_t>> steal() {
std::shared_ptr<Buffer<uint8_t>> res = std::move(_buffer);
_buffer.reset(new Buffer<uint8_t>());
_pos = 0;
return res;
}
@ -298,6 +299,8 @@ class Builder {
return _pos;
}
bool isEmpty() const throw() { return _pos == 0; }
bool isClosed() const throw() { return _stack.empty(); }
bool isOpenArray() const throw() {

View File

@ -479,6 +479,10 @@ AqlItemBlock* TraversalBlock::getSome (size_t, // atLeast,
return res.release();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief skipSome
////////////////////////////////////////////////////////////////////////////////
size_t TraversalBlock::skipSome (size_t atLeast, size_t atMost) {
size_t skipped = 0;

View File

@ -444,6 +444,31 @@ function multiCollectionGraphSuite () {
});
},
testNoBindParameterSingleForFilter: function () {
var query = "FOR s IN " + vn + " SORT s FOR x, e, p IN OUTBOUND s " +
en + " FILTER p.vertices[1]._key == s._key SORT x RETURN x";
var result = db._query(query).toArray();
assertEqual(result.length, 0);
var plans = AQL_EXPLAIN(query, { }, opts).plans;
plans.forEach(function(plan) {
var jsonResult = AQL_EXECUTEJSON(plan, { optimizer: { rules: [ "-all" ] } }).json;
assertEqual(jsonResult.length, 0);
});
},
testNoBindParameterV8Function: function () {
var query = "FOR s IN " + vn + " SORT s FOR x, e, p IN OUTBOUND s " +
en + " FILTER p.vertices[1]._key == NOOPT(V8(RAND())) SORT x RETURN x";
var result = db._query(query).toArray();
assertEqual(result.length, 0);
var plans = AQL_EXPLAIN(query, { }, opts).plans;
plans.forEach(function(plan) {
var jsonResult = AQL_EXECUTEJSON(plan, { optimizer: { rules: [ "-all" ] } }).json;
assertEqual(jsonResult.length, 0);
});
},
testNoBindParameter: function () {
var query = "FOR x, e, p IN OUTBOUND '" + vertex.B + "' " + en + " RETURN {vertex: x, path: p}";
var result = db._query(query).toArray();
@ -744,6 +769,89 @@ function multiCollectionGraphSuite () {
};
}
function multiEdgeCollectionGraphSuite () {
/***********************************************************************
* Graph under test:
*
* B<----+ <- B & C via edge collection A
* |
* D<----A----<C
* |
* +----<E <- D & E via edge colltion B
*
***********************************************************************/
var g;
const gn = "UnitTestGraph";
const en2 = "UnitTestEdgeCollection2";
var ruleName = "merge-traversal-filter";
var paramEnabled = { optimizer: { rules: [ "-all", "+" + ruleName ] } };
var opts = _.clone(paramEnabled);
return {
setUp: function() {
opts.allPlans = true;
opts.verbosePlans = true;
cleanup();
try {
gm._drop(gn);
} catch (e) {
// It is expected that this graph does not exist.
}
vc = db._create(vn, {numberOfShards: 4});
ec = db._createEdgeCollection(en, {numberOfShards: 4});
var ec2 = db._createEdgeCollection(en2, {numberOfShards: 4});
g = gm._create(gn, [gm._relation(en, vn, vn), gm._relation(en2, vn, vn)]);
vertex.A = vc.save({_key: "A"})._id;
vertex.B = vc.save({_key: "B"})._id;
vertex.C = vc.save({_key: "C"})._id;
vertex.D = vc.save({_key: "D"})._id;
vertex.E = vc.save({_key: "E"})._id;
edge.AB = ec.save(vertex.A, vertex.B, {})._id;
edge.CA = ec.save(vertex.C, vertex.A, {})._id;
edge.AD = ec2.save(vertex.A, vertex.D, {})._id;
edge.EA = ec2.save(vertex.E, vertex.A, {})._id;
},
tearDown: function() {
gm._drop(gn);
db._drop(vn);
db._drop(en);
db._drop(en2);
cleanup();
},
testTwoVertexCollectionsInOutbound: function () {
/* this test is intended to trigger the clone functionality. */
var expectResult = ['B', 'C', 'D', 'E'];
var query = "FOR x IN ANY @startId GRAPH @graph SORT x._id RETURN x._key";
var bindVars = {
graph: gn,
startId: vertex.A
};
var result = db._query(query, bindVars).toArray();
assertEqual(result, expectResult, query);
var plans = AQL_EXPLAIN(query, bindVars, opts).plans;
plans.forEach(function(plan) {
var jsonResult = AQL_EXECUTEJSON(plan, { optimizer: { rules: [ "-all" ] } }).json;
assertEqual(jsonResult, result, query);
});
},
};
}
function potentialErrorsSuite () {
var vc, ec;
@ -1557,6 +1665,7 @@ function brokenGraphSuite () {
jsunity.run(namedGraphSuite);
jsunity.run(multiCollectionGraphSuite);
jsunity.run(multiEdgeCollectionGraphSuite);
jsunity.run(potentialErrorsSuite);
jsunity.run(complexInternaSuite);
jsunity.run(complexFilteringSuite);

View File

@ -1,5 +1,5 @@
/*jshint globalstrict:false, strict:false, maxlen: 500 */
/*global assertEqual, assertTrue, assertNotEqual, AQL_EXPLAIN, AQL_EXECUTE */
/*global assertEqual, assertTrue, assertNotEqual, AQL_EXPLAIN, AQL_EXECUTE, AQL_EXECUTEJSON */
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for optimizer rules
@ -31,6 +31,7 @@
var jsunity = require("jsunity");
var helper = require("@arangodb/aql-helper");
var isEqual = helper.isEqual;
var _ = require("underscore");
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
@ -41,7 +42,9 @@ function optimizerRuleTestSuite () {
// various choices to control the optimizer:
var paramEnabled = { optimizer: { rules: [ "-all", "+" + ruleName ] } };
var paramDisabled = { optimizer: { rules: [ "+all", "-" + ruleName ] } };
var graphName = "myGraph";
var graphName = "myUnittestGraph";
var opts = _.clone(paramEnabled);
return {
////////////////////////////////////////////////////////////////////////////////
@ -50,7 +53,10 @@ function optimizerRuleTestSuite () {
setUp : function () {
var graph_module = require("@arangodb/general-graph");
opts.allPlans = true;
opts.verbosePlans = true;
try { graph_module._drop(graphName, true); } catch (x) {}
var graph = graph_module._create(graphName, [
graph_module._relation("edges", "circles", ["circles"])]);
@ -72,8 +78,6 @@ function optimizerRuleTestSuite () {
graph.edges.save("circles/B", "circles/E", {theFalse: false, theTruth: true, "label": 'blub'});
graph.edges.save("circles/C", "circles/F", {theFalse: false, theTruth: true, "label": 'schubi'});
graph.edges.save("circles/C", "circles/G", {theFalse: false, theTruth: true, "label": 'doo'});
},
////////////////////////////////////////////////////////////////////////////////
@ -92,11 +96,11 @@ function optimizerRuleTestSuite () {
testRuleNoEffect : function () {
var queries = [
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' LET localScopeVar = NOOPT(true) FILTER p.edges[0].theTruth == localScopeVar return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[-1].theTruth == true return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[*].theTruth == true or p.edges[1].label == 'bar' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[RAND()].theFalse == false return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[p.edges.length - 1].theFalse == false return {v:v,e:e,p:p}"
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' LET localScopeVar = NOOPT(true) FILTER p.edges[0].theTruth == localScopeVar return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[-1].theTruth == true return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[*].theTruth == true or p.edges[1].label == 'bar' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[RAND()].theFalse == false return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[p.edges.length - 1].theFalse == false return {v:v,e:e,p:p}"
];
queries.forEach(function(query) {
@ -111,11 +115,11 @@ function optimizerRuleTestSuite () {
testRuleHasEffect : function () {
var queries = [
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[0].theTruth == true return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[1].theTruth == true return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[2].theTruth == true return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[2].theTruth == true AND p.edges[1].label == 'bar' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[0].theTruth == true FILTER p.edges[1].label == 'bar' return {v:v,e:e,p:p}"
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[0].theTruth == true return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[1].theTruth == true return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[2].theTruth == true return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[2].theTruth == true AND p.edges[1].label == 'bar' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[0].theTruth == true FILTER p.edges[1].label == 'bar' return {v:v,e:e,p:p}"
];
queries.forEach(function(query) {
@ -130,12 +134,12 @@ function optimizerRuleTestSuite () {
testResults : function () {
var queries = [
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[0].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[1].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[0].theTruth == true FILTER p.edges[0].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[0].theTruth == true FILTER p.edges[1].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[0].theTruth == true FILTER p.edges[0].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[1].theTruth == true FILTER p.edges[1].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[0].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[1].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[0].theTruth == true FILTER p.edges[0].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[0].theTruth == true FILTER p.edges[1].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[0].theTruth == true FILTER p.edges[0].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[1].theTruth == true FILTER p.edges[1].label == 'foo' return {v:v,e:e,p:p}",
];
queries.forEach(function(query) {
@ -149,6 +153,12 @@ function optimizerRuleTestSuite () {
assertEqual(-1, planDisabled.plan.rules.indexOf(ruleName), query);
assertNotEqual(-1, planEnabled.plan.rules.indexOf(ruleName), query);
var plans = AQL_EXPLAIN(query, {}, opts).plans;
plans.forEach(function(plan) {
var jsonResult = AQL_EXECUTEJSON(plan, { optimizer: { rules: [ "-all" ] } }).json;
assertEqual(jsonResult, resultDisabled, query);
});
});
},
@ -160,10 +170,10 @@ function optimizerRuleTestSuite () {
testNoResults : function () {
var queries = [
// sure shot: 5 < 7
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[7].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[7].label == 'foo' return {v:v,e:e,p:p}",
// indexed access starts with 0 - this is also forbidden since it will look for the 6th!
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[5].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 5..1 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[1].label == 'foo' return {v:v,e:e,p:p}"
"FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[5].label == 'foo' return {v:v,e:e,p:p}",
"FOR v, e, p IN 5..1 OUTBOUND 'circles/A' GRAPH '" + graphName + "' FILTER p.edges[1].label == 'foo' return {v:v,e:e,p:p}"
// TODO: right now we're not clever enough to find this:
// "FOR v, e, p IN 1..5 OUTBOUND 'circles/A' GRAPH 'myGraph' FILTER p.edges[1].label == 'foo' AND p.edges[1].label == 'bar' return {v:v,e:e,p:p}"
];