mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'aql2' of ssh://github.com/triAGENS/ArangoDB into aql2
This commit is contained in:
commit
d147be8de3
|
@ -119,6 +119,7 @@ AqlValue Expression::execute (AQL_TRANSACTION_V8* trx,
|
|||
std::vector<Variable*> const& vars,
|
||||
std::vector<RegisterId> const& regs) {
|
||||
|
||||
AqlValue ret;
|
||||
TRI_ASSERT(_type != UNPROCESSED);
|
||||
|
||||
// and execute
|
||||
|
@ -130,7 +131,19 @@ AqlValue Expression::execute (AQL_TRANSACTION_V8* trx,
|
|||
|
||||
case V8: {
|
||||
TRI_ASSERT(_func != nullptr);
|
||||
return _func->execute(trx, docColls, argv, startPos, vars, regs);
|
||||
try {
|
||||
ret = _func->execute(trx, docColls, argv, startPos, vars, regs);
|
||||
}
|
||||
catch (triagens::arango::Exception ex) {
|
||||
ex.addToMessage("\nwhile evaluating Expression \n");
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
ex.addToMessage(toJson(TRI_UNKNOWN_MEM_ZONE, true).toString());
|
||||
ex.addToMessage("\n");
|
||||
#endif
|
||||
throw ex;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
case SIMPLE: {
|
||||
|
|
|
@ -79,7 +79,8 @@ Query::Query (TRI_vocbase_t* vocbase,
|
|||
|
||||
Query::Query (TRI_vocbase_t* vocbase,
|
||||
triagens::basics::Json queryStruct,
|
||||
QueryType Type)
|
||||
QueryType Type,
|
||||
TRI_json_t* options)
|
||||
: _vocbase(vocbase),
|
||||
_executor(nullptr),
|
||||
_queryString(nullptr),
|
||||
|
@ -87,7 +88,7 @@ Query::Query (TRI_vocbase_t* vocbase,
|
|||
_queryJson(queryStruct),
|
||||
_type(Type),
|
||||
_bindParameters(nullptr),
|
||||
_options(nullptr),
|
||||
_options(options),
|
||||
_collections(vocbase),
|
||||
_strings(),
|
||||
_ast(nullptr) {
|
||||
|
@ -276,7 +277,7 @@ QueryResult Query::execute () {
|
|||
plan = opt.stealBest(); // Now we own the best one again
|
||||
TRI_ASSERT(plan != nullptr);
|
||||
/* // for debugging of serialisation/deserialisation . . .
|
||||
auto JsonPlan = plan->toJson(TRI_UNKNOWN_MEM_ZONE, true);
|
||||
auto JsonPlan = plan->toJson(parser.ast(),TRI_UNKNOWN_MEM_ZONE, true);
|
||||
auto JsonString = JsonPlan.toString();
|
||||
std::cout << "original plan: \n" << JsonString << "\n";
|
||||
|
||||
|
|
|
@ -90,7 +90,8 @@ namespace triagens {
|
|||
|
||||
Query (struct TRI_vocbase_s*,
|
||||
triagens::basics::Json queryStruct,
|
||||
QueryType Type);
|
||||
QueryType Type,
|
||||
struct TRI_json_s*);
|
||||
|
||||
~Query ();
|
||||
|
||||
|
|
|
@ -98,6 +98,10 @@ namespace triagens {
|
|||
int code () const throw () {
|
||||
return _code;
|
||||
}
|
||||
|
||||
void addToMessage(std::string More) {
|
||||
_errorMessage += More;
|
||||
}
|
||||
|
||||
static std::string FillExceptionString (int, ...);
|
||||
|
||||
|
|
|
@ -959,6 +959,7 @@ static v8::Handle<v8::Value> JS_ExecuteAqlJson (v8::Arguments const& argv) {
|
|||
TRI_V8_TYPE_ERROR(scope, "expecting object for <queryjson>");
|
||||
}
|
||||
TRI_json_t* queryjson = TRI_ObjectToJson(argv[0]);
|
||||
TRI_json_t* options = nullptr;
|
||||
|
||||
if (argv.Length() > 1) {
|
||||
// we have options! yikes!
|
||||
|
@ -992,9 +993,10 @@ static v8::Handle<v8::Value> JS_ExecuteAqlJson (v8::Arguments const& argv) {
|
|||
if (argValue->Has(optionName)) {
|
||||
extra = TRI_ObjectToJson(argValue->Get(optionName));
|
||||
}
|
||||
options = TRI_ObjectToJson(argv[1]);
|
||||
}
|
||||
|
||||
triagens::aql::Query query(vocbase, Json(TRI_UNKNOWN_MEM_ZONE, queryjson), triagens::aql::AQL_QUERY_READ);
|
||||
triagens::aql::Query query(vocbase, Json(TRI_UNKNOWN_MEM_ZONE, queryjson), triagens::aql::AQL_QUERY_READ, options);
|
||||
|
||||
auto queryResult = query.execute();
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
var internal = require("internal");
|
||||
var arangodb = require("org/arangodb");
|
||||
var ShapedJson = internal.ShapedJson;
|
||||
var printYaml = function (plan) { require("internal").print(require("js-yaml").safeDump(plan));};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- AQL test helper functions
|
||||
|
@ -475,7 +476,7 @@ function findReferencedNodes(plan, testNode) {
|
|||
return matches;
|
||||
}
|
||||
|
||||
function getQueryMultiplePlansAndExecutions (query, bindVars) {
|
||||
function getQueryMultiplePlansAndExecutions (query, bindVars, debug) {
|
||||
var plan;
|
||||
var i;
|
||||
var plans = [];
|
||||
|
@ -484,19 +485,43 @@ function getQueryMultiplePlansAndExecutions (query, bindVars) {
|
|||
var paramNone = { optimizer: { rules: [ "-all" ]}, verbosePlans: true};
|
||||
var paramAllPlans = { allPlans : true, verbosePlans: true};
|
||||
|
||||
if (debug === undefined)
|
||||
debug = false;
|
||||
|
||||
// first fetch the unmodified version
|
||||
if (debug) {
|
||||
require("internal").print("Analysing Query unoptimized: " + query);
|
||||
}
|
||||
plans [0] = AQL_EXPLAIN(query, bindVars, paramNone);
|
||||
// then all of the ones permuted by by the optimizer.
|
||||
if (debug) {
|
||||
require("internal").print("Unoptimized Plan (0):");
|
||||
printYaml(plans [0]);
|
||||
|
||||
}
|
||||
allPlans = AQL_EXPLAIN(query, bindVars, paramAllPlans);
|
||||
|
||||
for (i=0; i < allPlans.plans.length; i++) {
|
||||
if (debug) {
|
||||
require("internal").print("Optimized Plan ["+(i+1)+"]:");
|
||||
printYaml(allPlans.plans [i]);
|
||||
}
|
||||
plans[i+1] = {'plan':allPlans.plans[i]};
|
||||
}
|
||||
// Now execute each of these variations.
|
||||
for (i=0; i < plans.length; i++) {
|
||||
results += AQL_EXECUTEJSON(plans[i].plan, paramNone);
|
||||
if (debug) {
|
||||
require("internal").print("Executing Plan No: " + i + "\n");
|
||||
}
|
||||
results[i] = AQL_EXECUTEJSON(plans[i].plan, paramNone);
|
||||
if (debug) {
|
||||
require("internal").print("\nDONE\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
require("internal").print("done\n");
|
||||
}
|
||||
return {'plans': plans, 'results': results};
|
||||
}
|
||||
|
||||
|
|
|
@ -26,12 +26,9 @@
|
|||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
var PY = function (plan) { require("internal").print(require("js-yaml").safeDump(plan));};
|
||||
var internal = require("internal");
|
||||
var jsunity = require("jsunity");
|
||||
var helper = require("org/arangodb/aql-helper");
|
||||
// var getQueryResults = helper.getQueryResults2;
|
||||
// TODO! var assertQueryError = helper.assertQueryError2;
|
||||
var isEqual = helper.isEqual;
|
||||
var findExecutionNodes = helper.findExecutionNodes;
|
||||
var findReferencedNodes = helper.findReferencedNodes;
|
||||
|
@ -192,27 +189,37 @@ function optimizerRuleTestSuite() {
|
|||
/// @brief test that rule has no effect
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testRuleNoEffect : function () {
|
||||
|
||||
var queries = [
|
||||
|
||||
"FOR v IN " + colName + " SORT v.c RETURN [v.a, v.b]",
|
||||
["FOR v IN " + colName + " SORT v.c RETURN [v.a, v.b]",true],
|
||||
// todo: we use an index anyways right now.
|
||||
// currently only ASC supported.
|
||||
// "FOR v IN " + colName + " SORT v.a DESC RETURN [v.a, v.b]",
|
||||
"FOR v IN " + colName + " SORT v.b, v.a RETURN [v.a, v.b]",
|
||||
"FOR v IN " + colName + " SORT v.c RETURN [v.a, v.b]",
|
||||
"FOR v IN " + colName + " SORT v.a + 1 RETURN [v.a, v.b]",
|
||||
"FOR v IN " + colName + " SORT CONCAT(TO_STRING(v.a), \"lol\") RETURN [v.a, v.b]",
|
||||
// "FOR v IN " + colName + " SORT v.a DESC RETURN [v.a, v.b]",true],
|
||||
["FOR v IN " + colName + " SORT v.b, v.a RETURN [v.a, v.b]",true],
|
||||
["FOR v IN " + colName + " SORT v.c RETURN [v.a, v.b]",true],
|
||||
["FOR v IN " + colName + " SORT v.a + 1 RETURN [v.a, v.b]",false],// this will throw...
|
||||
["FOR v IN " + colName + " SORT CONCAT(TO_STRING(v.a), \"lol\") RETURN [v.a, v.b]",true],
|
||||
// TODO: limit blocks sort atm.
|
||||
"FOR v IN " + colName + " FILTER v.a > 2 LIMIT 3 SORT v.a RETURN [v.a, v.b] ",
|
||||
"FOR v IN " + colName + " FOR w IN " + colNameOther + " SORT v.a RETURN [v.a, v.b]"
|
||||
["FOR v IN " + colName + " FILTER v.a > 2 LIMIT 3 SORT v.a RETURN [v.a, v.b] ",true],
|
||||
["FOR v IN " + colName + " FOR w IN " + colNameOther + " SORT v.a RETURN [v.a, v.b]",true]
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
|
||||
var result = AQL_EXPLAIN(query, { }, paramIndexFromSort);
|
||||
var result = AQL_EXPLAIN(query[0], { }, paramIndexFromSort);
|
||||
assertEqual([], result.plan.rules, query);
|
||||
if (query[1]) {
|
||||
allresults = getQueryMultiplePlansAndExecutions(query[0], {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
@ -227,15 +234,17 @@ function optimizerRuleTestSuite() {
|
|||
// currently only ASC supported, but we use the index range anyways.
|
||||
// todo: this may change.
|
||||
"FOR v IN " + colName + " SORT v.d DESC RETURN [v.d]",
|
||||
|
||||
"FOR v IN " + colName + " SORT v.d FILTER v.a > 2 LIMIT 3 RETURN [v.d] ",
|
||||
"FOR v IN " + colName + " FOR w IN 1..10 SORT v.d RETURN [v.d]",
|
||||
|
||||
|
||||
"FOR v IN " + colName + " LET x = (FOR w IN " + colNameOther + " RETURN w.f ) SORT v.a RETURN [v.a]"
|
||||
];
|
||||
var QResults = [];
|
||||
var i = 0;
|
||||
queries.forEach(function(query) {
|
||||
|
||||
var j;
|
||||
|
||||
var result = AQL_EXPLAIN(query, { }, paramIndexFromSort);
|
||||
assertEqual([ ruleName ], result.plan.rules, query);
|
||||
QResults[0] = AQL_EXECUTE(query, { }, paramNone).json;
|
||||
|
@ -244,6 +253,14 @@ function optimizerRuleTestSuite() {
|
|||
assertTrue(isEqual(QResults[0], QResults[1]), "Result " + i + " is Equal?");
|
||||
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
AQL_EXECUTEJSON(allresults.plans[0].plan, paramNone);
|
||||
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
i++;
|
||||
});
|
||||
|
||||
|
@ -263,7 +280,7 @@ function optimizerRuleTestSuite() {
|
|||
var QResults = [];
|
||||
var i = 0;
|
||||
queries.forEach(function(query) {
|
||||
|
||||
var j;
|
||||
var result = AQL_EXPLAIN(query, { }, paramIndexFromSort);
|
||||
assertEqual([ ruleName ], result.plan.rules);
|
||||
hasIndexRangeNode_WithRanges(result, false);
|
||||
|
@ -271,6 +288,14 @@ function optimizerRuleTestSuite() {
|
|||
QResults[0] = AQL_EXECUTE(query, { }, paramNone).json;
|
||||
QResults[1] = AQL_EXECUTE(query, { }, paramIndexFromSort ).json;
|
||||
assertTrue(isEqual(QResults[0], QResults[1]), "Result " + i + " is Equal?");
|
||||
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
i++;
|
||||
});
|
||||
|
||||
|
@ -291,7 +316,7 @@ function optimizerRuleTestSuite() {
|
|||
|
||||
var XPresult;
|
||||
var QResults=[];
|
||||
var i;
|
||||
var i, j;
|
||||
|
||||
// we have to re-sort here, because of the index has one more sort criteria.
|
||||
QResults[0] = AQL_EXECUTE(query, { }, paramNone).json.sort(sortArray);
|
||||
|
@ -323,7 +348,13 @@ function optimizerRuleTestSuite() {
|
|||
for (i = 1; i < 3; i++) {
|
||||
assertTrue(isEqual(QResults[0], QResults[i]), "Result " + i + " is Equal?");
|
||||
}
|
||||
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
@ -387,6 +418,13 @@ function optimizerRuleTestSuite() {
|
|||
for (i = 1; i < 4; i++) {
|
||||
assertTrue(isEqual(QResults[0], QResults[i]), "Result " + i + " is Equal?");
|
||||
}
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -399,7 +437,7 @@ function optimizerRuleTestSuite() {
|
|||
|
||||
var XPresult;
|
||||
var QResults=[];
|
||||
var i;
|
||||
var i, j;
|
||||
|
||||
// the index we will compare to sorts by a & b, so we need to
|
||||
// re-sort the result here to accomplish similarity.
|
||||
|
@ -456,7 +494,13 @@ function optimizerRuleTestSuite() {
|
|||
for (i = 1; i < 5; i++) {
|
||||
assertTrue(isEqual(QResults[0], QResults[i]), "Result " + i + " is Equal?");
|
||||
}
|
||||
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -468,7 +512,7 @@ function optimizerRuleTestSuite() {
|
|||
var query = "FOR v IN " + colName + " FILTER v.a == 1 SORT v.a, v.b RETURN [v.a, v.b, v.c]";
|
||||
var XPresult;
|
||||
var QResults=[];
|
||||
var i;
|
||||
var i, j;
|
||||
|
||||
// the index we will compare to sorts by a & b, so we need to
|
||||
// re-sort the result here to accomplish similarity.
|
||||
|
@ -528,6 +572,13 @@ function optimizerRuleTestSuite() {
|
|||
for (i = 1; i < 5; i++) {
|
||||
assertTrue(isEqual(QResults[0], QResults[i]), "Result " + i + " is Equal?");
|
||||
}
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
@ -545,7 +596,7 @@ function optimizerRuleTestSuite() {
|
|||
|
||||
var XPresult;
|
||||
var QResults=[];
|
||||
var i;
|
||||
var i, j;
|
||||
|
||||
// the index we will compare to sorts by a & b, so we need to
|
||||
// re-sort the result here to accomplish similarity.
|
||||
|
@ -569,7 +620,13 @@ function optimizerRuleTestSuite() {
|
|||
for (i = 1; i < 2; i++) {
|
||||
assertTrue(isEqual(QResults[0].sort(sortArray), QResults[i]), "Result " + i + " is Equal?");
|
||||
}
|
||||
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
@ -581,6 +638,7 @@ function optimizerRuleTestSuite() {
|
|||
|
||||
var XPresult;
|
||||
var QResults=[];
|
||||
var j;
|
||||
|
||||
// the index we will compare to sorts by a & b, so we need to
|
||||
// re-sort the result here to accomplish similarity.
|
||||
|
@ -603,6 +661,14 @@ function optimizerRuleTestSuite() {
|
|||
assertEqual(first.highConst.bound, 5, "proper value was set");
|
||||
|
||||
assertTrue(isEqual(QResults[0], QResults[1]), "Results are Equal?");
|
||||
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -612,6 +678,7 @@ function optimizerRuleTestSuite() {
|
|||
var query = "FOR v IN " + colName + " FILTER v.a > 5 RETURN [v.a, v.b]";
|
||||
var XPresult;
|
||||
var QResults=[];
|
||||
var j;
|
||||
|
||||
// the index we will compare to sorts by a & b, so we need to
|
||||
// re-sort the result here to accomplish similarity.
|
||||
|
@ -636,6 +703,13 @@ function optimizerRuleTestSuite() {
|
|||
|
||||
assertTrue(isEqual(QResults[0], QResults[1]), "Results are Equal?");
|
||||
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -646,6 +720,7 @@ function optimizerRuleTestSuite() {
|
|||
var query = "FOR v IN " + colName + " FILTER v.a > 4 && v.a < 10 RETURN [v.a, v.b]";
|
||||
var XPresult;
|
||||
var QResults=[];
|
||||
var j;
|
||||
|
||||
// the index we will compare to sorts by a & b, so we need to
|
||||
// re-sort the result here to accomplish similarity.
|
||||
|
@ -669,6 +744,14 @@ function optimizerRuleTestSuite() {
|
|||
assertEqual(first.highConst.bound, 10, "proper value was set");
|
||||
|
||||
assertTrue(isEqual(QResults[0], QResults[1]), "Results are Equal?");
|
||||
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -680,7 +763,7 @@ function optimizerRuleTestSuite() {
|
|||
|
||||
testRangeBandpassInvalid: function () {
|
||||
var query = "FOR v IN " + colName + " FILTER v.a > 7 && v.a < 4 RETURN [v.a, v.b]";
|
||||
|
||||
var j;
|
||||
var XPresult;
|
||||
var QResults=[];
|
||||
|
||||
|
@ -701,7 +784,13 @@ function optimizerRuleTestSuite() {
|
|||
hasNoIndexRangeNode(XPresult);
|
||||
|
||||
assertTrue(isEqual(QResults[0], QResults[1]), "Results are Equal?");
|
||||
|
||||
allresults = getQueryMultiplePlansAndExecutions(query, {});
|
||||
for (j = 1; j <= allresults.length; j++) {
|
||||
AssertTrue(isEqual(allresults.results[0],
|
||||
allresults.results[j]),
|
||||
"whether the execution of this plan gave the right results: " +
|
||||
allresults.plans[j]);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
@ -780,6 +869,7 @@ function optimizerRuleTestSuite() {
|
|||
// assertTrue(isEqual(QResults[0], QResults[1]), "Results are Equal?");
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue