mirror of https://gitee.com/bigwinds/arangodb
Moved the conditionFinder to a seperate file
This commit is contained in:
parent
6525755cc0
commit
180ffa74a3
|
@ -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:
|
||||
|
|
@ -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:
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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 \
|
||||
|
|
Loading…
Reference in New Issue