1
0
Fork 0

fixed leak

This commit is contained in:
Jan Steemann 2015-01-19 22:25:16 +01:00
parent 70a1392dad
commit 14e82da2b0
5 changed files with 322 additions and 290 deletions

View File

@ -526,7 +526,7 @@ AstNode::AstNode (Ast* ast,
case NODE_TYPE_RANGE:
case NODE_TYPE_NOP:
break;
}
}
Json subNodes = json.get("subNodes");
if (subNodes.isArray()) {

View File

@ -5504,9 +5504,9 @@ int RemoteBlock::initializeCursor (AqlItemBlock* items, size_t pos) {
}
else {
body("pos", Json(static_cast<double>(pos)))
("items", items->toJson(_engine->getQuery()->trx()))
("exhausted", Json(false))
("error", Json(false));
("items", items->toJson(_engine->getQuery()->trx()))
("exhausted", Json(false))
("error", Json(false));
}
std::string bodyString(body.toString());

View File

@ -1160,6 +1160,296 @@ int triagens::aql::removeUnnecessaryCalculationsRule (Optimizer* opt,
return TRI_ERROR_NO_ERROR;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief helper function to find variable and attribute names from a node (if any)
//////////////////////////////////////////////////////////////////////////////////////////////////
static void FindVarAndAttr (ExecutionPlan const* plan,
AstNode const* node,
Variable const*& enumCollVar,
std::string& attr) {
if (node->type == NODE_TYPE_REFERENCE) {
auto x = static_cast<Variable*>(node->getData());
auto setter = plan->getVarSetBy(x->id);
if (setter != nullptr &&
setter->getType() == EN::ENUMERATE_COLLECTION) {
enumCollVar = x;
}
return;
}
if (node->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
FindVarAndAttr(plan, node->getMember(0), enumCollVar, attr);
if (enumCollVar != nullptr) {
char const* attributeName = node->getStringValue();
attr.append(attributeName);
attr.push_back('.');
}
return;
}
attr.clear();
enumCollVar = nullptr;
return;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief builds a range info from the expression node
////////////////////////////////////////////////////////////////////////////////
static RangeInfoMapVec* BuildRangeInfo (ExecutionPlan* plan,
AstNode const* node,
Variable const*& enumCollVar,
std::string& attr,
bool& mustNotUseRanges,
AstNodeType combineType = NODE_TYPE_OPERATOR_BINARY_AND) {
TRI_ASSERT(combineType == NODE_TYPE_OPERATOR_BINARY_AND ||
combineType == NODE_TYPE_OPERATOR_BINARY_OR);
bool foundSomething = false;
if (node->type == NODE_TYPE_OPERATOR_BINARY_EQ) {
auto lhs = node->getMember(0);
auto rhs = node->getMember(1);
std::unique_ptr<RangeInfoMap> rim(new RangeInfoMap());
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
FindVarAndAttr(plan, rhs, enumCollVar, attr);
if (enumCollVar != nullptr) {
foundSomething = true;
std::unordered_set<Variable*> varsUsed
= Ast::getReferencedVariables(lhs);
if (varsUsed.find(const_cast<Variable*>(enumCollVar))
== varsUsed.end()) {
// Found a multiple attribute access of a variable and an
// expression which does not involve that variable:
rim->insert(enumCollVar->name,
attr.substr(0, attr.size() - 1),
RangeInfoBound(lhs, true),
RangeInfoBound(lhs, true),
true);
enumCollVar = nullptr;
attr.clear();
}
}
}
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
FindVarAndAttr(plan, lhs, enumCollVar, attr);
if (enumCollVar != nullptr) {
foundSomething = true;
std::unordered_set<Variable*> varsUsed
= Ast::getReferencedVariables(rhs);
if (varsUsed.find(const_cast<Variable*>(enumCollVar))
== varsUsed.end()) {
// Found a multiple attribute access of a variable and an
// expression which does not involve that variable:
rim->insert(enumCollVar->name,
attr.substr(0, attr.size() - 1),
RangeInfoBound(rhs, true),
RangeInfoBound(rhs, true),
true);
enumCollVar = nullptr;
attr.clear();
}
}
}
if (combineType == NODE_TYPE_OPERATOR_BINARY_OR && ! foundSomething) {
// disable the use of the range because we may have found something like this,
// which makes using an index for a.x invalid:
// a.x == 1 || RAND() > 0
mustNotUseRanges = true;
}
return new RangeInfoMapVec(rim.release());
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_LT ||
node->type == NODE_TYPE_OPERATOR_BINARY_GT ||
node->type == NODE_TYPE_OPERATOR_BINARY_LE ||
node->type == NODE_TYPE_OPERATOR_BINARY_GE) {
std::unique_ptr<RangeInfoMap> rim(new RangeInfoMap());
bool include = (node->type == NODE_TYPE_OPERATOR_BINARY_LE ||
node->type == NODE_TYPE_OPERATOR_BINARY_GE);
auto lhs = node->getMember(0);
auto rhs = node->getMember(1);
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
// Attribute access on the right:
// First find out whether there is a multiple attribute access
// of a variable on the right:
FindVarAndAttr(plan, rhs, enumCollVar, attr);
if (enumCollVar != nullptr) {
foundSomething = true;
RangeInfoBound low;
RangeInfoBound high;
// Constant value on the left, so insert a constant condition:
if (node->type == NODE_TYPE_OPERATOR_BINARY_GE ||
node->type == NODE_TYPE_OPERATOR_BINARY_GT) {
high.assign(lhs, include);
}
else {
low.assign(lhs, include);
}
rim->insert(enumCollVar->name,
attr.substr(0, attr.size() - 1),
low,
high,
false);
enumCollVar = nullptr;
attr.clear();
}
}
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
// Attribute access on the left:
// First find out whether there is a multiple attribute access
// of a variable on the left:
FindVarAndAttr(plan, lhs, enumCollVar, attr);
if (enumCollVar != nullptr) {
foundSomething = true;
RangeInfoBound low;
RangeInfoBound high;
// Constant value on the right, so insert a constant condition:
if (node->type == NODE_TYPE_OPERATOR_BINARY_GE ||
node->type == NODE_TYPE_OPERATOR_BINARY_GT) {
low.assign(rhs, include);
}
else {
high.assign(rhs, include);
}
rim->insert(enumCollVar->name,
attr.substr(0, attr.size() - 1),
low,
high,
false);
enumCollVar = nullptr;
attr.clear();
}
}
if (combineType == NODE_TYPE_OPERATOR_BINARY_OR && ! foundSomething) {
// disable the use of the range because we may have found something like this,
// which makes using an index for a.x invalid:
// a.x == 1 || RAND() > 0
mustNotUseRanges = true;
}
return new RangeInfoMapVec(rim.release());
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_AND) {
auto lhs = BuildRangeInfo(plan, node->getMember(0), enumCollVar, attr, mustNotUseRanges, node->type);
auto rhs = BuildRangeInfo(plan, node->getMember(1), enumCollVar, attr, mustNotUseRanges, node->type);
if ((lhs == nullptr || lhs->empty()) && rhs != nullptr) {
delete lhs;
return rhs;
}
else if (lhs != nullptr && (rhs == nullptr || rhs->empty())) {
delete rhs;
return lhs;
}
// distribute AND into OR
return andCombineRangeInfoMapVecs(lhs, rhs);
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_IN) {
auto lhs = node->getMember(0); // enumCollVar
auto rhs = node->getMember(1); // value
std::unique_ptr<RangeInfoMapVec> rimv(new RangeInfoMapVec());
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
FindVarAndAttr(plan, lhs, enumCollVar, attr);
if (enumCollVar != nullptr) {
foundSomething = true;
std::unordered_set<Variable*> varsUsed
= Ast::getReferencedVariables(rhs);
if (varsUsed.find(const_cast<Variable*>(enumCollVar))
== varsUsed.end()) {
// Found a multiple attribute access of a variable and an
// expression which does not involve that variable:
if (rhs->type == NODE_TYPE_ARRAY) {
for (size_t i = 0; i < rhs->numMembers(); i++) {
RangeInfo ri(enumCollVar->name,
attr.substr(0, attr.size() - 1),
RangeInfoBound(rhs->getMember(i), true),
RangeInfoBound(rhs->getMember(i), true),
true);
rimv->differenceRangeInfo(ri);
if (ri.isValid()) {
rimv->emplace_back(new RangeInfoMap(ri));
}
}
}
else {
RangeInfo ri(enumCollVar->name,
attr.substr(0, attr.size() - 1),
RangeInfoBound(rhs, true),
RangeInfoBound(rhs, true),
true);
rimv->differenceRangeInfo(ri);
if (ri.isValid()) {
rimv->emplace_back(new RangeInfoMap(ri));
}
}
enumCollVar = nullptr;
attr.clear();
}
}
}
if (combineType == NODE_TYPE_OPERATOR_BINARY_OR && ! foundSomething) {
// disable the use of the range because we may have found something like this,
// which makes using an index for a.x invalid:
// a.x == 1 || RAND() > 0
mustNotUseRanges = true;
}
return rimv.release();
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_OR) {
return orCombineRangeInfoMapVecs(
BuildRangeInfo(plan, node->getMember(0), enumCollVar, attr, mustNotUseRanges, node->type),
BuildRangeInfo(plan, node->getMember(1), enumCollVar, attr, mustNotUseRanges, node->type)
);
}
if (combineType == NODE_TYPE_OPERATOR_BINARY_AND) {
attr.clear();
enumCollVar = nullptr;
return nullptr;
}
// default case
mustNotUseRanges = true;
attr.clear();
enumCollVar = nullptr;
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief prefer IndexRange nodes over EnumerateCollection nodes
////////////////////////////////////////////////////////////////////////////////
@ -1221,13 +1511,18 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
auto node = static_cast<CalculationNode*>(en);
std::string attr;
Variable const* enumCollVar = nullptr;
auto expression = node->expression()->node();
// there is an implicit AND between FILTER statements
if (_rangeInfoMapVec == nullptr) {
_rangeInfoMapVec = buildRangeInfo(node->expression()->node(), enumCollVar, attr, NODE_TYPE_OPERATOR_BINARY_AND);
// don't yet have anything to AND-combine
_rangeInfoMapVec = BuildRangeInfo(_plan, expression, enumCollVar, attr, _mustNotUseRanges);
}
else {
_rangeInfoMapVec = andCombineRangeInfoMapVecs(_rangeInfoMapVec,
buildRangeInfo(node->expression()->node(), enumCollVar, attr, NODE_TYPE_OPERATOR_BINARY_AND));
// AND-combine with previous ranges
_rangeInfoMapVec = andCombineRangeInfoMapVecs(
_rangeInfoMapVec,
BuildRangeInfo(_plan, expression, enumCollVar, attr, _mustNotUseRanges)
);
}
if (_rangeInfoMapVec != nullptr && _mustNotUseRanges) {
@ -1533,282 +1828,6 @@ class FilterToEnumCollFinder : public WalkerWorker<ExecutionNode> {
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void findVarAndAttr (AstNode const* node,
Variable const*& enumCollVar,
std::string& attr) {
if (node->type == NODE_TYPE_REFERENCE) {
auto x = static_cast<Variable*>(node->getData());
auto setter = _plan->getVarSetBy(x->id);
if (setter != nullptr &&
setter->getType() == EN::ENUMERATE_COLLECTION) {
enumCollVar = x;
}
return;
}
if (node->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
findVarAndAttr(node->getMember(0), enumCollVar, attr);
if (enumCollVar != nullptr) {
char const* attributeName = node->getStringValue();
attr.append(attributeName);
attr.push_back('.');
}
return;
}
attr.clear();
enumCollVar = nullptr;
return;
}
RangeInfoMapVec* buildRangeInfo (AstNode const* node,
Variable const*& enumCollVar,
std::string& attr,
AstNodeType previousNode) {
bool foundSomething = false;
if (node->type == NODE_TYPE_OPERATOR_BINARY_EQ) {
auto lhs = node->getMember(0);
auto rhs = node->getMember(1);
std::unique_ptr<RangeInfoMap> rim(new RangeInfoMap());
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
findVarAndAttr(rhs, enumCollVar, attr);
if (enumCollVar != nullptr) {
foundSomething = true;
std::unordered_set<Variable*> varsUsed
= Ast::getReferencedVariables(lhs);
if (varsUsed.find(const_cast<Variable*>(enumCollVar))
== varsUsed.end()) {
// Found a multiple attribute access of a variable and an
// expression which does not involve that variable:
rim->insert(enumCollVar->name,
attr.substr(0, attr.size() - 1),
RangeInfoBound(lhs, true),
RangeInfoBound(lhs, true),
true);
enumCollVar = nullptr;
attr.clear();
}
}
}
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
findVarAndAttr(lhs, enumCollVar, attr);
if (enumCollVar != nullptr) {
foundSomething = true;
std::unordered_set<Variable*> varsUsed
= Ast::getReferencedVariables(rhs);
if (varsUsed.find(const_cast<Variable*>(enumCollVar))
== varsUsed.end()) {
// Found a multiple attribute access of a variable and an
// expression which does not involve that variable:
rim->insert(enumCollVar->name,
attr.substr(0, attr.size() - 1),
RangeInfoBound(rhs, true),
RangeInfoBound(rhs, true),
true);
enumCollVar = nullptr;
attr.clear();
}
}
}
if (previousNode == NODE_TYPE_OPERATOR_BINARY_OR && ! foundSomething) {
// disable the use of the range because we may have found something like this,
// which makes using an index for a.x invalid:
// a.x == 1 || RAND() > 0
_mustNotUseRanges = true;
}
return new RangeInfoMapVec(rim.release());
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_LT ||
node->type == NODE_TYPE_OPERATOR_BINARY_GT ||
node->type == NODE_TYPE_OPERATOR_BINARY_LE ||
node->type == NODE_TYPE_OPERATOR_BINARY_GE) {
std::unique_ptr<RangeInfoMap> rim(new RangeInfoMap());
bool include = (node->type == NODE_TYPE_OPERATOR_BINARY_LE ||
node->type == NODE_TYPE_OPERATOR_BINARY_GE);
auto lhs = node->getMember(0);
auto rhs = node->getMember(1);
if (rhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
// Attribute access on the right:
// First find out whether there is a multiple attribute access
// of a variable on the right:
findVarAndAttr(rhs, enumCollVar, attr);
if (enumCollVar != nullptr) {
foundSomething = true;
RangeInfoBound low;
RangeInfoBound high;
// Constant value on the left, so insert a constant condition:
if (node->type == NODE_TYPE_OPERATOR_BINARY_GE ||
node->type == NODE_TYPE_OPERATOR_BINARY_GT) {
high.assign(lhs, include);
}
else {
low.assign(lhs, include);
}
rim->insert(enumCollVar->name,
attr.substr(0, attr.size() - 1),
low,
high,
false);
enumCollVar = nullptr;
attr.clear();
}
}
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
// Attribute access on the left:
// First find out whether there is a multiple attribute access
// of a variable on the left:
findVarAndAttr(lhs, enumCollVar, attr);
if (enumCollVar != nullptr) {
foundSomething = true;
RangeInfoBound low;
RangeInfoBound high;
// Constant value on the right, so insert a constant condition:
if (node->type == NODE_TYPE_OPERATOR_BINARY_GE ||
node->type == NODE_TYPE_OPERATOR_BINARY_GT) {
low.assign(rhs, include);
}
else {
high.assign(rhs, include);
}
rim->insert(enumCollVar->name,
attr.substr(0, attr.size() - 1),
low,
high,
false);
enumCollVar = nullptr;
attr.clear();
}
}
if (previousNode == NODE_TYPE_OPERATOR_BINARY_OR && ! foundSomething) {
// disable the use of the range because we may have found something like this,
// which makes using an index for a.x invalid:
// a.x == 1 || RAND() > 0
_mustNotUseRanges = true;
}
return new RangeInfoMapVec(rim.release());
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_AND) {
auto lhs = buildRangeInfo(node->getMember(0), enumCollVar, attr, node->type);
auto rhs = buildRangeInfo(node->getMember(1), enumCollVar, attr, node->type);
if ((lhs == nullptr || lhs->empty()) && rhs != nullptr) {
delete lhs;
return rhs;
}
else if (lhs != nullptr && (rhs == nullptr || rhs->empty())) {
delete rhs;
return lhs;
}
// distribute AND into OR
return andCombineRangeInfoMapVecs(buildRangeInfo(node->getMember(0), enumCollVar, attr, node->type),
buildRangeInfo(node->getMember(1), enumCollVar, attr, node->type));
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_IN) {
auto lhs = node->getMember(0); // enumCollVar
auto rhs = node->getMember(1); // value
std::unique_ptr<RangeInfoMapVec> rimv(new RangeInfoMapVec());
if (lhs->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
findVarAndAttr(lhs, enumCollVar, attr);
if (enumCollVar != nullptr) {
foundSomething = true;
std::unordered_set<Variable*> varsUsed
= Ast::getReferencedVariables(rhs);
if (varsUsed.find(const_cast<Variable*>(enumCollVar))
== varsUsed.end()) {
// Found a multiple attribute access of a variable and an
// expression which does not involve that variable:
if (rhs->type == NODE_TYPE_ARRAY) {
for (size_t i = 0; i < rhs->numMembers(); i++) {
RangeInfo ri(enumCollVar->name,
attr.substr(0, attr.size() - 1),
RangeInfoBound(rhs->getMember(i), true),
RangeInfoBound(rhs->getMember(i), true),
true);
rimv->differenceRangeInfo(ri);
if (ri.isValid()) {
rimv->emplace_back(new RangeInfoMap(ri));
}
}
}
else {
RangeInfo ri(enumCollVar->name,
attr.substr(0, attr.size() - 1),
RangeInfoBound(rhs, true),
RangeInfoBound(rhs, true),
true);
rimv->differenceRangeInfo(ri);
if (ri.isValid()) {
rimv->emplace_back(new RangeInfoMap(ri));
}
}
enumCollVar = nullptr;
attr.clear();
}
}
}
if (previousNode == NODE_TYPE_OPERATOR_BINARY_OR && ! foundSomething) {
// disable the use of the range because we may have found something like this,
// which makes using an index for a.x invalid:
// a.x == 1 || RAND() > 0
_mustNotUseRanges = true;
}
return rimv.release();
}
if (node->type == NODE_TYPE_OPERATOR_BINARY_OR) {
return orCombineRangeInfoMapVecs(buildRangeInfo(node->getMember(0), enumCollVar, attr, node->type),
buildRangeInfo(node->getMember(1), enumCollVar, attr, node->type));
}
if (previousNode == NODE_TYPE_OPERATOR_BINARY_AND) {
attr.clear();
enumCollVar = nullptr;
return nullptr;
}
// default case
_mustNotUseRanges = true;
attr.clear();
enumCollVar = nullptr;
return nullptr;
}
bool enterSubquery (ExecutionNode* super, ExecutionNode* sub) final {
return false;
}

