mirror of https://gitee.com/bigwinds/arangodb
removed canThrow tag for various built-in functions
This commit is contained in:
parent
19dc758c1a
commit
bf30927913
|
@ -1073,12 +1073,18 @@ bool AstNode::isComparisonOperator () const {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool AstNode::canThrow () const {
|
||||
if (hasFlag(FLAG_THROWS)) {
|
||||
// fast track exit
|
||||
return true;
|
||||
}
|
||||
|
||||
// check sub-nodes first
|
||||
size_t const n = numMembers();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
auto member = getMember(i);
|
||||
if (member->canThrow()) {
|
||||
// if any sub-node may throw, the whole branch may throw
|
||||
setFlag(FLAG_THROWS);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1093,13 +1099,16 @@ bool AstNode::canThrow () const {
|
|||
// potentially throwing. This is not correct on the one hand, but on
|
||||
// the other hand we must not optimize or move non-deterministic functions
|
||||
// during optimization
|
||||
// TODO: move the check for isDeterministic into a function of its
|
||||
// own and check it from the optimizer rules
|
||||
return func->canThrow || ! func->isDeterministic;
|
||||
if (func->canThrow) {
|
||||
setFlag(FLAG_THROWS);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == NODE_TYPE_FCALL_USER) {
|
||||
// user functions can always throw
|
||||
setFlag(FLAG_THROWS);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1144,12 +1153,18 @@ bool AstNode::canRunOnDBServer () const {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool AstNode::isDeterministic () const {
|
||||
if (hasFlag(FLAG_NONDETERMINISTIC)) {
|
||||
// fast track exit
|
||||
return false;
|
||||
}
|
||||
|
||||
// check sub-nodes first
|
||||
size_t const n = numMembers();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
auto member = getMember(i);
|
||||
if (! member->isDeterministic()) {
|
||||
// if any sub-node is non-deterministic, we are neither
|
||||
setFlag(FLAG_NONDETERMINISTIC);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1157,11 +1172,16 @@ bool AstNode::isDeterministic () const {
|
|||
if (type == NODE_TYPE_FCALL) {
|
||||
// built-in functions may or may not be deterministic
|
||||
auto func = static_cast<Function*>(getData());
|
||||
return func->isDeterministic;
|
||||
if (! func->isDeterministic) {
|
||||
setFlag(FLAG_NONDETERMINISTIC);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == NODE_TYPE_FCALL_USER) {
|
||||
// user functions are always non-deterministic
|
||||
setFlag(FLAG_NONDETERMINISTIC);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,11 +59,12 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum AstNodeFlagType : uint8_t {
|
||||
FLAG_SORTED = 1, // node is a list and its members are sorted asc.
|
||||
FLAG_CONSTANT = 2, // node value is constant (i.e. not dynamic)
|
||||
FLAG_DYNAMIC = 4, // node value is dynamic (i.e. not constant)
|
||||
FLAG_SIMPLE = 8 // node value is simple (i.e. for use in a simple expression)
|
||||
|
||||
FLAG_SORTED = 1, // node is a list and its members are sorted asc.
|
||||
FLAG_CONSTANT = 2, // node value is constant (i.e. not dynamic)
|
||||
FLAG_DYNAMIC = 4, // node value is dynamic (i.e. not constant)
|
||||
FLAG_SIMPLE = 8, // node value is simple (i.e. for use in a simple expression)
|
||||
FLAG_THROWS = 16, // node can throws an exception
|
||||
FLAG_NONDETERMINISTIC = 32 // node produces non-deterministic result (e.g. function call nodes)
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1824,6 +1824,10 @@ SortInformation SortNode::getSortInformation (ExecutionPlan* plan,
|
|||
// variable introduced by a calculation
|
||||
auto expression = static_cast<CalculationNode*>(setter)->expression();
|
||||
|
||||
if (! expression->isDeterministic()) {
|
||||
result.isDeterministic = false;
|
||||
}
|
||||
|
||||
if (! expression->isAttributeAccess() &&
|
||||
! expression->isReference()) {
|
||||
result.isComplex = true;
|
||||
|
|
|
@ -1718,9 +1718,10 @@ namespace triagens {
|
|||
};
|
||||
|
||||
std::vector<std::tuple<ExecutionNode const*, std::string, bool>> criteria;
|
||||
bool isValid = true;
|
||||
bool isComplex = false;
|
||||
bool canThrow = false;
|
||||
bool isValid = true;
|
||||
bool isDeterministic = true;
|
||||
bool isComplex = false;
|
||||
bool canThrow = false;
|
||||
|
||||
Match isCoveredBy (SortInformation const& other) {
|
||||
if (! isValid || ! other.isValid) {
|
||||
|
|
|
@ -104,63 +104,63 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
|
|||
{ "TO_LIST", Function("TO_LIST", "AQL_TO_LIST", ".", true, false, true) },
|
||||
|
||||
// string functions
|
||||
{ "CONCAT", Function("CONCAT", "AQL_CONCAT", "sz,sz|+", true, true, true) },
|
||||
{ "CONCAT_SEPARATOR", Function("CONCAT_SEPARATOR", "AQL_CONCAT_SEPARATOR", "s,sz,sz|+", true, true, true) },
|
||||
{ "CHAR_LENGTH", Function("CHAR_LENGTH", "AQL_CHAR_LENGTH", "s", true, true, true) },
|
||||
{ "LOWER", Function("LOWER", "AQL_LOWER", "s", true, true, true) },
|
||||
{ "UPPER", Function("UPPER", "AQL_UPPER", "s", true, true, true) },
|
||||
{ "SUBSTRING", Function("SUBSTRING", "AQL_SUBSTRING", "s,n|n", true, true, true) },
|
||||
{ "CONTAINS", Function("CONTAINS", "AQL_CONTAINS", "s,s|b", true, true, true) },
|
||||
{ "LIKE", Function("LIKE", "AQL_LIKE", "s,r|b", true, true, true) },
|
||||
{ "LEFT", Function("LEFT", "AQL_LEFT", "s,n", true, true, true) },
|
||||
{ "RIGHT", Function("RIGHT", "AQL_RIGHT", "s,n", true, true, true) },
|
||||
{ "TRIM", Function("TRIM", "AQL_TRIM", "s|n", true, true, true) },
|
||||
{ "FIND_FIRST", Function("FIND_FIRST", "AQL_FIND_FIRST", "s,s|zn,zn", true, true, true) },
|
||||
{ "FIND_LAST", Function("FIND_LAST", "AQL_FIND_LAST", "s,s|zn,zn", true, true, true) },
|
||||
{ "CONCAT", Function("CONCAT", "AQL_CONCAT", "sz,sz|+", true, false, true) },
|
||||
{ "CONCAT_SEPARATOR", Function("CONCAT_SEPARATOR", "AQL_CONCAT_SEPARATOR", "s,sz,sz|+", true, false, true) },
|
||||
{ "CHAR_LENGTH", Function("CHAR_LENGTH", "AQL_CHAR_LENGTH", "s", true, false, true) },
|
||||
{ "LOWER", Function("LOWER", "AQL_LOWER", "s", true, false, true) },
|
||||
{ "UPPER", Function("UPPER", "AQL_UPPER", "s", true, false, true) },
|
||||
{ "SUBSTRING", Function("SUBSTRING", "AQL_SUBSTRING", "s,n|n", true, false, true) },
|
||||
{ "CONTAINS", Function("CONTAINS", "AQL_CONTAINS", "s,s|b", true, false, true) },
|
||||
{ "LIKE", Function("LIKE", "AQL_LIKE", "s,r|b", true, false, true) },
|
||||
{ "LEFT", Function("LEFT", "AQL_LEFT", "s,n", true, false, true) },
|
||||
{ "RIGHT", Function("RIGHT", "AQL_RIGHT", "s,n", true, false, true) },
|
||||
{ "TRIM", Function("TRIM", "AQL_TRIM", "s|n", true, false, true) },
|
||||
{ "FIND_FIRST", Function("FIND_FIRST", "AQL_FIND_FIRST", "s,s|zn,zn", true, false, true) },
|
||||
{ "FIND_LAST", Function("FIND_LAST", "AQL_FIND_LAST", "s,s|zn,zn", true, false, true) },
|
||||
|
||||
// numeric functions
|
||||
{ "FLOOR", Function("FLOOR", "AQL_FLOOR", "n", true, true, true) },
|
||||
{ "CEIL", Function("CEIL", "AQL_CEIL", "n", true, true, true) },
|
||||
{ "ROUND", Function("ROUND", "AQL_ROUND", "n", true, true, true) },
|
||||
{ "ABS", Function("ABS", "AQL_ABS", "n", true, true, true) },
|
||||
{ "FLOOR", Function("FLOOR", "AQL_FLOOR", "n", true, false, true) },
|
||||
{ "CEIL", Function("CEIL", "AQL_CEIL", "n", true, false, true) },
|
||||
{ "ROUND", Function("ROUND", "AQL_ROUND", "n", true, false, true) },
|
||||
{ "ABS", Function("ABS", "AQL_ABS", "n", true, false, true) },
|
||||
{ "RAND", Function("RAND", "AQL_RAND", "", false, false, true) },
|
||||
{ "SQRT", Function("SQRT", "AQL_SQRT", "n", true, true, true) },
|
||||
{ "SQRT", Function("SQRT", "AQL_SQRT", "n", true, false, true) },
|
||||
|
||||
// list functions
|
||||
{ "RANGE", Function("RANGE", "AQL_RANGE", "n,n|n", true, true, true) },
|
||||
{ "UNION", Function("UNION", "AQL_UNION", "l,l|+",true, true, true) },
|
||||
{ "UNION_DISTINCT", Function("UNION_DISTINCT", "AQL_UNION_DISTINCT", "l,l|+", true, true, true) },
|
||||
{ "MINUS", Function("MINUS", "AQL_MINUS", "l,l|+", true, true, true) },
|
||||
{ "INTERSECTION", Function("INTERSECTION", "AQL_INTERSECTION", "l,l|+", true, true, true) },
|
||||
{ "FLATTEN", Function("FLATTEN", "AQL_FLATTEN", "l|n", true, true, true) },
|
||||
{ "LENGTH", Function("LENGTH", "AQL_LENGTH", "las", true, true, true) },
|
||||
{ "MIN", Function("MIN", "AQL_MIN", "l", true, true, true) },
|
||||
{ "MAX", Function("MAX", "AQL_MAX", "l", true, true, true) },
|
||||
{ "SUM", Function("SUM", "AQL_SUM", "l", true, true, true) },
|
||||
{ "MEDIAN", Function("MEDIAN", "AQL_MEDIAN", "l", true, true, true) },
|
||||
{ "AVERAGE", Function("AVERAGE", "AQL_AVERAGE", "l", true, true, true) },
|
||||
{ "VARIANCE_SAMPLE", Function("VARIANCE_SAMPLE", "AQL_VARIANCE_SAMPLE", "l", true, true, true) },
|
||||
{ "VARIANCE_POPULATION", Function("VARIANCE_POPULATION", "AQL_VARIANCE_POPULATION", "l", true, true, true) },
|
||||
{ "STDDEV_SAMPLE", Function("STDDEV_SAMPLE", "AQL_STDDEV_SAMPLE", "l", true, true, true) },
|
||||
{ "STDDEV_POPULATION", Function("STDDEV_POPULATION", "AQL_STDDEV_POPULATION", "l", true, true, true) },
|
||||
{ "UNIQUE", Function("UNIQUE", "AQL_UNIQUE", "l", true, true, true) },
|
||||
{ "SLICE", Function("SLICE", "AQL_SLICE", "l,n|n", true, true, true) },
|
||||
{ "REVERSE", Function("REVERSE", "AQL_REVERSE", "ls", true, true, true) }, // note: REVERSE() can be applied on strings, too
|
||||
{ "FIRST", Function("FIRST", "AQL_FIRST", "l", true, true, true) },
|
||||
{ "LAST", Function("LAST", "AQL_LAST", "l", true, true, true) },
|
||||
{ "NTH", Function("NTH", "AQL_NTH", "l,n", true, true, true) },
|
||||
{ "POSITION", Function("POSITION", "AQL_POSITION", "l,.|b", true, true, true) },
|
||||
{ "RANGE", Function("RANGE", "AQL_RANGE", "n,n|n", true, false, true) },
|
||||
{ "UNION", Function("UNION", "AQL_UNION", "l,l|+",true, false, true) },
|
||||
{ "UNION_DISTINCT", Function("UNION_DISTINCT", "AQL_UNION_DISTINCT", "l,l|+", true, false, true) },
|
||||
{ "MINUS", Function("MINUS", "AQL_MINUS", "l,l|+", true, false, true) },
|
||||
{ "INTERSECTION", Function("INTERSECTION", "AQL_INTERSECTION", "l,l|+", true, false, true) },
|
||||
{ "FLATTEN", Function("FLATTEN", "AQL_FLATTEN", "l|n", true, false, true) },
|
||||
{ "LENGTH", Function("LENGTH", "AQL_LENGTH", "las", true, false, true) },
|
||||
{ "MIN", Function("MIN", "AQL_MIN", "l", true, false, true) },
|
||||
{ "MAX", Function("MAX", "AQL_MAX", "l", true, false, true) },
|
||||
{ "SUM", Function("SUM", "AQL_SUM", "l", true, false, true) },
|
||||
{ "MEDIAN", Function("MEDIAN", "AQL_MEDIAN", "l", true, false, true) },
|
||||
{ "AVERAGE", Function("AVERAGE", "AQL_AVERAGE", "l", true, false, true) },
|
||||
{ "VARIANCE_SAMPLE", Function("VARIANCE_SAMPLE", "AQL_VARIANCE_SAMPLE", "l", true, false, true) },
|
||||
{ "VARIANCE_POPULATION", Function("VARIANCE_POPULATION", "AQL_VARIANCE_POPULATION", "l", true, false, true) },
|
||||
{ "STDDEV_SAMPLE", Function("STDDEV_SAMPLE", "AQL_STDDEV_SAMPLE", "l", true, false, true) },
|
||||
{ "STDDEV_POPULATION", Function("STDDEV_POPULATION", "AQL_STDDEV_POPULATION", "l", true, false, true) },
|
||||
{ "UNIQUE", Function("UNIQUE", "AQL_UNIQUE", "l", true, false, true) },
|
||||
{ "SLICE", Function("SLICE", "AQL_SLICE", "l,n|n", true, false, true) },
|
||||
{ "REVERSE", Function("REVERSE", "AQL_REVERSE", "ls", true, false, true) }, // note: REVERSE() can be applied on strings, too
|
||||
{ "FIRST", Function("FIRST", "AQL_FIRST", "l", true, false, true) },
|
||||
{ "LAST", Function("LAST", "AQL_LAST", "l", true, false, true) },
|
||||
{ "NTH", Function("NTH", "AQL_NTH", "l,n", true, false, true) },
|
||||
{ "POSITION", Function("POSITION", "AQL_POSITION", "l,.|b", true, false, true) },
|
||||
|
||||
// document functions
|
||||
{ "HAS", Function("HAS", "AQL_HAS", "az,s", true, true, true) },
|
||||
{ "ATTRIBUTES", Function("ATTRIBUTES", "AQL_ATTRIBUTES", "a|b,b", true, true, true) },
|
||||
{ "MERGE", Function("MERGE", "AQL_MERGE", "a,a|+", true, true, true) },
|
||||
{ "MERGE_RECURSIVE", Function("MERGE_RECURSIVE", "AQL_MERGE_RECURSIVE", "a,a|+", true, true, true) },
|
||||
{ "HAS", Function("HAS", "AQL_HAS", "az,s", true, false, true) },
|
||||
{ "ATTRIBUTES", Function("ATTRIBUTES", "AQL_ATTRIBUTES", "a|b,b", true, false, true) },
|
||||
{ "MERGE", Function("MERGE", "AQL_MERGE", "a,a|+", true, false, true) },
|
||||
{ "MERGE_RECURSIVE", Function("MERGE_RECURSIVE", "AQL_MERGE_RECURSIVE", "a,a|+", true, false, true) },
|
||||
{ "DOCUMENT", Function("DOCUMENT", "AQL_DOCUMENT", "h.|.", false, true, false) },
|
||||
{ "MATCHES", Function("MATCHES", "AQL_MATCHES", ".,l|b", true, true, true) },
|
||||
{ "UNSET", Function("UNSET", "AQL_UNSET", "a,sl|+", true, true, true) },
|
||||
{ "KEEP", Function("KEEP", "AQL_KEEP", "a,sl|+", true, true, true) },
|
||||
{ "TRANSLATE", Function("TRANSLATE", "AQL_TRANSLATE", ".,a|.", true, true, true) },
|
||||
{ "MATCHES", Function("MATCHES", "AQL_MATCHES", ".,l|b", true, false, true) },
|
||||
{ "UNSET", Function("UNSET", "AQL_UNSET", "a,sl|+", true, false, true) },
|
||||
{ "KEEP", Function("KEEP", "AQL_KEEP", "a,sl|+", true, false, true) },
|
||||
{ "TRANSLATE", Function("TRANSLATE", "AQL_TRANSLATE", ".,a|.", true, false, true) },
|
||||
|
||||
// geo functions
|
||||
{ "NEAR", Function("NEAR", "AQL_NEAR", "h,n,n|nz,s", false, true, false) },
|
||||
|
@ -199,26 +199,26 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
|
|||
|
||||
// date functions
|
||||
{ "DATE_NOW", Function("DATE_NOW", "AQL_DATE_NOW", "", false, false, true) },
|
||||
{ "DATE_TIMESTAMP", Function("DATE_TIMESTAMP", "AQL_DATE_TIMESTAMP", "ns|ns,ns,ns,ns,ns,ns", true, true, true) },
|
||||
{ "DATE_ISO8601", Function("DATE_ISO8601", "AQL_DATE_ISO8601", "ns|ns,ns,ns,ns,ns,ns", true, true, true) },
|
||||
{ "DATE_DAYOFWEEK", Function("DATE_DAYOFWEEK", "AQL_DATE_DAYOFWEEK", "ns", true, true, true) },
|
||||
{ "DATE_YEAR", Function("DATE_YEAR", "AQL_DATE_YEAR", "ns", true, true, true) },
|
||||
{ "DATE_MONTH", Function("DATE_MONTH", "AQL_DATE_MONTH", "ns", true, true, true) },
|
||||
{ "DATE_DAY", Function("DATE_DAY", "AQL_DATE_DAY", "ns", true, true, true) },
|
||||
{ "DATE_HOUR", Function("DATE_HOUR", "AQL_DATE_HOUR", "ns", true, true, true) },
|
||||
{ "DATE_MINUTE", Function("DATE_MINUTE", "AQL_DATE_MINUTE", "ns", true, true, true) },
|
||||
{ "DATE_SECOND", Function("DATE_SECOND", "AQL_DATE_SECOND", "ns", true, true, true) },
|
||||
{ "DATE_MILLISECOND", Function("DATE_MILLISECOND", "AQL_DATE_MILLISECOND", "ns", true, true, true) },
|
||||
{ "DATE_TIMESTAMP", Function("DATE_TIMESTAMP", "AQL_DATE_TIMESTAMP", "ns|ns,ns,ns,ns,ns,ns", true, false, true) },
|
||||
{ "DATE_ISO8601", Function("DATE_ISO8601", "AQL_DATE_ISO8601", "ns|ns,ns,ns,ns,ns,ns", true, false, true) },
|
||||
{ "DATE_DAYOFWEEK", Function("DATE_DAYOFWEEK", "AQL_DATE_DAYOFWEEK", "ns", true, false, true) },
|
||||
{ "DATE_YEAR", Function("DATE_YEAR", "AQL_DATE_YEAR", "ns", true, false, true) },
|
||||
{ "DATE_MONTH", Function("DATE_MONTH", "AQL_DATE_MONTH", "ns", true, false, true) },
|
||||
{ "DATE_DAY", Function("DATE_DAY", "AQL_DATE_DAY", "ns", true, false, true) },
|
||||
{ "DATE_HOUR", Function("DATE_HOUR", "AQL_DATE_HOUR", "ns", true, false, true) },
|
||||
{ "DATE_MINUTE", Function("DATE_MINUTE", "AQL_DATE_MINUTE", "ns", true, false, true) },
|
||||
{ "DATE_SECOND", Function("DATE_SECOND", "AQL_DATE_SECOND", "ns", true, false, true) },
|
||||
{ "DATE_MILLISECOND", Function("DATE_MILLISECOND", "AQL_DATE_MILLISECOND", "ns", true, false, true) },
|
||||
|
||||
// misc functions
|
||||
{ "FAIL", Function("FAIL", "AQL_FAIL", "|s", false, true, true) },
|
||||
{ "PASSTHRU", Function("PASSTHRU", "AQL_PASSTHRU", ".", false, true, true) },
|
||||
{ "SLEEP", Function("SLEEP", "AQL_SLEEP", "n", false, false, true) },
|
||||
{ "PASSTHRU", Function("PASSTHRU", "AQL_PASSTHRU", ".", false, false, true) },
|
||||
{ "SLEEP", Function("SLEEP", "AQL_SLEEP", "n", false, true, true) },
|
||||
{ "COLLECTIONS", Function("COLLECTIONS", "AQL_COLLECTIONS", "", false, true, false) },
|
||||
{ "NOT_NULL", Function("NOT_NULL", "AQL_NOT_NULL", ".|+", true, true, true) },
|
||||
{ "NOT_NULL", Function("NOT_NULL", "AQL_NOT_NULL", ".|+", true, false, true) },
|
||||
{ "FIRST_LIST", Function("FIRST_LIST", "AQL_FIRST_LIST", ".|+", true, false, true) },
|
||||
{ "FIRST_DOCUMENT", Function("FIRST_DOCUMENT", "AQL_FIRST_DOCUMENT", ".|+", true, false, true) },
|
||||
{ "PARSE_IDENTIFIER", Function("PARSE_IDENTIFIER", "AQL_PARSE_IDENTIFIER", ".", true, true, true) },
|
||||
{ "PARSE_IDENTIFIER", Function("PARSE_IDENTIFIER", "AQL_PARSE_IDENTIFIER", ".", true, false, true) },
|
||||
{ "SKIPLIST", Function("SKIPLIST", "AQL_SKIPLIST", "h,a|n,n", false, true, false) },
|
||||
{ "CURRENT_USER", Function("CURRENT_USER", "AQL_CURRENT_USER", "", false, false, false) },
|
||||
{ "CURRENT_DATABASE", Function("CURRENT_DATABASE", "AQL_CURRENT_DATABASE", "", false, false, false) }
|
||||
|
|
|
@ -96,8 +96,8 @@ int triagens::aql::removeRedundantSorts (Optimizer* opt,
|
|||
if (nodesRelyingOnSort == 0) {
|
||||
// a sort directly followed by another sort: now remove one of them
|
||||
|
||||
if (other.canThrow) {
|
||||
// if the sort can throw, we must not remove it
|
||||
if (other.canThrow || ! other.isDeterministic) {
|
||||
// if the sort can throw or is non-deterministic, we must not remove it
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -267,8 +267,9 @@ int triagens::aql::moveCalculationsUpRule (Optimizer* opt,
|
|||
|
||||
for (auto n : nodes) {
|
||||
auto nn = static_cast<CalculationNode*>(n);
|
||||
if (nn->expression()->canThrow()) {
|
||||
// we will only move expressions up that cannot throw
|
||||
if (nn->expression()->canThrow() ||
|
||||
! nn->expression()->isDeterministic()) {
|
||||
// we will only move expressions up that cannot throw and that are deterministic
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -367,6 +368,14 @@ int triagens::aql::moveFiltersUpRule (Optimizer* opt,
|
|||
break;
|
||||
}
|
||||
|
||||
if (current->getType() == EN::CALCULATION) {
|
||||
// must not move a filter beyond a node with a non-deterministic result
|
||||
auto calculation = static_cast<CalculationNode const*>(current);
|
||||
if (! calculation->expression()->isDeterministic()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
|
||||
auto&& varsSet = current->getVariablesSetHere();
|
||||
|
@ -650,9 +659,8 @@ int triagens::aql::removeUnnecessaryCalculationsRule (Optimizer* opt,
|
|||
if (n->getType() == EN::CALCULATION) {
|
||||
auto nn = static_cast<CalculationNode*>(n);
|
||||
|
||||
if (nn->canThrow() ||
|
||||
! nn->expression()->isDeterministic()) {
|
||||
// If this node can throw or is non-deterministic, we must not optimize it away!
|
||||
if (nn->canThrow()) {
|
||||
// If this node can throw, we must not optimize it away!
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,13 +104,16 @@ function optimizerRuleTestSuite () {
|
|||
"FOR i IN 1..10 LET a = 1 FILTER i == 1 RETURN a",
|
||||
"FOR i IN 1..10 FILTER i == 1 LET a = 1 RETURN i",
|
||||
"FOR i IN 1..10 LET a = 25 + 7 RETURN i",
|
||||
"FOR i IN 1..10 LET a = MIN([ i, 1 ]) LET b = i + 1 RETURN [ a, b ]",
|
||||
"FOR i IN 1..10 LET a = RAND() LET b = 25 + i RETURN i",
|
||||
"FOR i IN 1..10 LET a = SLEEP(0.1) LET b = i + 1 RETURN b",
|
||||
"FOR i IN 1..10 FOR j IN 1..10 LET a = i + 2 RETURN i",
|
||||
"FOR i IN 1..10 FILTER i == 7 LET a = i COLLECT x = i RETURN x"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
var result = AQL_EXPLAIN(query, { }, paramEnabled);
|
||||
assertEqual([ ruleName ], result.plan.rules);
|
||||
assertEqual([ ruleName ], result.plan.rules, query);
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ function optimizerRuleTestSuite () {
|
|||
"FOR i IN 1..10 LET a = i LET b = i FILTER a == b RETURN i",
|
||||
"FOR i IN 1..10 FOR j IN 1..10 FILTER i > j RETURN i",
|
||||
"FOR i IN 1..10 LET a = 2 * i FILTER a == 1 RETURN i",
|
||||
"FOR i IN 1..10 LIMIT 1 FILTER i == 1 RETURN i"
|
||||
"FOR i IN 1..10 LET a = SLEEP(1) FILTER i == 1 RETURN i" // SLEEP is non-deterministic
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
|
@ -106,7 +106,8 @@ function optimizerRuleTestSuite () {
|
|||
"FOR i IN 1..10 FOR j IN 1..10 FILTER i > 1 RETURN i",
|
||||
"FOR i IN 1..10 LET x = (FOR j IN [i] RETURN j) FILTER i > 1 RETURN i",
|
||||
"FOR i IN 1..10 FOR l IN 1..10 LET a = 2 * i FILTER i == 1 RETURN a",
|
||||
"FOR i IN 1..10 FOR l IN 1..10 LET a = 2 * i FILTER i == 1 LIMIT 1 RETURN a"
|
||||
"FOR i IN 1..10 FOR l IN 1..10 LET a = 2 * i FILTER i == 1 LIMIT 1 RETURN a",
|
||||
"FOR i IN 1..10 FOR l IN 1..10 LET a = MIN([1, l]) FILTER i == 1 LIMIT 1 RETURN a",
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
|
|
Loading…
Reference in New Issue