mirror of https://gitee.com/bigwinds/arangodb
fixed issue #2400
This commit is contained in:
parent
3ad5c6366d
commit
467307fd07
24
CHANGELOG
24
CHANGELOG
|
@ -158,7 +158,13 @@ v3.2.alpha1 (2017-02-05)
|
||||||
* generated Foxx services now use swagger tags
|
* generated Foxx services now use swagger tags
|
||||||
|
|
||||||
|
|
||||||
v3.1.16 (2017-XX-XX)
|
v3.1.17 (2017-XX-XX)
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
* fixed issue #2400
|
||||||
|
|
||||||
|
|
||||||
|
v3.1.16 (2017-03-27)
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
* fixed issue #2392
|
* fixed issue #2392
|
||||||
|
@ -173,6 +179,22 @@ v3.1.16 (2017-XX-XX)
|
||||||
|
|
||||||
* avoid name resolution when given connection string is a valid ip address
|
* avoid name resolution when given connection string is a valid ip address
|
||||||
|
|
||||||
|
* helps with issue #1842, bug in COLLECT statement in connection with LIMIT.
|
||||||
|
|
||||||
|
* fix locking bug in cluster traversals
|
||||||
|
|
||||||
|
* increase lock timeout defaults
|
||||||
|
|
||||||
|
* increase various cluster timeouts
|
||||||
|
|
||||||
|
* limit default target size for revision cache to 1GB, which is better for
|
||||||
|
tight RAM situations (used to be 40% of (totalRAM - 1GB), use
|
||||||
|
--database.revision-cache-target-size <VALUEINBYTES> to get back the
|
||||||
|
old behaviour
|
||||||
|
|
||||||
|
* fixed a bug with restarted servers indicating status as "STARTUP"
|
||||||
|
rather that "SERVING" in Nodes UI.
|
||||||
|
|
||||||
|
|
||||||
v3.1.15 (2017-03-20)
|
v3.1.15 (2017-03-20)
|
||||||
--------------------
|
--------------------
|
||||||
|
|
|
@ -1878,7 +1878,7 @@ bool AstNode::isCacheable() const {
|
||||||
/// user-defined function
|
/// user-defined function
|
||||||
bool AstNode::callsUserDefinedFunction() const {
|
bool AstNode::callsUserDefinedFunction() const {
|
||||||
if (isConstant()) {
|
if (isConstant()) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check sub-nodes first
|
// check sub-nodes first
|
||||||
|
@ -1887,14 +1887,36 @@ bool AstNode::callsUserDefinedFunction() const {
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
auto member = getMemberUnchecked(i);
|
auto member = getMemberUnchecked(i);
|
||||||
|
|
||||||
if (!member->callsUserDefinedFunction()) {
|
if (member->callsUserDefinedFunction()) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (type == NODE_TYPE_FCALL_USER);
|
return (type == NODE_TYPE_FCALL_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief whether or not a node (and its subnodes) may contain a call to a
|
||||||
|
/// function or user-defined function
|
||||||
|
bool AstNode::callsFunction() const {
|
||||||
|
if (isConstant()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check sub-nodes first
|
||||||
|
size_t const n = numMembers();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
auto member = getMemberUnchecked(i);
|
||||||
|
|
||||||
|
if (member->callsFunction()) {
|
||||||
|
// abort early
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (type == NODE_TYPE_FCALL || type == NODE_TYPE_FCALL_USER);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief whether or not the object node contains dynamically named attributes
|
/// @brief whether or not the object node contains dynamically named attributes
|
||||||
/// on its first level
|
/// on its first level
|
||||||
bool AstNode::containsDynamicAttributeName() const {
|
bool AstNode::containsDynamicAttributeName() const {
|
||||||
|
|
|
@ -482,6 +482,10 @@ struct AstNode {
|
||||||
/// user-defined function
|
/// user-defined function
|
||||||
bool callsUserDefinedFunction() const;
|
bool callsUserDefinedFunction() const;
|
||||||
|
|
||||||
|
/// @brief whether or not a node (and its subnodes) may contain a call to a
|
||||||
|
/// a function or a user-defined function
|
||||||
|
bool callsFunction() const;
|
||||||
|
|
||||||
/// @brief whether or not the object node contains dynamically named
|
/// @brief whether or not the object node contains dynamically named
|
||||||
/// attributes
|
/// attributes
|
||||||
/// on its first level
|
/// on its first level
|
||||||
|
|
|
@ -1581,7 +1581,6 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
|
||||||
TRI_ASSERT(outvars.size() == 1);
|
TRI_ASSERT(outvars.size() == 1);
|
||||||
auto varsUsedLater = n->getVarsUsedLater();
|
auto varsUsedLater = n->getVarsUsedLater();
|
||||||
|
|
||||||
|
|
||||||
if (varsUsedLater.find(outvars[0]) == varsUsedLater.end()) {
|
if (varsUsedLater.find(outvars[0]) == varsUsedLater.end()) {
|
||||||
// The variable whose value is calculated here is not used at
|
// The variable whose value is calculated here is not used at
|
||||||
// all further down the pipeline! We remove the whole
|
// all further down the pipeline! We remove the whole
|
||||||
|
@ -1669,7 +1668,6 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
|
||||||
vars.clear();
|
vars.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (usageCount == 1) {
|
if (usageCount == 1) {
|
||||||
// our variable is used by exactly one other calculation
|
// our variable is used by exactly one other calculation
|
||||||
// now we can replace the reference to our variable in the other
|
// now we can replace the reference to our variable in the other
|
||||||
|
@ -1688,6 +1686,15 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!n->isInInnerLoop() &&
|
||||||
|
rootNode->callsFunction() &&
|
||||||
|
other->isInInnerLoop()) {
|
||||||
|
// original expression calls a function and is not contained in a loop
|
||||||
|
// we're about to move this expression into a loop, but we don't want
|
||||||
|
// to move (expensive) function calls into loops
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
TRI_ASSERT(other != nullptr);
|
TRI_ASSERT(other != nullptr);
|
||||||
otherExpression->replaceVariableReference(outvars[0], rootNode);
|
otherExpression->replaceVariableReference(outvars[0], rootNode);
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,9 @@ function optimizerRuleTestSuite () {
|
||||||
var queries = [
|
var queries = [
|
||||||
"FOR i IN [ { a: 1 }, { a: 2 }, { a: 3 } ] LET a = i.a LET b = i.a RETURN [ a, b ]",
|
"FOR i IN [ { a: 1 }, { a: 2 }, { a: 3 } ] LET a = i.a LET b = i.a RETURN [ a, b ]",
|
||||||
"FOR i IN [ { a: 1 }, { a: 2 }, { a: 3 } ] LET a = LENGTH(i), b = LENGTH(i) RETURN [ a, b ]",
|
"FOR i IN [ { a: 1 }, { a: 2 }, { a: 3 } ] LET a = LENGTH(i), b = LENGTH(i) RETURN [ a, b ]",
|
||||||
"FOR i IN [ { a: 1 }, { a: 2 }, { a: 3 } ] LET a = MAX(i) RETURN MAX(i)"
|
"FOR i IN [ { a: 1 }, { a: 2 }, { a: 3 } ] LET a = MAX(i) RETURN MAX(i)",
|
||||||
|
"LET a = NOOPT(CONCAT('a', 'b')) FOR i IN [ 1, 2, 3 ] RETURN CONCAT(a, 'b')",
|
||||||
|
"FOR i IN [ 1, 2, 3 ] LET a = CONCAT(i, 'b') RETURN CONCAT(a, 'b')"
|
||||||
];
|
];
|
||||||
|
|
||||||
queries.forEach(function(query) {
|
queries.forEach(function(query) {
|
||||||
|
@ -89,7 +91,8 @@ function optimizerRuleTestSuite () {
|
||||||
["FOR i IN [ { a: 1 }, { a: 2 }, { a: 3 } ] LET a = LENGTH(i), b = LENGTH(i) + 1 RETURN [ a, b ]", true],
|
["FOR i IN [ { a: 1 }, { a: 2 }, { a: 3 } ] LET a = LENGTH(i), b = LENGTH(i) + 1 RETURN [ a, b ]", true],
|
||||||
["FOR i IN [ " + collection + " ] LET a = MAX(i.a) RETURN MIN(i.a)", true],
|
["FOR i IN [ " + collection + " ] LET a = MAX(i.a) RETURN MIN(i.a)", true],
|
||||||
["FOR i IN [ { a: 1 }, { a: 2 }, { a: 3 } ] LET a = RAND(), b = RAND() RETURN [ a, b ]", false],
|
["FOR i IN [ { a: 1 }, { a: 2 }, { a: 3 } ] LET a = RAND(), b = RAND() RETURN [ a, b ]", false],
|
||||||
["FOR i IN [ " + collection + " ] LET c = MAX(i.a) COLLECT d = c LET i = RAND() LET b = i.a RETURN d",true]
|
["FOR i IN [ " + collection + " ] LET c = MAX(i.a) COLLECT d = c LET i = RAND() LET b = i.a RETURN d", true],
|
||||||
|
["LET a = NOOPT(CONCAT('a', 'b')) FOR i IN [ 1, 2, 3 ] RETURN CONCAT(a, 'b')", true]
|
||||||
];
|
];
|
||||||
|
|
||||||
queryList.forEach(function(query) {
|
queryList.forEach(function(query) {
|
||||||
|
|
|
@ -82,7 +82,8 @@ function optimizerRuleTestSuite () {
|
||||||
"FOR i IN [1] LET a = i, b = i RETURN [ a, b ]",
|
"FOR i IN [1] LET a = i, b = i RETURN [ a, b ]",
|
||||||
"FOR i IN [1] LET a = i + 1, b = i - 1 RETURN [ a, b ]",
|
"FOR i IN [1] LET a = i + 1, b = i - 1 RETURN [ a, b ]",
|
||||||
"FOR i IN [1] LET a = i RETURN a.value",
|
"FOR i IN [1] LET a = i RETURN a.value",
|
||||||
"FOR i IN [1] LET a = i RETURN a[0]"
|
"FOR i IN [1] LET a = i RETURN a[0]",
|
||||||
|
"FOR i IN [ 1, 2, 3 ] LET a = CONCAT(i, 'b') RETURN CONCAT(a, 'b')"
|
||||||
];
|
];
|
||||||
|
|
||||||
queries.forEach(function(query) {
|
queries.forEach(function(query) {
|
||||||
|
@ -169,7 +170,10 @@ function optimizerRuleTestSuite () {
|
||||||
|
|
||||||
// v8 vs. non-v8 expression types
|
// v8 vs. non-v8 expression types
|
||||||
"FOR doc IN [ { a: 1 }, { a: 2 } ] LET a = V8(ATTRIBUTES(doc)) RETURN KEEP(doc, a)",
|
"FOR doc IN [ { a: 1 }, { a: 2 } ] LET a = V8(ATTRIBUTES(doc)) RETURN KEEP(doc, a)",
|
||||||
"FOR doc IN [ { a: 1 }, { a: 2 } ] LET a = ATTRIBUTES(doc) RETURN V8(KEEP(doc, a))"
|
"FOR doc IN [ { a: 1 }, { a: 2 } ] LET a = ATTRIBUTES(doc) RETURN V8(KEEP(doc, a))",
|
||||||
|
|
||||||
|
// different loop
|
||||||
|
"LET a = NOOPT(CONCAT('a', 'b')) FOR i IN [ 1, 2, 3 ] RETURN CONCAT(a, 'b')"
|
||||||
];
|
];
|
||||||
|
|
||||||
queries.forEach(function(query) {
|
queries.forEach(function(query) {
|
||||||
|
@ -266,7 +270,10 @@ function optimizerRuleTestSuite () {
|
||||||
|
|
||||||
// same expression types
|
// same expression types
|
||||||
"FOR doc IN [ { a: 1 }, { a: 2 } ] LET a = V8(ATTRIBUTES(doc)) RETURN V8(KEEP(doc, a))",
|
"FOR doc IN [ { a: 1 }, { a: 2 } ] LET a = V8(ATTRIBUTES(doc)) RETURN V8(KEEP(doc, a))",
|
||||||
"FOR doc IN [ { a: 1 }, { a: 2 } ] LET a = ATTRIBUTES(doc) RETURN KEEP(doc, a)"
|
"FOR doc IN [ { a: 1 }, { a: 2 } ] LET a = ATTRIBUTES(doc) RETURN KEEP(doc, a)",
|
||||||
|
|
||||||
|
// same loop
|
||||||
|
"FOR i IN [ 1, 2, 3 ] LET a = CONCAT(i, 'b') RETURN CONCAT(a, 'b')"
|
||||||
];
|
];
|
||||||
|
|
||||||
queries.forEach(function(query) {
|
queries.forEach(function(query) {
|
||||||
|
|
Loading…
Reference in New Issue