1
0
Fork 0

prelim version of undistributeRemoveAfterEnumColl

This commit is contained in:
James 2014-10-01 10:17:36 +01:00
parent 96cb6e3550
commit 2fd8c2b185
2 changed files with 150 additions and 7 deletions

View File

@ -1875,17 +1875,17 @@ int triagens::aql::distributeSortToCluster (Optimizer* opt,
return TRI_ERROR_NO_ERROR;
}
class RemoveToSingletonViaCalcOnlyFinder: public WalkerWorker<ExecutionNode> {
class RemoteToSingletonViaCalcOnlyFinder: public WalkerWorker<ExecutionNode> {
ExecutionNode* _scatter;
std::unordered_set<ExecutionNode*>& _toUnlink;
public:
RemoveToSingletonViaCalcOnlyFinder (std::unordered_set<ExecutionNode*>& toUnlink)
RemoteToSingletonViaCalcOnlyFinder (std::unordered_set<ExecutionNode*>& toUnlink)
: _scatter(nullptr),
_toUnlink(toUnlink){
};
~RemoveToSingletonViaCalcOnlyFinder () {
~RemoteToSingletonViaCalcOnlyFinder () {
}
bool before (ExecutionNode* en) {
@ -1944,19 +1944,156 @@ class RemoveToSingletonViaCalcOnlyFinder: public WalkerWorker<ExecutionNode> {
////////////////////////////////////////////////////////////////////////////////
int triagens::aql::removeUnnecessaryRemoteScatter (Optimizer* opt,
ExecutionPlan* plan,
Optimizer::Rule const* rule) {
ExecutionPlan* plan,
Optimizer::Rule const* rule) {
std::vector<ExecutionNode*> nodes
= plan->findNodesOfType(triagens::aql::ExecutionNode::REMOTE, true);
std::unordered_set<ExecutionNode*> toUnlink;
for (auto n : nodes) {
RemoveToSingletonViaCalcOnlyFinder finder(toUnlink);
RemoteToSingletonViaCalcOnlyFinder finder(toUnlink);
n->walk(&finder);
}
bool modified = false;
if (! toUnlink.empty()) {
if (!toUnlink.empty()) {
plan->unlinkNodes(toUnlink);
plan->findVarUsage();
modified = true;
}
opt->addPlan(plan, rule->level, modified);
return TRI_ERROR_NO_ERROR;
}
class RemoveToEnumCollFinder: public WalkerWorker<ExecutionNode> {
ExecutionPlan* _plan;
std::unordered_set<ExecutionNode*>& _toUnlink;
bool _remove;
bool _scatter;
bool _gather;
EnumerateCollectionNode* _enumColl;
const Variable* _variable;
public:
RemoveToEnumCollFinder (ExecutionPlan* plan,
std::unordered_set<ExecutionNode*>& toUnlink)
: _plan(plan),
_toUnlink(toUnlink),
_remove(false),
_scatter(false),
_gather(false),
_enumColl(nullptr){
};
~RemoveToEnumCollFinder () {
}
bool before (ExecutionNode* en) {
switch (en->getType()) {
case EN::REMOVE:{
TRI_ASSERT(_remove == false);
_remove = en;
_toUnlink.insert(en);
// find the variable we are removing . . .
auto rn = static_cast<RemoveNode*>(en);
auto varsToRemove = rn->getVariablesUsedHere();
// remove nodes always have one input variable
TRI_ASSERT(varsToRemove.size() == 1);
_variable = varsToRemove[0]; // the variable we'll remove
auto _enumColl = static_cast<EnumerateCollectionNode*>(_plan->getVarSetBy(_variable->id));
if (_enumColl == nullptr
|| _enumColl->getType() != triagens::aql::ExecutionNode::ENUMERATE_COLLECTION
|| _enumColl->collection()->cid() != rn->collection()->cid() ) {
// remove variable was not introduced by an enumerate collection or
// it was but the collections differ
break; // abort . . .
}
return false; // continue . . .
}
case EN::REMOTE:{
_toUnlink.insert(en);
return false; // continue . . .
}
case EN::SCATTER:{
if (_scatter) { // met more than one scatter node
break; // abort . . .
}
_scatter = en;
_toUnlink.insert(en);
return false; // continue . . .
}
case EN::GATHER:{
if (_gather) { // met more than one gather node
break; // abort . . .
}
_gather = en;
_toUnlink.insert(en);
return false; // continue . . .
}
case EN::FILTER:{
// check that we are filtering something with the variable we are to remove
auto fn = static_cast<FilterNode*>(en);
auto varsUsedHere = fn->getVariablesUsedHere();
// filter nodes always have one input variable
TRI_ASSERT(varsUsedHere.size() == 1);
if (varsUsedHere[0]->id != _variable->id) {
break; // abort . . . FIXME is this the desired behaviour??
}
_toUnlink.insert(en);
return false; // continue . . .
}
case EN::ENUMERATE_COLLECTION: {
// check that we are enumerating the variable we are to remove
if (en->id() != _enumColl->id()) {
break; // abort . . . FIXME is this the desired behaviour??
}
_toUnlink.insert(en);
return true; // stop
}
case EN::SINGLETON:
case EN::CALCULATION:
case EN::ENUMERATE_LIST:
case EN::SUBQUERY:
case EN::AGGREGATE:
case EN::INSERT:
case EN::REPLACE:
case EN::UPDATE:
case EN::RETURN:
case EN::NORESULTS:
case EN::ILLEGAL:
case EN::LIMIT:
case EN::SORT:
case EN::INDEX_RANGE:{}
// if we meet any of the above, then we abort . . .
}
_toUnlink.clear();
return true;
}
};
int triagens::aql::undistributeRemoveAfterEnumColl (Optimizer* opt,
ExecutionPlan* plan,
Optimizer::Rule const* rule) {
std::vector<ExecutionNode*> nodes
= plan->findNodesOfType(triagens::aql::ExecutionNode::REMOVE, true);
std::unordered_set<ExecutionNode*> toUnlink;
for (auto n : nodes) {
RemoveToEnumCollFinder finder(plan, toUnlink);
n->walk(&finder);
}
bool modified = false;
if (!toUnlink.empty()) {
plan->unlinkNodes(toUnlink);
plan->findVarUsage();
modified = true;

View File

@ -123,6 +123,12 @@ namespace triagens {
int removeUnnecessaryRemoteScatter (Optimizer*, ExecutionPlan*, Optimizer::Rule const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief recognises that a RemoveNode can be moved to the shards.
////////////////////////////////////////////////////////////////////////////////
int undistributeRemoveAfterEnumColl (Optimizer*, ExecutionPlan*, Optimizer::Rule const*);
} // namespace aql
} // namespace triagens