1
0
Fork 0

Moved the conditionFinder to a seperate file

This commit is contained in:
Michael Hackstein 2015-09-24 14:16:25 +02:00
parent 6525755cc0
commit 180ffa74a3
4 changed files with 204 additions and 117 deletions

View File

@ -0,0 +1,121 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Condition finder, used to build up the Condition object
///
/// @file arangod/Aql/ConditionFinder.h
///
/// DISCLAIMER
///
/// Copyright 2010-2014 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "Aql/ConditionFinder.h"
#include "Aql/ExecutionPlan.h"
using namespace triagens::aql;
using EN = triagens::aql::ExecutionNode;
bool ConditionFinder::before (ExecutionNode* en) {
if (en->canThrow()) {
// something that can throw is not safe to optimize
_condition = nullptr;
return true;
}
switch (en->getType()) {
case EN::ENUMERATE_LIST:
case EN::AGGREGATE:
case EN::SCATTER:
case EN::DISTRIBUTE:
case EN::GATHER:
case EN::REMOTE:
case EN::SUBQUERY:
case EN::SORT:
case EN::INDEX_RANGE:
// in these cases we simply ignore the intermediate nodes, note
// that we have taken care of nodes that could throw exceptions
// above.
break;
case EN::SINGLETON:
case EN::INSERT:
case EN::REMOVE:
case EN::REPLACE:
case EN::UPDATE:
case EN::UPSERT:
case EN::RETURN:
case EN::NORESULTS:
case EN::ILLEGAL:
// in all these cases something is seriously wrong and we better abort
// fall-through intentional...
case EN::LIMIT:
// if we meet a limit node between a filter and an enumerate
// collection, we abort . . .
return true;
case EN::FILTER: {
std::vector<Variable const*>&& inVar = en->getVariablesUsedHere();
TRI_ASSERT(inVar.size() == 1);
// register which variable is used in a filter
_varIds.emplace(inVar[0]->id);
break;
}
case EN::CALCULATION: {
auto outvar = en->getVariablesSetHere();
TRI_ASSERT(outvar.size() == 1);
if (_varIds.find(outvar[0]->id) == _varIds.end()) {
// some non-interesting variable
break;
}
auto expression = static_cast<CalculationNode const*>(en)->expression()->node();
if (_condition == nullptr) {
// did not have any expression before. now save what we found
_condition = new Condition(_plan->getAst());
}
TRI_ASSERT(_condition != nullptr);
_condition->andCombine(expression);
break;
}
case EN::ENUMERATE_COLLECTION: {
// auto node = static_cast<EnumerateCollectionNode*>(en);
// auto var = node->getVariablesSetHere()[0]; // should only be 1
_condition->normalize(_plan);
_condition->findIndices(static_cast<EnumerateCollectionNode const*>(en));
break;
}
}
return false;
}
bool ConditionFinder::enterSubquery (ExecutionNode* super, ExecutionNode* sub) {
return false;
}
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -0,0 +1,79 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Condition finder, used to build up the Condition object
///
/// @file arangod/Aql/ConditionFinder.h
///
/// DISCLAIMER
///
/// Copyright 2010-2014 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGOD_AQL_CONDITION_FINDER_H
#define ARANGOD_AQL_CONDITION_FINDER 1
#include "Aql/Condition.h"
#include "Aql/ExecutionNode.h"
#include "Aql/WalkerWorker.h"
namespace triagens {
namespace aql {
////////////////////////////////////////////////////////////////////////////////
/// @brief condition finder
////////////////////////////////////////////////////////////////////////////////
class ConditionFinder : public WalkerWorker<ExecutionNode> {
public:
ConditionFinder (ExecutionPlan* plan,
Variable const* var)
: _plan(plan),
_condition(nullptr),
_varIds() {
_varIds.emplace(var->id);
};
~ConditionFinder () {
delete _condition;
}
bool before (ExecutionNode* en) override final;
bool enterSubquery (ExecutionNode* super, ExecutionNode* sub) final;
private:
ExecutionPlan* _plan;
Condition* _condition;
std::unordered_set<VariableId> _varIds;
};
}
}
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -27,7 +27,7 @@
#include "Aql/OptimizerRules.h"
#include "Aql/AggregationOptions.h"
#include "Aql/Condition.h"
#include "Aql/ConditionFinder.h"
#include "Aql/ExecutionEngine.h"
#include "Aql/ExecutionNode.h"
#include "Aql/Function.h"
@ -2027,119 +2027,6 @@ static RangeInfoMapVec* BuildRangeInfo (ExecutionPlan* plan,
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief condition finder
////////////////////////////////////////////////////////////////////////////////
class ConditionFinder : public WalkerWorker<ExecutionNode> {
public:
ConditionFinder (ExecutionPlan* plan,
Variable const* var)
: _plan(plan),
_condition(nullptr),
_varIds() {
_varIds.emplace(var->id);
};
~ConditionFinder () {
delete _condition;
}
bool before (ExecutionNode* en) override final {
if (en->canThrow()) {
// something that can throw is not safe to optimize
_condition = nullptr;
return true;
}
switch (en->getType()) {
case EN::ENUMERATE_LIST:
case EN::AGGREGATE:
case EN::SCATTER:
case EN::DISTRIBUTE:
case EN::GATHER:
case EN::REMOTE:
case EN::SUBQUERY:
case EN::SORT:
case EN::INDEX_RANGE:
// in these cases we simply ignore the intermediate nodes, note
// that we have taken care of nodes that could throw exceptions
// above.
break;
case EN::SINGLETON:
case EN::INSERT:
case EN::REMOVE:
case EN::REPLACE:
case EN::UPDATE:
case EN::UPSERT:
case EN::RETURN:
case EN::NORESULTS:
case EN::ILLEGAL:
// in all these cases something is seriously wrong and we better abort
// fall-through intentional...
case EN::LIMIT:
// if we meet a limit node between a filter and an enumerate
// collection, we abort . . .
return true;
case EN::FILTER: {
std::vector<Variable const*>&& inVar = en->getVariablesUsedHere();
TRI_ASSERT(inVar.size() == 1);
// register which variable is used in a filter
_varIds.emplace(inVar[0]->id);
break;
}
case EN::CALCULATION: {
auto outvar = en->getVariablesSetHere();
TRI_ASSERT(outvar.size() == 1);
if (_varIds.find(outvar[0]->id) == _varIds.end()) {
// some non-interesting variable
break;
}
auto expression = static_cast<CalculationNode const*>(en)->expression()->node();
if (_condition == nullptr) {
// did not have any expression before. now save what we found
_condition = new Condition(_plan->getAst());
}
TRI_ASSERT(_condition != nullptr);
_condition->andCombine(expression);
break;
}
case EN::ENUMERATE_COLLECTION: {
// auto node = static_cast<EnumerateCollectionNode*>(en);
// auto var = node->getVariablesSetHere()[0]; // should only be 1
_condition->normalize(_plan);
_condition->findIndices(static_cast<EnumerateCollectionNode const*>(en));
break;
}
}
return false;
}
bool enterSubquery (ExecutionNode* super, ExecutionNode* sub) final {
return false;
}
private:
ExecutionPlan* _plan;
Condition* _condition;
std::unordered_set<VariableId> _varIds;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief useIndex, try to use an index for filtering
////////////////////////////////////////////////////////////////////////////////
@ -2658,7 +2545,7 @@ class FilterToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
}
}
auto indexRangeNode = new IndexRangeNode(
std::unique_ptr<ExecutionNode> newNode(new IndexRangeNode(
_plan,
_plan->nextId(),
node->vocbase(),
@ -2667,9 +2554,8 @@ class FilterToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
idx,
indexOrCondition,
false
);
));
std::unique_ptr<ExecutionNode> newNode(indexRangeNode);
size_t place = node->id();
std::unordered_map<size_t, size_t>::iterator it = _changesPlaces.find(place);

View File

@ -32,6 +32,7 @@ arangod_libarangod_a_SOURCES = \
arangod/Aql/Collection.cpp \
arangod/Aql/CollectionScanner.cpp \
arangod/Aql/Condition.cpp \
arangod/Aql/ConditionFinder.cpp \
arangod/Aql/ClusterBlocks.cpp \
arangod/Aql/EnumerateCollectionBlock.cpp \
arangod/Aql/EnumerateListBlock.cpp \