View File

@ -130,7 +130,10 @@ AstNode const* RangeInfoBound::getExpressionAst (Ast* ast) const {
if (_isConstant) {
return nullptr;
}
// TODO: check who is going to free this node...
_expressionAst = new AstNode(ast, _bound);
return _expressionAst;
}
@ -408,6 +411,7 @@ bool RangeInfoMap::isValid (std::string const& var) {
void RangeInfoMap::attributes (std::unordered_set<std::string>& set,
std::string const& var) {
std::unordered_map<std::string, RangeInfo>* map = find(var);
if (map != nullptr) {
for(auto x: *map) {
set.insert(x.first);
@ -415,11 +419,17 @@ void RangeInfoMap::attributes (std::unordered_set<std::string>& set,
}
}
std::unordered_set<std::string> RangeInfoMap::variables () {
////////////////////////////////////////////////////////////////////////////////
/// @brief return the names of variables contained in the RangeInfoMap
////////////////////////////////////////////////////////////////////////////////
std::unordered_set<std::string> RangeInfoMap::variables () const {
std::unordered_set<std::string> vars;
for(auto x: _ranges) {
vars.insert(x.first);
}
return vars;
}
@ -432,8 +442,8 @@ std::unordered_set<std::string> RangeInfoMap::variables () {
/// RangeInfoMap containing a single RangeInfo.
////////////////////////////////////////////////////////////////////////////////
RangeInfoMapVec::RangeInfoMapVec (RangeInfoMap* rim) :
_rangeInfoMapVec() {
RangeInfoMapVec::RangeInfoMapVec (RangeInfoMap* rim)
: _rangeInfoMapVec() {
_rangeInfoMapVec.emplace_back(rim);
}

View File

@ -587,7 +587,7 @@ namespace triagens {
public:
RangeInfoMap (const RangeInfoMap& copy) = delete;
RangeInfoMap (RangeInfoMap const& copy) = delete;
RangeInfoMap& operator= (RangeInfoMap const& copy) = delete;
////////////////////////////////////////////////////////////////////////////////
@ -742,9 +742,11 @@ namespace triagens {
void attributes (std::unordered_set<std::string>& set, std::string const& var);
////////////////////////////////////////////////////////////////////////////////
/// @brief return the names of variables contained in the RangeInfoMap
////////////////////////////////////////////////////////////////////////////////
//TODO write @brief
std::unordered_set<std::string> variables();
std::unordered_set<std::string> variables() const;
////////////////////////////////////////////////////////////////////////////////
/// @brief private data
@ -766,7 +768,7 @@ namespace triagens {
public:
RangeInfoMapVec (const RangeInfoMapVec& copy) = delete;
RangeInfoMapVec (RangeInfoMapVec const& copy) = delete;
RangeInfoMapVec& operator= (RangeInfoMapVec const& copy) = delete;
////////////////////////////////////////////////////////////////////////////////
@ -888,6 +890,7 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
private:
std::vector<RangeInfoMap*> _rangeInfoMapVec;
};