CParentIntfc::~CParentIntfc() { TInt count = iChildrenList.Count(); CChildIntfc* childPtr(NULL); for (TInt index(0); index < count; index++) { if (GetChild(index, childPtr) == KErrNone) { childPtr->ParentDeleted(*((CParentIntfc*)this)); } } iChildrenList.Close(); }
MatchExpression::ExpressionOptimizerFunc ListOfMatchExpression::getOptimizer() const { return [](std::unique_ptr<MatchExpression> expression) -> std::unique_ptr<MatchExpression> { auto& children = static_cast<ListOfMatchExpression&>(*expression)._expressions; // Recursively apply optimizations to child expressions. for (auto& childExpression : children) { // Since 'childExpression' is a reference to a member of the ListOfMatchExpression's // child array, this assignment replaces the original child with the optimized child. // We must set this child's entry in '_expressions' to null after assigning ownership to // 'childExpressionPtr'. Otherwise, if the call to optimize() throws we will attempt to // free twice. std::unique_ptr<MatchExpression> childExpressionPtr(childExpression); childExpression = nullptr; auto optimizedExpression = MatchExpression::optimize(std::move(childExpressionPtr)); childExpression = optimizedExpression.release(); } // Associativity of AND and OR: an AND absorbs the children of any ANDs among its children // (and likewise for any OR with OR children). MatchType matchType = expression->matchType(); if (matchType == AND || matchType == OR) { std::vector<MatchExpression*> absorbedExpressions; for (MatchExpression*& childExpression : children) { if (childExpression->matchType() == matchType) { // Move this child out of the children array. std::unique_ptr<ListOfMatchExpression> childExpressionPtr( static_cast<ListOfMatchExpression*>(childExpression)); childExpression = nullptr; // Null out this child's entry in _expressions, so // that it will be deleted by the erase call below. // Move all of the grandchildren from the child expression to // absorbedExpressions. auto& grandChildren = childExpressionPtr->_expressions; absorbedExpressions.insert( absorbedExpressions.end(), grandChildren.begin(), grandChildren.end()); grandChildren.clear(); // Note that 'childExpressionPtr' will now be destroyed. } } // We replaced each destroyed child expression with nullptr. Now we remove those // nullptrs from the array. children.erase(std::remove(children.begin(), children.end(), nullptr), children.end()); // Append the absorbed children to the end of the array. children.insert(children.end(), absorbedExpressions.begin(), absorbedExpressions.end()); } // Remove all children of AND that are $alwaysTrue and all children of OR that are // $alwaysFalse. if (matchType == AND || matchType == OR) { for (MatchExpression*& childExpression : children) { if ((childExpression->isTriviallyTrue() && matchType == MatchExpression::AND) || (childExpression->isTriviallyFalse() && matchType == MatchExpression::OR)) { std::unique_ptr<MatchExpression> childPtr(childExpression); childExpression = nullptr; } } // We replaced each destroyed child expression with nullptr. Now we remove those // nullptrs from the vector. children.erase(std::remove(children.begin(), children.end(), nullptr), children.end()); } // Check if the above optimizations eliminated all children. An OR with no children is // always false. // TODO SERVER-34759 It is correct to replace this empty AND with an $alwaysTrue, but we // need to make enhancements to the planner to make it understand an $alwaysTrue and an // empty AND as the same thing. The planner can create inferior plans for $alwaysTrue which // it would not produce for an AND with no children. if (children.empty() && matchType == MatchExpression::OR) { return stdx::make_unique<AlwaysFalseMatchExpression>(); } if (children.size() == 1) { if ((matchType == AND || matchType == OR || matchType == INTERNAL_SCHEMA_XOR)) { // Simplify AND/OR/XOR with exactly one operand to an expression consisting of just // that operand. MatchExpression* simplifiedExpression = children.front(); children.clear(); return std::unique_ptr<MatchExpression>(simplifiedExpression); } else if (matchType == NOR) { // Simplify NOR of exactly one operand to NOT of that operand. auto simplifiedExpression = stdx::make_unique<NotMatchExpression>(children.front()); children.clear(); return std::move(simplifiedExpression); } } if (matchType == MatchExpression::AND || matchType == MatchExpression::OR) { for (auto& childExpression : children) { // An AND containing an expression that always evaluates to false can be // optimized to a single $alwaysFalse expression. if (childExpression->isTriviallyFalse() && matchType == MatchExpression::AND) { return stdx::make_unique<AlwaysFalseMatchExpression>(); } // Likewise, an OR containing an expression that always evaluates to true can be // optimized to a single $alwaysTrue expression. if (childExpression->isTriviallyTrue() && matchType == MatchExpression::OR) { return stdx::make_unique<AlwaysTrueMatchExpression>(); } } } return expression; }; }