1
0
Fork 0

safer casts for ExecutionNode types

This commit is contained in:
jsteemann 2018-05-10 20:08:37 +02:00
parent 89d68dd748
commit 27e985d5d0
24 changed files with 269 additions and 251 deletions

View File

@ -36,7 +36,7 @@ void SingletonBlock::deleteInputVariables() {
void SingletonBlock::buildWhitelist() {
if (!_whitelistBuilt) {
auto en = static_cast<SingletonNode const*>(getPlanNode());
auto en = ExecutionNode::castTo<SingletonNode const*>(getPlanNode());
auto const& registerPlan = en->getRegisterPlan()->varInfo;
std::unordered_set<Variable const*> const& varsUsedLater = en->getVarsUsedLater();
@ -435,7 +435,7 @@ AqlItemBlock* ReturnBlock::getSome(size_t atMost) {
size_t const n = res->size();
// Let's steal the actual result and throw away the vars:
auto ep = static_cast<ReturnNode const*>(getPlanNode());
auto ep = ExecutionNode::castTo<ReturnNode const*>(getPlanNode());
auto it = ep->getRegisterPlan()->varInfo.find(ep->_inVariable->id);
TRI_ASSERT(it != ep->getRegisterPlan()->varInfo.end());
RegisterId const registerId = it->second.registerId;
@ -485,7 +485,7 @@ RegisterId ReturnBlock::returnInheritedResults() {
DEBUG_BEGIN_BLOCK();
_returnInheritedResults = true;
auto ep = static_cast<ReturnNode const*>(getPlanNode());
auto ep = ExecutionNode::castTo<ReturnNode const*>(getPlanNode());
auto it = ep->getRegisterPlan()->varInfo.find(ep->_inVariable->id);
TRI_ASSERT(it != ep->getRegisterPlan()->varInfo.end());

View File

@ -102,7 +102,7 @@ void CalculationBlock::fillBlockWithReference(AqlItemBlock* result) {
/// @brief shared code for executing a simple or a V8 expression
void CalculationBlock::executeExpression(AqlItemBlock* result) {
DEBUG_BEGIN_BLOCK();
bool const hasCondition = (static_cast<CalculationNode const*>(_exeNode)
bool const hasCondition = (ExecutionNode::castTo<CalculationNode const*>(_exeNode)
->_conditionVariable != nullptr);
TRI_ASSERT(!hasCondition); // currently not implemented

View File

@ -1092,7 +1092,7 @@ size_t DistributeBlock::sendToClient(AqlItemBlock* cur) {
bool hasCreatedKeyAttribute = false;
if (input.isString() &&
static_cast<DistributeNode const*>(_exeNode)
ExecutionNode::castTo<DistributeNode const*>(_exeNode)
->_allowKeyConversionToObject) {
_keyBuilder.clear();
_keyBuilder.openObject(true);
@ -1113,7 +1113,7 @@ size_t DistributeBlock::sendToClient(AqlItemBlock* cur) {
TRI_ASSERT(value.isObject());
if (static_cast<DistributeNode const*>(_exeNode)->_createKeys) {
if (ExecutionNode::castTo<DistributeNode const*>(_exeNode)->_createKeys) {
bool buildNewObject = false;
// we are responsible for creating keys if none present

View File

@ -92,7 +92,7 @@ class RemoteNode final : public ExecutionNode {
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief estimateCost
@ -177,7 +177,7 @@ class ScatterNode : public ExecutionNode {
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief estimateCost
@ -246,7 +246,7 @@ class DistributeNode : public ExecutionNode {
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief getVariablesUsedHere, returning a vector
@ -342,7 +342,7 @@ class GatherNode final : public ExecutionNode {
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief estimateCost

View File

@ -518,10 +518,10 @@ void SortedCollectBlock::emitGroup(AqlItemBlock const* cur, AqlItemBlock* res,
if (_collectRegister != ExecutionNode::MaxRegisterId) {
_currentGroup.addValues(cur, _collectRegister);
if (static_cast<CollectNode const*>(_exeNode)->_count) {
if (ExecutionNode::castTo<CollectNode const*>(_exeNode)->_count) {
// only set group count in result register
res->emplaceValue(row, _collectRegister, AqlValueHintUInt(static_cast<uint64_t>(_currentGroup.groupLength)));
} else if (static_cast<CollectNode const*>(_exeNode)->_expressionVariable !=
} else if (ExecutionNode::castTo<CollectNode const*>(_exeNode)->_expressionVariable !=
nullptr) {
// copy expression result into result register
res->setValue(row, _collectRegister,
@ -589,7 +589,7 @@ HashedCollectBlock::HashedCollectBlock(ExecutionEngine* engine,
TRI_ASSERT(_aggregateRegisters.size() == en->_aggregateVariables.size());
if (en->_outVariable != nullptr) {
TRI_ASSERT(static_cast<CollectNode const*>(_exeNode)->_count);
TRI_ASSERT(ExecutionNode::castTo<CollectNode const*>(_exeNode)->_count);
auto const& registerPlan = en->getRegisterPlan()->varInfo;
auto it = registerPlan.find(en->_outVariable->id);
@ -598,7 +598,7 @@ HashedCollectBlock::HashedCollectBlock(ExecutionEngine* engine,
TRI_ASSERT(_collectRegister > 0 &&
_collectRegister < ExecutionNode::MaxRegisterId);
} else {
TRI_ASSERT(!static_cast<CollectNode const*>(_exeNode)->_count);
TRI_ASSERT(!ExecutionNode::castTo<CollectNode const*>(_exeNode)->_count);
}
TRI_ASSERT(!_groupRegisters.empty());
@ -625,7 +625,7 @@ int HashedCollectBlock::getOrSkipSome(size_t atMost,
_pos = 0; // this is in the first block
}
auto* en = static_cast<CollectNode const*>(_exeNode);
auto* en = ExecutionNode::castTo<CollectNode const*>(_exeNode);
// If we get here, we do have _buffer.front()
AqlItemBlock* cur = _buffer.front();

View File

@ -194,7 +194,7 @@ ExecutionNode* CollectNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief helper struct for finding variables

View File

@ -1148,7 +1148,7 @@ bool Condition::CanRemove(ExecutionPlan const* plan, ConditionPart const& me,
plan->getVarSetBy(static_cast<Variable const*>(node->getData())->id);
if (setter != nullptr &&
setter->getType() == ExecutionNode::CALCULATION) {
auto cn = static_cast<CalculationNode const*>(setter);
auto cn = ExecutionNode::castTo<CalculationNode const*>(setter);
// use expression node instead
node = cn->expression()->node();
}

View File

@ -79,7 +79,7 @@ bool ConditionFinder::before(ExecutionNode* en) {
case EN::SORT: {
// register which variables are used in a SORT
if (_sorts.empty()) {
for (auto& it : static_cast<SortNode const*>(en)->elements()) {
for (auto& it : ExecutionNode::castTo<SortNode const*>(en)->elements()) {
_sorts.emplace_back(it.var, it.ascending);
TRI_IF_FAILURE("ConditionFinder::sortNode") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
@ -95,7 +95,7 @@ bool ConditionFinder::before(ExecutionNode* en) {
_variableDefinitions.emplace(
outvars[0]->id,
static_cast<CalculationNode const*>(en)->expression()->node());
ExecutionNode::castTo<CalculationNode const*>(en)->expression()->node());
TRI_IF_FAILURE("ConditionFinder::variableDefinition") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
@ -103,7 +103,7 @@ bool ConditionFinder::before(ExecutionNode* en) {
}
case EN::ENUMERATE_COLLECTION: {
auto node = static_cast<EnumerateCollectionNode const*>(en);
auto node = ExecutionNode::castTo<EnumerateCollectionNode const*>(en);
if (_changes->find(node->id()) != _changes->end()) {
// already optimized this node
break;
@ -196,7 +196,7 @@ bool ConditionFinder::handleFilterCondition(
auto setter = _plan->getVarSetBy(variable->id);
if (setter != nullptr && setter->getType() == EN::CALCULATION) {
auto s = static_cast<CalculationNode*>(setter);
auto s = ExecutionNode::castTo<CalculationNode*>(setter);
auto filterExpression = s->expression();
AstNode* inNode = filterExpression->nodeForModification();
if (!inNode->canThrow() && inNode->isDeterministic() &&

View File

@ -96,7 +96,7 @@ void EngineInfoContainerDBServer::EngineInfo::connectQueryId(QueryId id) {
void EngineInfoContainerDBServer::EngineInfo::addNode(ExecutionNode* node) {
switch (node->getType()) {
case ExecutionNode::ENUMERATE_COLLECTION: {
auto ecNode = static_cast<EnumerateCollectionNode*>(node);
auto ecNode = ExecutionNode::castTo<EnumerateCollectionNode*>(node);
if (ecNode->isRestricted()) {
TRI_ASSERT(_restrictedShard.empty());
_restrictedShard = ecNode->restrictedShard();
@ -104,7 +104,7 @@ void EngineInfoContainerDBServer::EngineInfo::addNode(ExecutionNode* node) {
break;
}
case ExecutionNode::INDEX: {
auto idxNode = static_cast<IndexNode*>(node);
auto idxNode = ExecutionNode::castTo<IndexNode*>(node);
if (idxNode->isRestricted()) {
TRI_ASSERT(_restrictedShard.empty());
_restrictedShard = idxNode->restrictedShard();
@ -116,7 +116,7 @@ void EngineInfoContainerDBServer::EngineInfo::addNode(ExecutionNode* node) {
case ExecutionNode::REMOVE:
case ExecutionNode::REPLACE:
case ExecutionNode::UPSERT: {
auto modNode = static_cast<ModificationNode*>(node);
auto modNode = ExecutionNode::castTo<ModificationNode*>(node);
if (modNode->isRestricted()) {
TRI_ASSERT(_restrictedShard.empty());
_restrictedShard = modNode->restrictedShard();
@ -175,7 +175,7 @@ void EngineInfoContainerDBServer::EngineInfo::serializeSnippet(
plan.increaseCounter(clone->getType());
if (current->getType() == ExecutionNode::REMOTE) {
auto rem = static_cast<RemoteNode*>(clone);
auto rem = ExecutionNode::castTo<RemoteNode*>(clone);
// update the remote node with the information about the query
rem->server("server:" + arangodb::ServerState::instance()->getId());
rem->ownName(id);
@ -234,7 +234,7 @@ void EngineInfoContainerDBServer::addNode(ExecutionNode* node) {
switch (node->getType()) {
case ExecutionNode::ENUMERATE_COLLECTION:
{
auto ecNode = static_cast<EnumerateCollectionNode*>(node);
auto ecNode = ExecutionNode::castTo<EnumerateCollectionNode*>(node);
auto col = ecNode->collection();
if (ecNode->isRestricted()) {
std::unordered_set<std::string> restrict{ecNode->restrictedShard()};
@ -247,7 +247,7 @@ void EngineInfoContainerDBServer::addNode(ExecutionNode* node) {
}
case ExecutionNode::INDEX:
{
auto idxNode = static_cast<IndexNode*>(node);
auto idxNode = ExecutionNode::castTo<IndexNode*>(node);
auto col = idxNode->collection();
if (idxNode->isRestricted()) {
std::unordered_set<std::string> restrict{idxNode->restrictedShard()};
@ -269,7 +269,7 @@ void EngineInfoContainerDBServer::addNode(ExecutionNode* node) {
case ExecutionNode::REPLACE:
case ExecutionNode::UPSERT:
{
auto modNode = static_cast<ModificationNode*>(node);
auto modNode = ExecutionNode::castTo<ModificationNode*>(node);
auto col = modNode->collection();
if (modNode->isRestricted()) {
std::unordered_set<std::string> restrict{modNode->restrictedShard()};

View File

@ -94,7 +94,7 @@ Result ExecutionEngine::createBlocks(
auto const nodeType = en->getType();
if (nodeType == ExecutionNode::REMOTE) {
remoteNode = static_cast<RemoteNode const*>(en);
remoteNode = ExecutionNode::castTo<RemoteNode const*>(en);
continue;
}
@ -216,7 +216,7 @@ struct Instanciator final : public WalkerWorker<ExecutionNode> {
if (en->getType() == ExecutionNode::TRAVERSAL ||
en->getType() == ExecutionNode::SHORTEST_PATH) {
// We have to prepare the options before we build the block
static_cast<GraphNode*>(en)->prepareOptions();
ExecutionNode::castTo<GraphNode*>(en)->prepareOptions();
}
// do we need to adjust the root node?
@ -376,7 +376,7 @@ struct CoordinatorInstanciator : public WalkerWorker<ExecutionNode> {
break;
case ExecutionNode::TRAVERSAL:
case ExecutionNode::SHORTEST_PATH:
_dbserverParts.addGraphNode(static_cast<GraphNode*>(en));
_dbserverParts.addGraphNode(ExecutionNode::castTo<GraphNode*>(en));
break;
default:
// Do nothing

View File

@ -55,48 +55,46 @@
using namespace arangodb::basics;
using namespace arangodb::aql;
static bool const Optional = true;
namespace {
/// @brief maximum register id that can be assigned.
/// this is used for assertions
RegisterId const ExecutionNode::MaxRegisterId = 1000;
/// @brief type names
std::unordered_map<int, std::string const> const ExecutionNode::TypeNames{
{static_cast<int>(SINGLETON), "SingletonNode"},
{static_cast<int>(ENUMERATE_COLLECTION), "EnumerateCollectionNode"},
{static_cast<int>(ENUMERATE_LIST), "EnumerateListNode"},
{static_cast<int>(INDEX), "IndexNode"},
{static_cast<int>(LIMIT), "LimitNode"},
{static_cast<int>(CALCULATION), "CalculationNode"},
{static_cast<int>(SUBQUERY), "SubqueryNode"},
{static_cast<int>(FILTER), "FilterNode"},
{static_cast<int>(SORT), "SortNode"},
{static_cast<int>(COLLECT), "CollectNode"},
{static_cast<int>(RETURN), "ReturnNode"},
{static_cast<int>(REMOVE), "RemoveNode"},
{static_cast<int>(INSERT), "InsertNode"},
{static_cast<int>(UPDATE), "UpdateNode"},
{static_cast<int>(REPLACE), "ReplaceNode"},
{static_cast<int>(REMOTE), "RemoteNode"},
{static_cast<int>(SCATTER), "ScatterNode"},
{static_cast<int>(DISTRIBUTE), "DistributeNode"},
{static_cast<int>(GATHER), "GatherNode"},
{static_cast<int>(NORESULTS), "NoResultsNode"},
{static_cast<int>(UPSERT), "UpsertNode"},
{static_cast<int>(TRAVERSAL), "TraversalNode"},
{static_cast<int>(SHORTEST_PATH), "ShortestPathNode"},
/// @brief NodeType to string mapping
std::unordered_map<int, std::string const> const typeNames{
{static_cast<int>(ExecutionNode::SINGLETON), "SingletonNode"},
{static_cast<int>(ExecutionNode::ENUMERATE_COLLECTION), "EnumerateCollectionNode"},
{static_cast<int>(ExecutionNode::ENUMERATE_LIST), "EnumerateListNode"},
{static_cast<int>(ExecutionNode::INDEX), "IndexNode"},
{static_cast<int>(ExecutionNode::LIMIT), "LimitNode"},
{static_cast<int>(ExecutionNode::CALCULATION), "CalculationNode"},
{static_cast<int>(ExecutionNode::SUBQUERY), "SubqueryNode"},
{static_cast<int>(ExecutionNode::FILTER), "FilterNode"},
{static_cast<int>(ExecutionNode::SORT), "SortNode"},
{static_cast<int>(ExecutionNode::COLLECT), "CollectNode"},
{static_cast<int>(ExecutionNode::RETURN), "ReturnNode"},
{static_cast<int>(ExecutionNode::REMOVE), "RemoveNode"},
{static_cast<int>(ExecutionNode::INSERT), "InsertNode"},
{static_cast<int>(ExecutionNode::UPDATE), "UpdateNode"},
{static_cast<int>(ExecutionNode::REPLACE), "ReplaceNode"},
{static_cast<int>(ExecutionNode::REMOTE), "RemoteNode"},
{static_cast<int>(ExecutionNode::SCATTER), "ScatterNode"},
{static_cast<int>(ExecutionNode::DISTRIBUTE), "DistributeNode"},
{static_cast<int>(ExecutionNode::GATHER), "GatherNode"},
{static_cast<int>(ExecutionNode::NORESULTS), "NoResultsNode"},
{static_cast<int>(ExecutionNode::UPSERT), "UpsertNode"},
{static_cast<int>(ExecutionNode::TRAVERSAL), "TraversalNode"},
{static_cast<int>(ExecutionNode::SHORTEST_PATH), "ShortestPathNode"},
#ifdef USE_IRESEARCH
{static_cast<int>(ENUMERATE_IRESEARCH_VIEW), "EnumerateViewNode"},
{static_cast<int>(SCATTER_IRESEARCH_VIEW), "ScatterViewNode"}
{static_cast<int>(ExecutionNode::ENUMERATE_IRESEARCH_VIEW), "EnumerateViewNode"},
{static_cast<int>(ExecutionNode::SCATTER_IRESEARCH_VIEW), "ScatterViewNode"}
#endif
};
} // namespace
/// @brief returns the type name of the node
std::string const& ExecutionNode::getTypeString() const {
auto it = TypeNames.find(static_cast<int>(getType()));
auto it = ::typeNames.find(static_cast<int>(getType()));
if (it != TypeNames.end()) {
if (it != ::typeNames.end()) {
return (*it).second;
}
@ -105,9 +103,9 @@ std::string const& ExecutionNode::getTypeString() const {
}
void ExecutionNode::validateType(int type) {
auto it = TypeNames.find(static_cast<int>(type));
auto it = ::typeNames.find(static_cast<int>(type));
if (it == TypeNames.end()) {
if (it == ::typeNames.end()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_NOT_IMPLEMENTED, "unknown TypeID");
}
}
@ -187,9 +185,9 @@ ExecutionNode* ExecutionNode::fromVPackFactory(
}
case COLLECT: {
Variable* expressionVariable =
Variable::varFromVPack(plan->getAst(), slice, "expressionVariable", Optional);
Variable::varFromVPack(plan->getAst(), slice, "expressionVariable", true);
Variable* outVariable =
Variable::varFromVPack(plan->getAst(), slice, "outVariable", Optional);
Variable::varFromVPack(plan->getAst(), slice, "outVariable", true);
// keepVariables
std::vector<Variable const*> keepVariables;
@ -540,7 +538,7 @@ void ExecutionNode::invalidateCost() {
// etc. are already virtual
if (dep->getType() == SUBQUERY) {
// invalid cost of subqueries, too
static_cast<SubqueryNode*>(dep)->getSubquery()->invalidateCost();
ExecutionNode::castTo<SubqueryNode*>(dep)->getSubquery()->invalidateCost();
}
}
}
@ -569,7 +567,7 @@ bool ExecutionNode::walk(WalkerWorker<ExecutionNode>& worker) {
// Now handle a subquery:
if (getType() == SUBQUERY) {
auto p = static_cast<SubqueryNode*>(this);
auto p = ExecutionNode::castTo<SubqueryNode*>(this);
auto subquery = p->getSubquery();
if (worker.enterSubquery(this, subquery)) {
@ -786,7 +784,7 @@ void ExecutionNode::planRegisters(ExecutionNode* super) {
walk(*v);
// Now handle the subqueries:
for (auto& s : v->subQueryNodes) {
auto sq = static_cast<SubqueryNode*>(s);
auto sq = ExecutionNode::castTo<SubqueryNode*>(s);
sq->getSubquery()->planRegisters(s);
}
v->reset();
@ -857,7 +855,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
RegisterId registerId = 1 + nrRegs.back();
nrRegs.emplace_back(registerId);
auto ep = static_cast<EnumerateCollectionNode const*>(en);
auto ep = ExecutionNode::castTo<EnumerateCollectionNode const*>(en);
TRI_ASSERT(ep != nullptr);
varInfo.emplace(ep->outVariable()->id, VarInfo(depth, totalNrRegs));
totalNrRegs++;
@ -873,7 +871,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
RegisterId registerId = 1 + nrRegs.back();
nrRegs.emplace_back(registerId);
auto ep = static_cast<IndexNode const*>(en);
auto ep = ExecutionNode::castTo<IndexNode const*>(en);
TRI_ASSERT(ep != nullptr);
varInfo.emplace(ep->outVariable()->id, VarInfo(depth, totalNrRegs));
totalNrRegs++;
@ -889,7 +887,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
RegisterId registerId = 1 + nrRegs.back();
nrRegs.emplace_back(registerId);
auto ep = static_cast<EnumerateListNode const*>(en);
auto ep = ExecutionNode::castTo<EnumerateListNode const*>(en);
TRI_ASSERT(ep != nullptr);
varInfo.emplace(ep->_outVariable->id, VarInfo(depth, totalNrRegs));
totalNrRegs++;
@ -899,7 +897,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
case ExecutionNode::CALCULATION: {
nrRegsHere[depth]++;
nrRegs[depth]++;
auto ep = static_cast<CalculationNode const*>(en);
auto ep = ExecutionNode::castTo<CalculationNode const*>(en);
TRI_ASSERT(ep != nullptr);
varInfo.emplace(ep->_outVariable->id, VarInfo(depth, totalNrRegs));
totalNrRegs++;
@ -909,7 +907,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
case ExecutionNode::SUBQUERY: {
nrRegsHere[depth]++;
nrRegs[depth]++;
auto ep = static_cast<SubqueryNode const*>(en);
auto ep = ExecutionNode::castTo<SubqueryNode const*>(en);
TRI_ASSERT(ep != nullptr);
varInfo.emplace(ep->_outVariable->id, VarInfo(depth, totalNrRegs));
totalNrRegs++;
@ -926,7 +924,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
RegisterId registerId = nrRegs.back();
nrRegs.emplace_back(registerId);
auto ep = static_cast<CollectNode const*>(en);
auto ep = ExecutionNode::castTo<CollectNode const*>(en);
for (auto const& p : ep->_groupVariables) {
// p is std::pair<Variable const*,Variable const*>
// and the first is the to be assigned output variable
@ -976,7 +974,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
RegisterId registerId = nrRegs.back();
nrRegs.emplace_back(registerId);
auto ep = static_cast<RemoveNode const*>(en);
auto ep = ExecutionNode::castTo<RemoveNode const*>(en);
if (ep->getOutVariableOld() != nullptr) {
nrRegsHere[depth]++;
nrRegs[depth]++;
@ -996,7 +994,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
RegisterId registerId = nrRegs.back();
nrRegs.emplace_back(registerId);
auto ep = static_cast<InsertNode const*>(en);
auto ep = ExecutionNode::castTo<InsertNode const*>(en);
if (ep->getOutVariableNew() != nullptr) {
nrRegsHere[depth]++;
nrRegs[depth]++;
@ -1016,7 +1014,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
RegisterId registerId = nrRegs.back();
nrRegs.emplace_back(registerId);
auto ep = static_cast<UpdateNode const*>(en);
auto ep = ExecutionNode::castTo<UpdateNode const*>(en);
if (ep->getOutVariableOld() != nullptr) {
nrRegsHere[depth]++;
nrRegs[depth]++;
@ -1045,7 +1043,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
RegisterId registerId = nrRegs.back();
nrRegs.emplace_back(registerId);
auto ep = static_cast<ReplaceNode const*>(en);
auto ep = ExecutionNode::castTo<ReplaceNode const*>(en);
if (ep->getOutVariableOld() != nullptr) {
nrRegsHere[depth]++;
nrRegs[depth]++;
@ -1072,7 +1070,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
RegisterId registerId = nrRegs.back();
nrRegs.emplace_back(registerId);
auto ep = static_cast<UpsertNode const*>(en);
auto ep = ExecutionNode::castTo<UpsertNode const*>(en);
if (ep->getOutVariableNew() != nullptr) {
nrRegsHere[depth]++;
nrRegs[depth]++;
@ -1097,7 +1095,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
case ExecutionNode::TRAVERSAL: {
depth++;
auto ep = static_cast<TraversalNode const*>(en);
auto ep = ExecutionNode::castTo<TraversalNode const*>(en);
TRI_ASSERT(ep != nullptr);
auto vars = ep->getVariablesSetHere();
nrRegsHere.emplace_back(static_cast<RegisterId>(vars.size()));
@ -1116,7 +1114,7 @@ void ExecutionNode::RegisterPlan::after(ExecutionNode* en) {
}
case ExecutionNode::SHORTEST_PATH: {
depth++;
auto ep = static_cast<ShortestPathNode const*>(en);
auto ep = ExecutionNode::castTo<ShortestPathNode const*>(en);
TRI_ASSERT(ep != nullptr);
auto vars = ep->getVariablesSetHere();
nrRegsHere.emplace_back(static_cast<RegisterId>(vars.size()));
@ -1375,7 +1373,7 @@ ExecutionNode* EnumerateCollectionNode::clone(ExecutionPlan* plan,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief the cost of an enumerate collection node is a multiple of the cost of
@ -1444,7 +1442,7 @@ ExecutionNode* EnumerateListNode::clone(ExecutionPlan* plan,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief the cost of an enumerate list node
@ -1464,7 +1462,7 @@ double EnumerateListNode::estimateCost(size_t& nrItems) const {
if (setter != nullptr) {
if (setter->getType() == ExecutionNode::CALCULATION) {
// list variable introduced by a calculation
auto expression = static_cast<CalculationNode*>(setter)->expression();
auto expression = ExecutionNode::castTo<CalculationNode*>(setter)->expression();
if (expression != nullptr) {
auto node = expression->node();
@ -1491,7 +1489,7 @@ double EnumerateListNode::estimateCost(size_t& nrItems) const {
}
} else if (setter->getType() == ExecutionNode::SUBQUERY) {
// length will be set by the subquery's cost estimator
static_cast<SubqueryNode const*>(setter)->getSubquery()->estimateCost(
ExecutionNode::castTo<SubqueryNode const*>(setter)->getSubquery()->estimateCost(
length);
}
}
@ -1598,7 +1596,7 @@ ExecutionNode* CalculationNode::clone(ExecutionPlan* plan,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief estimateCost
@ -1642,7 +1640,7 @@ bool SubqueryNode::isConst() {
return false;
}
auto expression = static_cast<CalculationNode const*>(setter)->expression();
auto expression = ExecutionNode::castTo<CalculationNode const*>(setter)->expression();
if (expression == nullptr) {
return false;
@ -1679,7 +1677,7 @@ ExecutionNode* SubqueryNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief whether or not the subquery is a data-modification operation
@ -1878,7 +1876,7 @@ ExecutionNode* FilterNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief estimateCost
@ -1936,7 +1934,7 @@ ExecutionNode* ReturnNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief estimateCost

View File

@ -61,6 +61,8 @@
#include "VocBase/voc-types.h"
#include "VocBase/vocbase.h"
#include <type_traits>
namespace arangodb {
namespace velocypack {
class Builder;
@ -154,14 +156,32 @@ class ExecutionNode {
/// @brief constructor using a VPackSlice
ExecutionNode(ExecutionPlan* plan, arangodb::velocypack::Slice const& slice);
/// @brief destructor, free dependencies;
/// @brief destructor, free dependencies
virtual ~ExecutionNode() {}
public:
/// @brief factory from json.
/// @brief factory from JSON
static ExecutionNode* fromVPackFactory(ExecutionPlan* plan,
arangodb::velocypack::Slice const& slice);
/// @brief cast an ExecutionNode to a specific sub-type
/// in maintainer mode, this function will perform a dynamic_cast and abort the
/// program if the cast is invalid. in release mode, this function will perform
/// a static_cast and will not abort the program
template<typename T, typename FromType>
static inline T castTo(FromType node) noexcept {
static_assert(std::is_pointer<T>::value, "invalid type passed into ExecutionNode::castTo");
static_assert(node->IsExecutionNode, "invalid type passed into ExecutionNode::castTo");
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
T result = dynamic_cast<T>(node);
TRI_ASSERT(result != nullptr);
return result;
#else
return static_cast<T>(node);
#endif
}
/// @brief return the node's id
inline size_t id() const { return _id; }
@ -571,12 +591,12 @@ class ExecutionNode {
std::unordered_set<RegisterId> _regsToClear;
public:
/// @brief NodeType to string mapping
static std::unordered_map<int, std::string const> const TypeNames;
/// @brief maximum register id that can be assigned.
/// this is used for assertions
static RegisterId const MaxRegisterId;
static constexpr RegisterId MaxRegisterId = 1000;
/// @brief used as "type traits" for ExecutionNodes and derived classes
static constexpr bool IsExecutionNode = true;
};
/// @brief class SingletonNode
@ -612,7 +632,7 @@ class SingletonNode : public ExecutionNode {
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief the cost of a singleton is 1
@ -831,7 +851,7 @@ class LimitNode : public ExecutionNode {
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief estimateCost
@ -1265,7 +1285,7 @@ class NoResultsNode : public ExecutionNode {
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief the cost of a NoResults is 0

View File

@ -265,7 +265,7 @@ ExecutionPlan* ExecutionPlan::instantiateFromAst(Ast* ast) {
// insert fullCount flag
if (plan->_lastLimitNode != nullptr &&
ast->query()->queryOptions().fullCount) {
static_cast<LimitNode*>(plan->_lastLimitNode)->setFullCount();
ExecutionNode::castTo<LimitNode*>(plan->_lastLimitNode)->setFullCount();
}
plan->findVarUsage();
@ -574,14 +574,14 @@ SubqueryNode* ExecutionPlan::getSubqueryFromExpression(
return nullptr;
}
return static_cast<SubqueryNode*>((*it).second);
return ExecutionNode::castTo<SubqueryNode*>((*it).second);
}
/// @brief get the output variable from a node
Variable const* ExecutionPlan::getOutVariable(ExecutionNode const* node) const {
if (node->getType() == ExecutionNode::CALCULATION) {
// CalculationNode has an outVariale() method
return static_cast<CalculationNode const*>(node)->outVariable();
return ExecutionNode::castTo<CalculationNode const*>(node)->outVariable();
}
if (node->getType() == ExecutionNode::COLLECT) {
@ -591,7 +591,7 @@ Variable const* ExecutionPlan::getOutVariable(ExecutionNode const* node) const {
// so this will return the first result variable of the COLLECT
// this part of the code should only be called for anonymous COLLECT nodes,
// which only have one result variable
auto en = static_cast<CollectNode const*>(node);
auto en = ExecutionNode::castTo<CollectNode const*>(node);
auto const& vars = en->groupVariables();
TRI_ASSERT(vars.size() == 1);
@ -753,7 +753,7 @@ ExecutionNode* ExecutionPlan::registerNode(ExecutionNode* node) {
}
SubqueryNode* ExecutionPlan::registerSubquery(SubqueryNode* node) {
node = static_cast<SubqueryNode*>(registerNode(node));
node = ExecutionNode::castTo<SubqueryNode*>(registerNode(node));
_subqueries[node->outVariable()->id] = node;
return node;
}
@ -1048,7 +1048,7 @@ ExecutionNode* ExecutionPlan::fromNodeLet(ExecutionNode* previous,
}
en = registerNode(new SubqueryNode(this, nextId(), subquery, v));
_subqueries[static_cast<SubqueryNode*>(en)->outVariable()->id] = en;
_subqueries[ExecutionNode::castTo<SubqueryNode*>(en)->outVariable()->id] = en;
} else {
// check if the LET is a reference to a subquery
auto subquery = getSubqueryFromExpression(expression);
@ -2097,7 +2097,7 @@ ExecutionNode* ExecutionPlan::fromSlice(VPackSlice const& slice) {
auto subqueryNode = fromSlice(subquery);
// register the just created subquery
static_cast<SubqueryNode*>(ret)->setSubquery(subqueryNode, false);
ExecutionNode::castTo<SubqueryNode*>(ret)->setSubquery(subqueryNode, false);
}
}

View File

@ -145,7 +145,7 @@ arangodb::aql::AstNode* IndexBlock::makeUnique(
arangodb::aql::AstNode* node) const {
if (node->type != arangodb::aql::NODE_TYPE_ARRAY || node->numMembers() >= 2) {
// an non-array or an array with more than 1 member
auto en = static_cast<IndexNode const*>(getPlanNode());
auto en = ExecutionNode::castTo<IndexNode const*>(getPlanNode());
auto ast = en->_plan->getAst();
auto array = ast->createNodeArray();
array->addMember(node);
@ -177,7 +177,7 @@ void IndexBlock::executeExpressions() {
// the current incoming item:
AqlItemBlock* cur = _buffer.front();
auto en = static_cast<IndexNode const*>(getPlanNode());
auto en = ExecutionNode::castTo<IndexNode const*>(getPlanNode());
auto ast = en->_plan->getAst();
AstNode const* oldCondition = _condition;
AstNode* newCondition = ast->shallowCopyForModify(oldCondition);
@ -245,7 +245,7 @@ int IndexBlock::initialize() {
DEBUG_BEGIN_BLOCK();
int res = ExecutionBlock::initialize();
auto en = static_cast<IndexNode const*>(getPlanNode());
auto en = ExecutionNode::castTo<IndexNode const*>(getPlanNode());
auto ast = en->_plan->getAst();
// instantiate expressions:
@ -436,7 +436,7 @@ bool IndexBlock::initIndexes() {
}
}
}
IndexNode const* node = static_cast<IndexNode const*>(getPlanNode());
IndexNode const* node = ExecutionNode::castTo<IndexNode const*>(getPlanNode());
if (!node->options().ascending) {
_currentIndex = _indexes.size() - 1;
} else {
@ -485,7 +485,7 @@ void IndexBlock::createCursor() {
void IndexBlock::startNextCursor() {
DEBUG_BEGIN_BLOCK();
IndexNode const* node = static_cast<IndexNode const*>(getPlanNode());
IndexNode const* node = ExecutionNode::castTo<IndexNode const*>(getPlanNode());
if (!node->options().ascending) {
--_currentIndex;
_isLastIndex = (_currentIndex == 0);
@ -593,7 +593,7 @@ bool IndexBlock::readIndex(size_t atMost,
_allowCoveringIndexOptimization = _cursor->hasCovering();
if (_allowCoveringIndexOptimization &&
!static_cast<IndexNode const*>(_exeNode)->coveringIndexAttributePositions().empty()) {
!ExecutionNode::castTo<IndexNode const*>(_exeNode)->coveringIndexAttributePositions().empty()) {
// index covers all projections
res = _cursor->nextCovering(callback, atMost - _returned);
} else {
@ -845,7 +845,7 @@ arangodb::OperationCursor* IndexBlock::orderCursor(size_t currentIndex) {
// from _condition
if (!_nonConstExpressions.empty() || _cursors[currentIndex] == nullptr) {
// yet no cursor for index, so create it
IndexNode const* node = static_cast<IndexNode const*>(getPlanNode());
IndexNode const* node = ExecutionNode::castTo<IndexNode const*>(getPlanNode());
_cursors[currentIndex].reset(_trx->indexScanForCondition(
_indexes[currentIndex], conditionNode, node->outVariable(), _mmdr.get(),
node->_options));

View File

@ -248,7 +248,7 @@ ExecutionNode* IndexNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief destroy the IndexNode

View File

@ -100,7 +100,7 @@ AqlItemBlock* ModificationBlock::getSome(size_t atMost) {
// loop over input until it is exhausted
try {
if (static_cast<ModificationNode const*>(_exeNode)
if (ExecutionNode::castTo<ModificationNode const*>(_exeNode)
->_options.readCompleteInput) {
// read all input into a buffer first
while (true) {
@ -274,7 +274,7 @@ AqlItemBlock* RemoveBlock::work(std::vector<AqlItemBlock*>& blocks) {
std::unique_ptr<AqlItemBlock> result;
auto ep = static_cast<RemoveNode const*>(getPlanNode());
auto ep = ExecutionNode::castTo<RemoveNode const*>(getPlanNode());
auto it = ep->getRegisterPlan()->varInfo.find(ep->_inVariable->id);
TRI_ASSERT(it != ep->getRegisterPlan()->varInfo.end());
RegisterId const registerId = it->second.registerId;
@ -436,7 +436,7 @@ AqlItemBlock* InsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
std::unique_ptr<AqlItemBlock> result;
auto ep = static_cast<InsertNode const*>(getPlanNode());
auto ep = ExecutionNode::castTo<InsertNode const*>(getPlanNode());
auto it = ep->getRegisterPlan()->varInfo.find(ep->_inVariable->id);
TRI_ASSERT(it != ep->getRegisterPlan()->varInfo.end());
RegisterId const registerId = it->second.registerId;
@ -568,7 +568,7 @@ AqlItemBlock* UpdateBlock::work(std::vector<AqlItemBlock*>& blocks) {
return nullptr;
}
auto ep = static_cast<UpdateNode const*>(getPlanNode());
auto ep = ExecutionNode::castTo<UpdateNode const*>(getPlanNode());
auto it = ep->getRegisterPlan()->varInfo.find(ep->_inDocVariable->id);
TRI_ASSERT(it != ep->getRegisterPlan()->varInfo.end());
RegisterId const docRegisterId = it->second.registerId;
@ -782,7 +782,7 @@ AqlItemBlock* UpsertBlock::work(std::vector<AqlItemBlock*>& blocks) {
}
std::unique_ptr<AqlItemBlock> result;
auto ep = static_cast<UpsertNode const*>(getPlanNode());
auto ep = ExecutionNode::castTo<UpsertNode const*>(getPlanNode());
auto const& registerPlan = ep->getRegisterPlan()->varInfo;
auto it = ep->getRegisterPlan()->varInfo.find(ep->_inDocVariable->id);
@ -1033,7 +1033,7 @@ AqlItemBlock* ReplaceBlock::work(std::vector<AqlItemBlock*>& blocks) {
return nullptr;
}
auto ep = static_cast<ReplaceNode const*>(getPlanNode());
auto ep = ExecutionNode::castTo<ReplaceNode const*>(getPlanNode());
auto it = ep->getRegisterPlan()->varInfo.find(ep->_inDocVariable->id);
TRI_ASSERT(it != ep->getRegisterPlan()->varInfo.end());
RegisterId const docRegisterId = it->second.registerId;

View File

@ -141,7 +141,7 @@ ExecutionNode* RemoveNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
InsertNode::InsertNode(ExecutionPlan* plan, arangodb::velocypack::Slice const& base)
@ -192,7 +192,7 @@ ExecutionNode* InsertNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
UpdateNode::UpdateNode(ExecutionPlan* plan, arangodb::velocypack::Slice const& base)
@ -260,7 +260,7 @@ ExecutionNode* UpdateNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
ReplaceNode::ReplaceNode(ExecutionPlan* plan,
@ -329,7 +329,7 @@ ExecutionNode* ReplaceNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
UpsertNode::UpsertNode(ExecutionPlan* plan, arangodb::velocypack::Slice const& base)
@ -394,5 +394,5 @@ ExecutionNode* UpsertNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}

View File

@ -77,12 +77,12 @@ static int indexOf(std::vector<std::string> const& haystack, std::string const&
static aql::Collection const* getCollection(ExecutionNode const* node) {
switch (node->getType()) {
case EN::ENUMERATE_COLLECTION:
return static_cast<EnumerateCollectionNode const*>(node)->collection();
return ExecutionNode::castTo<EnumerateCollectionNode const*>(node)->collection();
case EN::INDEX:
return static_cast<IndexNode const*>(node)->collection();
return ExecutionNode::castTo<IndexNode const*>(node)->collection();
case EN::TRAVERSAL:
case EN::SHORTEST_PATH:
return static_cast<GraphNode const*>(node)->collection();
return ExecutionNode::castTo<GraphNode const*>(node)->collection();
default:
// note: modification nodes are not covered here yet
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "node type does not have a collection");
@ -156,7 +156,7 @@ std::string getSingleShardId(ExecutionPlan const* plan, ExecutionNode const* nod
builder.openObject();
if (setter->getType() == ExecutionNode::CALCULATION) {
CalculationNode const* c = static_cast<CalculationNode const*>(setter);
CalculationNode const* c = ExecutionNode::castTo<CalculationNode const*>(setter);
auto ex = c->expression();
if (ex == nullptr) {
@ -208,7 +208,7 @@ std::string getSingleShardId(ExecutionPlan const* plan, ExecutionNode const* nod
return std::string();
}
} else if (setter->getType() == ExecutionNode::INDEX) {
IndexNode const* c = static_cast<IndexNode const*>(setter);
IndexNode const* c = ExecutionNode::castTo<IndexNode const*>(setter);
if (c->getIndexes().size() != 1) {
// we can only handle a single index here
@ -332,7 +332,7 @@ void arangodb::aql::sortInValuesRule(Optimizer* opt,
// filter variable was introduced a CalculationNode. now check the
// expression
auto s = static_cast<CalculationNode*>(setter);
auto s = ExecutionNode::castTo<CalculationNode*>(setter);
auto filterExpression = s->expression();
auto* inNode = filterExpression->nodeForModification();
@ -396,7 +396,7 @@ void arangodb::aql::sortInValuesRule(Optimizer* opt,
if (setter->getType() == EN::CALCULATION) {
AstNode const* originalNode =
static_cast<CalculationNode*>(setter)->expression()->node();
ExecutionNode::castTo<CalculationNode*>(setter)->expression()->node();
TRI_ASSERT(originalNode != nullptr);
AstNode const* testNode = originalNode;
@ -433,7 +433,7 @@ void arangodb::aql::sortInValuesRule(Optimizer* opt,
originalArg = originalNode;
} else {
TRI_ASSERT(setter->getType() == EN::SUBQUERY);
auto sub = static_cast<SubqueryNode*>(setter);
auto sub = ExecutionNode::castTo<SubqueryNode*>(setter);
// estimate items in subquery
size_t nrItems = 0;
@ -479,7 +479,7 @@ void arangodb::aql::sortInValuesRule(Optimizer* opt,
// mark the original node as being removable, even if it can throw
// this is special as the optimizer will normally not remove any nodes
// if they throw - even when fully unused otherwise
static_cast<CalculationNode*>(setter)->canRemoveIfThrows(true);
ExecutionNode::castTo<CalculationNode*>(setter)->canRemoveIfThrows(true);
}
AstNode* clone = ast->clone(inNode);
@ -520,7 +520,7 @@ void arangodb::aql::removeRedundantSortsRule(
continue;
}
auto const sortNode = static_cast<SortNode*>(n);
auto const sortNode = ExecutionNode::castTo<SortNode*>(n);
auto sortInfo = sortNode->getSortInformation(plan.get(), &buffer);
@ -539,7 +539,7 @@ void arangodb::aql::removeRedundantSortsRule(
if (current->getType() == EN::SORT) {
// we found another sort. now check if they are compatible!
auto other = static_cast<SortNode*>(current)->getSortInformation(
auto other = ExecutionNode::castTo<SortNode*>(current)->getSortInformation(
plan.get(), &buffer);
switch (sortInfo.isCoveredBy(other)) {
@ -675,7 +675,7 @@ void arangodb::aql::removeUnnecessaryFiltersRule(
// filter variable was introduced a CalculationNode. now check the
// expression
auto s = static_cast<CalculationNode*>(setter);
auto s = ExecutionNode::castTo<CalculationNode*>(setter);
auto root = s->expression()->node();
TRI_ASSERT(root != nullptr);
@ -722,7 +722,7 @@ void arangodb::aql::removeCollectVariablesRule(
bool modified = false;
for (auto const& n : nodes) {
auto collectNode = static_cast<CollectNode*>(n);
auto collectNode = ExecutionNode::castTo<CollectNode*>(n);
TRI_ASSERT(collectNode != nullptr);
auto varsUsedLater = n->getVarsUsedLater();
@ -745,7 +745,7 @@ void arangodb::aql::removeCollectVariablesRule(
auto p = collectNode->getFirstParent();
while (p != nullptr) {
if (p->getType() == EN::CALCULATION) {
auto cc = static_cast<CalculationNode const*>(p);
auto cc = ExecutionNode::castTo<CalculationNode const*>(p);
Expression const* exp = cc->expression();
if (exp != nullptr && exp->node() != nullptr) {
bool isSafeForOptimization;
@ -824,14 +824,14 @@ class PropagateConstantAttributesHelper {
plan->findNodesOfType(nodes, EN::FILTER, true);
for (auto const& node : nodes) {
auto fn = static_cast<FilterNode*>(node);
auto fn = ExecutionNode::castTo<FilterNode*>(node);
auto inVar = fn->getVariablesUsedHere();
TRI_ASSERT(inVar.size() == 1);
auto setter = plan->getVarSetBy(inVar[0]->id);
if (setter != nullptr && setter->getType() == EN::CALCULATION) {
auto cn = static_cast<CalculationNode*>(setter);
auto cn = ExecutionNode::castTo<CalculationNode*>(setter);
auto expression = cn->expression();
if (expression != nullptr) {
@ -842,14 +842,14 @@ class PropagateConstantAttributesHelper {
if (!_constants.empty()) {
for (auto const& node : nodes) {
auto fn = static_cast<FilterNode*>(node);
auto fn = ExecutionNode::castTo<FilterNode*>(node);
auto inVar = fn->getVariablesUsedHere();
TRI_ASSERT(inVar.size() == 1);
auto setter = plan->getVarSetBy(inVar[0]->id);
if (setter != nullptr && setter->getType() == EN::CALCULATION) {
auto cn = static_cast<CalculationNode*>(setter);
auto cn = ExecutionNode::castTo<CalculationNode*>(setter);
auto expression = cn->expression();
if (expression != nullptr) {
@ -1045,7 +1045,7 @@ void arangodb::aql::moveCalculationsUpRule(Optimizer* opt,
std::unordered_set<Variable const*> neededVars;
for (auto const& n : nodes) {
auto nn = static_cast<CalculationNode*>(n);
auto nn = ExecutionNode::castTo<CalculationNode*>(n);
if (nn->expression()->canThrow() || !nn->expression()->isDeterministic()) {
// we will only move expressions up that cannot throw and that are
@ -1102,7 +1102,7 @@ void arangodb::aql::moveCalculationsDownRule(
bool modified = false;
for (auto const& n : nodes) {
auto nn = static_cast<CalculationNode*>(n);
auto nn = ExecutionNode::castTo<CalculationNode*>(n);
if (nn->expression()->canThrow() || !nn->expression()->isDeterministic()) {
// we will only move expressions down that cannot throw and that are
// deterministic
@ -1189,7 +1189,7 @@ void arangodb::aql::specializeCollectRule(Optimizer* opt,
bool modified = false;
for (auto const& n : nodes) {
auto collectNode = static_cast<CollectNode*>(n);
auto collectNode = ExecutionNode::castTo<CollectNode*>(n);
if (collectNode->isSpecialized()) {
// already specialized this node
@ -1242,7 +1242,7 @@ void arangodb::aql::specializeCollectRule(Optimizer* opt,
// use the cloned COLLECT node
auto newCollectNode =
static_cast<CollectNode*>(newPlan->getNodeById(collectNode->id()));
ExecutionNode::castTo<CollectNode*>(newPlan->getNodeById(collectNode->id()));
TRI_ASSERT(newCollectNode != nullptr);
// specialize the CollectNode so it will become a HashedCollectBlock
@ -1343,7 +1343,7 @@ void arangodb::aql::splitFiltersRule(Optimizer* opt,
continue;
}
auto cn = static_cast<CalculationNode*>(setter);
auto cn = ExecutionNode::castTo<CalculationNode*>(setter);
auto const expression = cn->expression();
if (expression->canThrow() || !expression->isDeterministic() ||
@ -1434,7 +1434,7 @@ void arangodb::aql::moveFiltersUpRule(Optimizer* opt,
if (current->getType() == EN::CALCULATION) {
// must not move a filter beyond a node with a non-deterministic result
auto calculation = static_cast<CalculationNode const*>(current);
auto calculation = ExecutionNode::castTo<CalculationNode const*>(current);
if (!calculation->expression()->isDeterministic()) {
break;
}
@ -1504,7 +1504,7 @@ class arangodb::aql::RedundantCalculationsReplacer final
}
void replaceInCalculation(ExecutionNode* en) {
auto node = static_cast<CalculationNode*>(en);
auto node = ExecutionNode::castTo<CalculationNode*>(en);
std::unordered_set<Variable const*> variables;
node->expression()->variables(variables);
@ -1552,7 +1552,7 @@ class arangodb::aql::RedundantCalculationsReplacer final
}
case EN::COLLECT: {
auto node = static_cast<CollectNode*>(en);
auto node = ExecutionNode::castTo<CollectNode*>(en);
for (auto& variable : node->_groupVariables) {
variable.second = Variable::replace(variable.second, _replacements);
}
@ -1579,7 +1579,7 @@ class arangodb::aql::RedundantCalculationsReplacer final
}
case EN::SORT: {
auto node = static_cast<SortNode*>(en);
auto node = ExecutionNode::castTo<SortNode*>(en);
for (auto& variable : node->_elements) {
variable.var = Variable::replace(variable.var, _replacements);
}
@ -1587,7 +1587,7 @@ class arangodb::aql::RedundantCalculationsReplacer final
}
case EN::GATHER: {
auto node = static_cast<GatherNode*>(en);
auto node = ExecutionNode::castTo<GatherNode*>(en);
for (auto& variable : node->_elements) {
auto v = Variable::replace(variable.var, _replacements);
if (v != variable.var) {
@ -1599,7 +1599,7 @@ class arangodb::aql::RedundantCalculationsReplacer final
}
case EN::DISTRIBUTE: {
auto node = static_cast<DistributeNode*>(en);
auto node = ExecutionNode::castTo<DistributeNode*>(en);
node->_variable = Variable::replace(node->_variable, _replacements);
node->_alternativeVariable = Variable::replace(node->_alternativeVariable, _replacements);
break;
@ -1616,7 +1616,7 @@ class arangodb::aql::RedundantCalculationsReplacer final
}
case EN::UPSERT: {
auto node = static_cast<UpsertNode*>(en);
auto node = ExecutionNode::castTo<UpsertNode*>(en);
if (node->_inDocVariable != nullptr) {
node->_inDocVariable =
@ -1634,7 +1634,7 @@ class arangodb::aql::RedundantCalculationsReplacer final
}
case EN::UPDATE: {
auto node = static_cast<UpdateNode*>(en);
auto node = ExecutionNode::castTo<UpdateNode*>(en);
if (node->_inDocVariable != nullptr) {
node->_inDocVariable =
@ -1648,7 +1648,7 @@ class arangodb::aql::RedundantCalculationsReplacer final
}
case EN::REPLACE: {
auto node = static_cast<ReplaceNode*>(en);
auto node = ExecutionNode::castTo<ReplaceNode*>(en);
if (node->_inDocVariable != nullptr) {
node->_inDocVariable =
@ -1693,7 +1693,7 @@ void arangodb::aql::removeRedundantCalculationsRule(
std::unordered_map<VariableId, Variable const*> replacements;
for (auto const& n : nodes) {
auto nn = static_cast<CalculationNode*>(n);
auto nn = ExecutionNode::castTo<CalculationNode*>(n);
if (!nn->expression()->isDeterministic()) {
// If this node is non-deterministic, we must not touch it!
@ -1724,8 +1724,8 @@ void arangodb::aql::removeRedundantCalculationsRule(
if (current->getType() == EN::CALCULATION) {
try {
//static_cast<CalculationNode*>(current)->expression()->node()->dump(0);
static_cast<CalculationNode*>(current)
//ExecutionNode::castTo<CalculationNode*>(current)->expression()->node()->dump(0);
ExecutionNode::castTo<CalculationNode*>(current)
->expression()
->stringifyIfNotTooLong(&buffer);
} catch (...) {
@ -1777,7 +1777,7 @@ void arangodb::aql::removeRedundantCalculationsRule(
}
if (current->getType() == EN::COLLECT) {
if (static_cast<CollectNode*>(current)->hasOutVariable()) {
if (ExecutionNode::castTo<CollectNode*>(current)->hasOutVariable()) {
// COLLECT ... INTO is evil (tm): it needs to keep all already defined
// variables
// we need to abort optimization here
@ -1821,7 +1821,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
for (auto const& n : nodes) {
if (n->getType() == EN::CALCULATION) {
auto nn = static_cast<CalculationNode*>(n);
auto nn = ExecutionNode::castTo<CalculationNode*>(n);
if (nn->canThrow() && !nn->canRemoveIfThrows()) {
// If this node can throw, we must not optimize it away!
@ -1829,7 +1829,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
}
// will remove calculation when we get here
} else if (n->getType() == EN::SUBQUERY) {
auto nn = static_cast<SubqueryNode*>(n);
auto nn = ExecutionNode::castTo<SubqueryNode*>(n);
if (nn->canThrow()) {
// subqueries that can throw must not be optimized away
@ -1859,12 +1859,12 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
// calculation easily
if (n->canThrow() ||
!static_cast<CalculationNode*>(n)->expression()->isDeterministic()) {
!ExecutionNode::castTo<CalculationNode*>(n)->expression()->isDeterministic()) {
continue;
}
AstNode const* rootNode =
static_cast<CalculationNode*>(n)->expression()->node();
ExecutionNode::castTo<CalculationNode*>(n)->expression()->node();
if (rootNode->type == NODE_TYPE_REFERENCE) {
// if the LET is a simple reference to another variable, e.g. LET a = b
@ -1876,7 +1876,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
// in this case we must not perform the replacements
while (current != nullptr) {
if (current->getType() == EN::COLLECT) {
if (static_cast<CollectNode const*>(current)->hasOutVariableButNoCount()) {
if (ExecutionNode::castTo<CollectNode const*>(current)->hasOutVariableButNoCount()) {
hasCollectWithOutVariable = true;
break;
}
@ -1907,7 +1907,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
current->getVariablesUsedHere(vars);
if (vars.find(outvars[0]) != vars.end()) {
if (current->getType() == EN::COLLECT) {
if (static_cast<CollectNode const*>(current)->hasOutVariableButNoCount()) {
if (ExecutionNode::castTo<CollectNode const*>(current)->hasOutVariableButNoCount()) {
// COLLECT with an INTO variable will collect all variables from
// the scope, so we shouldn't try to remove or change the meaning
// of variables
@ -1925,7 +1925,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(
// got a LET. we can replace the variable reference in it by
// something else
++usageCount;
other = static_cast<CalculationNode*>(current);
other = ExecutionNode::castTo<CalculationNode*>(current);
}
if (usageCount > 1) {
@ -2258,7 +2258,7 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
} else if (numCovered > 0 && sortCondition.isUnidirectional()) {
// remove the first few attributes if they are constant
SortNode* sortNode =
static_cast<SortNode*>(_plan->getNodeById(_sortNode->id()));
ExecutionNode::castTo<SortNode*>(_plan->getNodeById(_sortNode->id()));
sortNode->removeConditions(numCovered);
_modified = true;
}
@ -2292,7 +2292,7 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
_variableDefinitions.emplace(
outvars[0]->id,
static_cast<CalculationNode const*>(en)->expression()->node());
ExecutionNode::castTo<CalculationNode const*>(en)->expression()->node());
return false;
}
@ -2316,18 +2316,18 @@ struct SortToIndexNode final : public WalkerWorker<ExecutionNode> {
if (!_sorts.empty() || _sortNode != nullptr) {
return true; // a different SORT node. abort
}
_sortNode = static_cast<SortNode*>(en);
_sortNode = ExecutionNode::castTo<SortNode*>(en);
for (auto& it : _sortNode->elements()) {
_sorts.emplace_back(it.var, it.ascending);
}
return false;
case EN::INDEX:
return handleIndexNode(static_cast<IndexNode*>(en));
return handleIndexNode(ExecutionNode::castTo<IndexNode*>(en));
case EN::ENUMERATE_COLLECTION:
return handleEnumerateCollectionNode(
static_cast<EnumerateCollectionNode*>(en));
ExecutionNode::castTo<EnumerateCollectionNode*>(en));
default: {
// should not reach this point
@ -2348,7 +2348,7 @@ void arangodb::aql::useIndexForSortRule(Optimizer* opt,
bool modified = false;
for (auto const& n : nodes) {
auto sortNode = static_cast<SortNode*>(n);
auto sortNode = ExecutionNode::castTo<SortNode*>(n);
SortToIndexNode finder(plan.get());
sortNode->walk(finder);
@ -2373,7 +2373,7 @@ void arangodb::aql::removeFiltersCoveredByIndexRule(
bool modified = false;
for (auto const& node : nodes) {
auto fn = static_cast<FilterNode const*>(node);
auto fn = ExecutionNode::castTo<FilterNode const*>(node);
// find the node with the filter expression
auto inVar = fn->getVariablesUsedHere();
TRI_ASSERT(inVar.size() == 1);
@ -2384,7 +2384,7 @@ void arangodb::aql::removeFiltersCoveredByIndexRule(
continue;
}
auto calculationNode = static_cast<CalculationNode*>(setter);
auto calculationNode = ExecutionNode::castTo<CalculationNode*>(setter);
auto conditionNode = calculationNode->expression()->node();
// build the filter condition
@ -2407,7 +2407,7 @@ void arangodb::aql::removeFiltersCoveredByIndexRule(
auto current = node;
while (current != nullptr) {
if (current->getType() == EN::INDEX) {
auto indexNode = static_cast<IndexNode const*>(current);
auto indexNode = ExecutionNode::castTo<IndexNode const*>(current);
// found an index node, now check if the expression is covered by the
// index
@ -2785,7 +2785,7 @@ void arangodb::aql::optimizeClusterJoinsRule(Optimizer* opt,
if (keys1.size() == keys2.size()) {
// same number of shard keys... now check if the shard keys are all used
// and whether we only have equality joins
Condition const* condition = static_cast<IndexNode const*>(n)->condition();
Condition const* condition = ExecutionNode::castTo<IndexNode const*>(n)->condition();
if (condition != nullptr) {
AstNode const* root = condition->root();
@ -2925,7 +2925,7 @@ void arangodb::aql::scatterInClusterRule(Optimizer* opt,
plan->findNodesOfType(subs, ExecutionNode::SUBQUERY, true);
for (auto& it : subs) {
subqueries.emplace(static_cast<SubqueryNode const*>(it)->getSubquery(),
subqueries.emplace(ExecutionNode::castTo<SubqueryNode const*>(it)->getSubquery(),
it);
}
@ -2975,10 +2975,10 @@ void arangodb::aql::scatterInClusterRule(Optimizer* opt,
SortElementVector elements;
if (nodeType == ExecutionNode::ENUMERATE_COLLECTION) {
vocbase = static_cast<EnumerateCollectionNode const*>(node)->vocbase();
collection = static_cast<EnumerateCollectionNode const*>(node)->collection();
vocbase = ExecutionNode::castTo<EnumerateCollectionNode const*>(node)->vocbase();
collection = ExecutionNode::castTo<EnumerateCollectionNode const*>(node)->collection();
} else if (nodeType == ExecutionNode::INDEX) {
auto idxNode = static_cast<IndexNode const*>(node);
auto idxNode = ExecutionNode::castTo<IndexNode const*>(node);
vocbase = idxNode->vocbase();
collection = idxNode->collection();
TRI_ASSERT(collection != nullptr);
@ -3009,14 +3009,14 @@ void arangodb::aql::scatterInClusterRule(Optimizer* opt,
nodeType == ExecutionNode::REPLACE ||
nodeType == ExecutionNode::REMOVE ||
nodeType == ExecutionNode::UPSERT) {
vocbase = static_cast<ModificationNode*>(node)->vocbase();
collection = static_cast<ModificationNode*>(node)->collection();
vocbase = ExecutionNode::castTo<ModificationNode*>(node)->vocbase();
collection = ExecutionNode::castTo<ModificationNode*>(node)->collection();
if (nodeType == ExecutionNode::REMOVE ||
nodeType == ExecutionNode::UPDATE) {
// Note that in the REPLACE or UPSERT case we are not getting here,
// since the distributeInClusterRule fires and a DistributionNode is
// used.
auto* modNode = static_cast<ModificationNode*>(node);
auto* modNode = ExecutionNode::castTo<ModificationNode*>(node);
modNode->getOptions().ignoreDocumentNotFound = true;
}
} else {
@ -3070,7 +3070,7 @@ void arangodb::aql::scatterInClusterRule(Optimizer* opt,
auto it = subqueries.find(node);
if (it != subqueries.end()) {
static_cast<SubqueryNode*>((*it).second)->setSubquery(gatherNode, true);
ExecutionNode::castTo<SubqueryNode*>((*it).second)->setSubquery(gatherNode, true);
}
if (isRootNode) {
@ -3112,7 +3112,7 @@ void arangodb::aql::distributeInClusterRule(Optimizer* opt,
snode = nullptr;
root = plan->root();
} else {
snode = static_cast<SubqueryNode*>(subqueryNode);
snode = ExecutionNode::castTo<SubqueryNode*>(subqueryNode);
root = snode->getSubquery();
}
ExecutionNode* node = root;
@ -3154,7 +3154,7 @@ void arangodb::aql::distributeInClusterRule(Optimizer* opt,
if (node->getType() != EN::UPSERT &&
!node->isInInnerLoop() &&
!getSingleShardId(plan.get(), node, static_cast<ModificationNode const*>(node)->collection()).empty()) {
!getSingleShardId(plan.get(), node, ExecutionNode::castTo<ModificationNode const*>(node)->collection()).empty()) {
// no need to insert a DistributeNode for a single operation that is restricted to a single shard
continue;
}
@ -3179,7 +3179,7 @@ void arangodb::aql::distributeInClusterRule(Optimizer* opt,
nodeType == ExecutionNode::UPSERT);
Collection const* collection =
static_cast<ModificationNode*>(node)->collection();
ExecutionNode::castTo<ModificationNode*>(node)->collection();
#ifdef USE_ENTERPRISE
auto ci = ClusterInfo::instance();
@ -3230,7 +3230,7 @@ void arangodb::aql::distributeInClusterRule(Optimizer* opt,
}
// extract database from plan node
TRI_vocbase_t* vocbase = static_cast<ModificationNode*>(node)->vocbase();
TRI_vocbase_t* vocbase = ExecutionNode::castTo<ModificationNode*>(node)->vocbase();
// insert a distribute node
ExecutionNode* distNode = nullptr;
@ -3280,7 +3280,7 @@ void arangodb::aql::distributeInClusterRule(Optimizer* opt,
auto d = new DistributeNode(plan.get(), plan->nextId(), vocbase,
collection, v[0], v[1], true, true);
d->setAllowSpecifiedKeys(true);
distNode = static_cast<ExecutionNode*>(d);
distNode = ExecutionNode::castTo<ExecutionNode*>(d);
} else {
TRI_ASSERT(false);
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "logic error");
@ -3352,7 +3352,7 @@ void arangodb::aql::collectInClusterRule(Optimizer* opt,
auto const& deps = node->getDependencies();
TRI_ASSERT(deps.size() == 1);
auto collectNode = static_cast<CollectNode*>(node);
auto collectNode = ExecutionNode::castTo<CollectNode*>(node);
// look for next remote node
GatherNode* gatherNode = nullptr;
auto current = node->getFirstDependency();
@ -3372,7 +3372,7 @@ void arangodb::aql::collectInClusterRule(Optimizer* opt,
}
if (current->getType() == ExecutionNode::GATHER) {
gatherNode = static_cast<GatherNode*>(current);
gatherNode = ExecutionNode::castTo<GatherNode*>(current);
} else if (current->getType() == ExecutionNode::REMOTE) {
auto previous = current->getFirstDependency();
// now we are on a DB server
@ -3635,7 +3635,7 @@ void arangodb::aql::distributeFilternCalcToClusterRule(
case EN::CALCULATION:
// check if the expression can be executed on a DB server safely
if (!static_cast<CalculationNode const*>(inspectNode)->expression()->canRunOnDBServer()) {
if (!ExecutionNode::castTo<CalculationNode const*>(inspectNode)->expression()->canRunOnDBServer()) {
stopSearching = true;
break;
}
@ -3695,7 +3695,7 @@ void arangodb::aql::distributeSortToClusterRule(
for (auto& n : nodes) {
auto const& remoteNodeList = n->getDependencies();
auto gatherNode = static_cast<GatherNode*>(n);
auto gatherNode = ExecutionNode::castTo<GatherNode*>(n);
TRI_ASSERT(remoteNodeList.size() > 0);
auto rn = remoteNodeList[0];
@ -3748,7 +3748,7 @@ void arangodb::aql::distributeSortToClusterRule(
break;
case EN::SORT: {
auto thisSortNode = static_cast<SortNode*>(inspectNode);
auto thisSortNode = ExecutionNode::castTo<SortNode*>(inspectNode);
// remember our cursor...
parents = inspectNode->getParents();
@ -3833,7 +3833,7 @@ void arangodb::aql::removeUnnecessaryRemoteScatterRule(
}
if (node->getType() == EN::CALCULATION) {
auto calc = static_cast<CalculationNode const*>(node);
auto calc = ExecutionNode::castTo<CalculationNode const*>(node);
// check if the expression can be executed on a DB server safely
if (!calc->expression()->canRunOnDBServer()) {
canOptimize = false;
@ -3887,7 +3887,7 @@ class RestrictToSingleShardChecker final : public WalkerWorker<ExecutionNode> {
case EN::INDEX: {
// track usage of the collection
auto collection = static_cast<IndexNode const*>(en)->collection();
auto collection = ExecutionNode::castTo<IndexNode const*>(en)->collection();
std::string shardId = getSingleShardId(_plan, en, collection);
if (shardId.empty()) {
_shardsUsed[collection].emplace("all");
@ -3899,14 +3899,14 @@ class RestrictToSingleShardChecker final : public WalkerWorker<ExecutionNode> {
case EN::ENUMERATE_COLLECTION: {
// track usage of the collection
auto collection = static_cast<EnumerateCollectionNode const*>(en)->collection();
auto collection = ExecutionNode::castTo<EnumerateCollectionNode const*>(en)->collection();
_shardsUsed[collection].emplace("all");
break;
}
case EN::UPSERT: {
// track usage of the collection
auto collection = static_cast<ModificationNode const*>(en)->collection();
auto collection = ExecutionNode::castTo<ModificationNode const*>(en)->collection();
_shardsUsed[collection].emplace("all");
break;
}
@ -3915,7 +3915,7 @@ class RestrictToSingleShardChecker final : public WalkerWorker<ExecutionNode> {
case EN::REPLACE:
case EN::UPDATE:
case EN::REMOVE: {
auto collection = static_cast<ModificationNode const*>(en)->collection();
auto collection = ExecutionNode::castTo<ModificationNode const*>(en)->collection();
std::string shardId = getSingleShardId(_plan, en, collection);
if (shardId.empty()) {
_shardsUsed[collection].emplace("all");
@ -3976,24 +3976,24 @@ void arangodb::aql::restrictToSingleShardRule(
currentType == ExecutionNode::UPDATE ||
currentType == ExecutionNode::REPLACE ||
currentType == ExecutionNode::REMOVE) {
auto collection = static_cast<ModificationNode const*>(current)->collection();
auto collection = ExecutionNode::castTo<ModificationNode const*>(current)->collection();
std::string shardId = getSingleShardId(plan.get(), current, collection);
if (!shardId.empty()) {
wasModified = true;
// we are on a single shard. we must not ignore not-found documents now
auto* modNode = static_cast<ModificationNode*>(current);
auto* modNode = ExecutionNode::castTo<ModificationNode*>(current);
modNode->getOptions().ignoreDocumentNotFound = false;
modNode->restrictToShard(shardId);
}
break;
} else if (currentType == ExecutionNode::INDEX) {
auto collection = static_cast<IndexNode const*>(current)->collection();
auto collection = ExecutionNode::castTo<IndexNode const*>(current)->collection();
std::string shardId = getSingleShardId(plan.get(), current, collection);
if (!shardId.empty()) {
wasModified = true;
static_cast<IndexNode*>(current)->restrictToShard(shardId);
ExecutionNode::castTo<IndexNode*>(current)->restrictToShard(shardId);
}
break;
} else if (currentType == ExecutionNode::UPSERT ||
@ -4047,7 +4047,7 @@ class RemoveToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
}
// find the variable we are removing . . .
auto rn = static_cast<RemoveNode*>(en);
auto rn = ExecutionNode::castTo<RemoveNode*>(en);
auto varsToRemove = rn->getVariablesUsedHere();
// remove nodes always have one input variable
@ -4059,7 +4059,7 @@ class RemoveToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
if (_setter->getType() == EN::CALCULATION) {
// this should be an attribute access for _key
auto cn = static_cast<CalculationNode*>(_setter);
auto cn = ExecutionNode::castTo<CalculationNode*>(_setter);
auto expr = cn->expression();
if (expr->isAttributeAccess()) {
@ -4215,8 +4215,8 @@ class RemoveToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
// doesn't match the last filter node
break; // abort . . .
}
auto cn = static_cast<CalculationNode*>(en);
auto fn = static_cast<FilterNode*>(_lastNode);
auto cn = ExecutionNode::castTo<CalculationNode*>(en);
auto fn = ExecutionNode::castTo<FilterNode*>(_lastNode);
// check these are a Calc-Filter pair
if (cn->getVariablesSetHere()[0]->id !=
@ -4610,10 +4610,10 @@ void arangodb::aql::replaceOrWithInRule(Optimizer* opt,
continue;
}
auto fn = static_cast<FilterNode*>(n);
auto fn = ExecutionNode::castTo<FilterNode*>(n);
auto inVar = fn->getVariablesUsedHere();
auto cn = static_cast<CalculationNode*>(dep);
auto cn = ExecutionNode::castTo<CalculationNode*>(dep);
auto outVar = cn->getVariablesSetHere();
if (outVar.size() != 1 || outVar[0]->id != inVar[0]->id) {
@ -4797,10 +4797,10 @@ void arangodb::aql::removeRedundantOrRule(Optimizer* opt,
continue;
}
auto fn = static_cast<FilterNode*>(n);
auto fn = ExecutionNode::castTo<FilterNode*>(n);
auto inVar = fn->getVariablesUsedHere();
auto cn = static_cast<CalculationNode*>(dep);
auto cn = ExecutionNode::castTo<CalculationNode*>(dep);
auto outVar = cn->getVariablesSetHere();
if (outVar.size() != 1 || outVar[0]->id != inVar[0]->id) {
@ -4848,7 +4848,7 @@ void arangodb::aql::removeDataModificationOutVariablesRule(
plan->findNodesOfType(nodes, types, true);
for (auto const& n : nodes) {
auto node = static_cast<ModificationNode*>(n);
auto node = ExecutionNode::castTo<ModificationNode*>(n);
TRI_ASSERT(node != nullptr);
auto varsUsedLater = n->getVarsUsedLater();
@ -4883,7 +4883,7 @@ void arangodb::aql::patchUpdateStatementsRule(
for (auto const& n : nodes) {
// we should only get through here a single time
auto node = static_cast<ModificationNode*>(n);
auto node = ExecutionNode::castTo<ModificationNode*>(n);
TRI_ASSERT(node != nullptr);
auto& options = node->getOptions();
@ -4907,7 +4907,7 @@ void arangodb::aql::patchUpdateStatementsRule(
}
if (type == EN::ENUMERATE_COLLECTION) {
auto collectionNode = static_cast<EnumerateCollectionNode const*>(dep);
auto collectionNode = ExecutionNode::castTo<EnumerateCollectionNode const*>(dep);
if (collectionNode->collection() != collection) {
// different collection, not suitable
@ -4968,7 +4968,7 @@ void arangodb::aql::optimizeTraversalsRule(Optimizer* opt,
// first make a pass over all traversal nodes and remove unused
// variables from them
for (auto const& n : tNodes) {
TraversalNode* traversal = static_cast<TraversalNode*>(n);
TraversalNode* traversal = ExecutionNode::castTo<TraversalNode*>(n);
auto varsUsedLater = n->getVarsUsedLater();
@ -5023,7 +5023,7 @@ void arangodb::aql::removeFiltersCoveredByTraversal(Optimizer* opt, std::unique_
std::unordered_set<ExecutionNode*> toUnlink;
for (auto const& node : fNodes) {
auto fn = static_cast<FilterNode const*>(node);
auto fn = ExecutionNode::castTo<FilterNode const*>(node);
// find the node with the filter expression
auto inVar = fn->getVariablesUsedHere();
TRI_ASSERT(inVar.size() == 1);
@ -5033,7 +5033,7 @@ void arangodb::aql::removeFiltersCoveredByTraversal(Optimizer* opt, std::unique_
continue;
}
auto calculationNode = static_cast<CalculationNode*>(setter);
auto calculationNode = ExecutionNode::castTo<CalculationNode*>(setter);
auto conditionNode = calculationNode->expression()->node();
// build the filter condition
@ -5056,7 +5056,7 @@ void arangodb::aql::removeFiltersCoveredByTraversal(Optimizer* opt, std::unique_
auto current = node;
while (current != nullptr) {
if (current->getType() == EN::TRAVERSAL) {
auto traversalNode = static_cast<TraversalNode const*>(current);
auto traversalNode = ExecutionNode::castTo<TraversalNode const*>(current);
// found a traversal node, now check if the expression
// is covered by the traversal
@ -5131,7 +5131,7 @@ void arangodb::aql::removeTraversalPathVariable(Optimizer* opt,
// first make a pass over all traversal nodes and remove unused
// variables from them
for (auto const& n : tNodes) {
TraversalNode* traversal = static_cast<TraversalNode*>(n);
TraversalNode* traversal = ExecutionNode::castTo<TraversalNode*>(n);
auto varsUsedLater = n->getVarsUsedLater();
auto outVariable = traversal->pathOutVariable();
@ -5164,11 +5164,11 @@ void arangodb::aql::prepareTraversalsRule(Optimizer* opt,
// variables from them
for (auto const& n : tNodes) {
if (n->getType() == EN::TRAVERSAL) {
TraversalNode* traversal = static_cast<TraversalNode*>(n);
TraversalNode* traversal = ExecutionNode::castTo<TraversalNode*>(n);
traversal->prepareOptions();
} else {
TRI_ASSERT(n->getType() == EN::SHORTEST_PATH);
ShortestPathNode* spn = static_cast<ShortestPathNode*>(n);
ShortestPathNode* spn = ExecutionNode::castTo<ShortestPathNode*>(n);
spn->prepareOptions();
}
}
@ -5206,7 +5206,7 @@ void arangodb::aql::inlineSubqueriesRule(Optimizer* opt,
bool modified = false;
for (auto const& n : nodes) {
auto subqueryNode = static_cast<SubqueryNode*>(n);
auto subqueryNode = ExecutionNode::castTo<SubqueryNode*>(n);
if (subqueryNode->isModificationQuery()) {
// can't modify modifying subqueries
@ -5226,7 +5226,7 @@ void arangodb::aql::inlineSubqueriesRule(Optimizer* opt,
while (current != nullptr) {
if (current->getType() == EN::COLLECT) {
if (static_cast<CollectNode const*>(current)->hasOutVariable()) {
if (ExecutionNode::castTo<CollectNode const*>(current)->hasOutVariable()) {
eligible = false;
break;
}
@ -5257,7 +5257,7 @@ void arangodb::aql::inlineSubqueriesRule(Optimizer* opt,
}
// we're only interested in FOR loops...
auto listNode = static_cast<EnumerateListNode*>(current);
auto listNode = ExecutionNode::castTo<EnumerateListNode*>(current);
// ...that use our subquery as its input
if (listNode->inVariable() == out) {
@ -5278,7 +5278,7 @@ void arangodb::aql::inlineSubqueriesRule(Optimizer* opt,
}
TRI_ASSERT(!subNodes.empty());
auto returnNode = static_cast<ReturnNode*>(subNodes[0]);
auto returnNode = ExecutionNode::castTo<ReturnNode*>(subNodes[0]);
TRI_ASSERT(returnNode->getType() == EN::RETURN);
modified = true;
@ -5397,7 +5397,7 @@ static bool applyFulltextOptimization(EnumerateListNode* elnode,
return false;
}
CalculationNode* calcNode = static_cast<CalculationNode*>(node);
CalculationNode* calcNode = ExecutionNode::castTo<CalculationNode*>(node);
Expression* expr = calcNode->expression();
// the expression must exist and it must have an astNode
if (expr->node() == nullptr) {
@ -5514,11 +5514,11 @@ void arangodb::aql::fulltextIndexRule(Optimizer* opt,
LimitNode* limit = nullptr; // maybe we have an existing LIMIT x,y
while (current) {
if (current->getType() == EN::ENUMERATE_LIST) {
EnumerateListNode* elnode = static_cast<EnumerateListNode*>(current);
EnumerateListNode* elnode = ExecutionNode::castTo<EnumerateListNode*>(current);
modified = modified || applyFulltextOptimization(elnode, limit, plan.get());
break;
} else if (current->getType() == EN::LIMIT) {
limit = static_cast<LimitNode*>(current);
limit = ExecutionNode::castTo<LimitNode*>(current);
}
current = current->getFirstDependency(); // inspect next node
}
@ -5748,7 +5748,7 @@ static bool checkDistanceFunc(ExecutionPlan* plan, AstNode const* funcNode,
if (setter == nullptr || setter->getType() != EN::CALCULATION) {
return false;
}
funcNode = static_cast<CalculationNode*>(setter)->expression()->node();
funcNode = ExecutionNode::castTo<CalculationNode*>(setter)->expression()->node();
}
// get the ast node of the expression
if (!funcNode || funcNode ->type != NODE_TYPE_FCALL || funcNode->numMembers() != 1) {
@ -5859,7 +5859,7 @@ static bool checkEnumerateListNode(ExecutionPlan* plan, EnumerateListNode* el, G
return false;
}
CalculationNode* calcNode = static_cast<CalculationNode*>(node);
CalculationNode* calcNode = ExecutionNode::castTo<CalculationNode*>(node);
Expression* expr = calcNode->expression();
// the expression must exist and it must have an astNode
if (expr == nullptr || expr->node() == nullptr) {
@ -5982,7 +5982,7 @@ static bool optimizeSortNode(ExecutionPlan* plan,
if (setter == nullptr || setter->getType() != EN::CALCULATION) {
return false; // setter could be enumerate list node e.g.
}
CalculationNode* calc = static_cast<CalculationNode*>(setter);
CalculationNode* calc = ExecutionNode::castTo<CalculationNode*>(setter);
Expression* expr = calc->expression();
if (expr == nullptr || expr->node() == nullptr) {
return false; // the expression must exist and must have an astNode
@ -6014,7 +6014,7 @@ static void optimizeFilterNode(ExecutionPlan* plan,
if (setter == nullptr || setter->getType() != EN::CALCULATION) {
return; // setter could be enumerate list node e.g.
}
CalculationNode* calc = static_cast<CalculationNode*>(setter);
CalculationNode* calc = ExecutionNode::castTo<CalculationNode*>(setter);
Expression* expr = calc->expression();
if (expr == nullptr || expr->node() == nullptr) {
return; // the expression must exist and must have an astNode
@ -6249,7 +6249,7 @@ void arangodb::aql::geoIndexRule(Optimizer* opt,
while (current) {
switch (current->getType()) {
case EN::SORT:
if (!optimizeSortNode(plan.get(), static_cast<SortNode*>(current), info)) {
if (!optimizeSortNode(plan.get(), ExecutionNode::castTo<SortNode*>(current), info)) {
// 1. EnumerateCollectionNode x
// 2. SortNode x.abc ASC
// 3. LimitNode n,m <-- cannot reuse LIMIT node here
@ -6257,10 +6257,10 @@ void arangodb::aql::geoIndexRule(Optimizer* opt,
}
break;
case EN::FILTER:
optimizeFilterNode(plan.get(), static_cast<FilterNode*>(current), info);
optimizeFilterNode(plan.get(), ExecutionNode::castTo<FilterNode*>(current), info);
break;
case EN::LIMIT: // collect this so we can use it
limit = static_cast<LimitNode*>(current);
limit = ExecutionNode::castTo<LimitNode*>(current);
break;
case EN::INDEX:
case EN::COLLECT:
@ -6269,7 +6269,7 @@ void arangodb::aql::geoIndexRule(Optimizer* opt,
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
case EN::ENUMERATE_LIST:
checkEnumerateListNode(plan.get(), static_cast<EnumerateListNode*>(current), info);
checkEnumerateListNode(plan.get(), ExecutionNode::castTo<EnumerateListNode*>(current), info);
// intentional fallthrough
#pragma GCC diagnostic pop
case EN::ENUMERATE_COLLECTION: {
@ -6302,7 +6302,7 @@ void arangodb::aql::replaceLegacyGeoFunctionsRule(Optimizer* opt,
Ast* ast = plan->getAst();
for (ExecutionNode* en : nodes) {
TRI_ASSERT(en->getType() == EN::CALCULATION);
CalculationNode* originalCN = static_cast<CalculationNode*>(en);
CalculationNode* originalCN = ExecutionNode::castTo<CalculationNode*>(en);
AstNode* root = originalCN->expression()->nodeForModification();
auto visitor = [&](AstNode* node) -> AstNode* {

View File

@ -306,7 +306,7 @@ ExecutionNode* ShortestPathNode::clone(ExecutionPlan* plan,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
double ShortestPathNode::estimateCost(size_t& nrItems) const {

View File

@ -126,7 +126,7 @@ SortCondition::SortCondition(
} else if (_plan != nullptr) {
ExecutionNode const* n = _plan->getVarSetBy(variableId);
if (n != nullptr && n->getType() == ExecutionNode::CALCULATION) {
Expression const* exp = static_cast<CalculationNode const*>(n)->expression();
Expression const* exp = ExecutionNode::castTo<CalculationNode const*>(n)->expression();
if (exp != nullptr) {
rootNode = exp->node();
}

View File

@ -114,7 +114,7 @@ bool SortNode::simplify(ExecutionPlan* plan) {
if (setter != nullptr) {
if (setter->getType() == ExecutionNode::CALCULATION) {
// variable introduced by a calculation
auto expression = static_cast<CalculationNode*>(setter)->expression();
auto expression = ExecutionNode::castTo<CalculationNode*>(setter)->expression();
if (expression->isConstant()) {
// constant expression, remove it!
@ -158,7 +158,7 @@ SortInformation SortNode::getSortInformation(
if (setter->getType() == ExecutionNode::CALCULATION) {
// variable introduced by a calculation
auto expression = static_cast<CalculationNode*>(setter)->expression();
auto expression = ExecutionNode::castTo<CalculationNode*>(setter)->expression();
if (!expression->isDeterministic()) {
result.isDeterministic = false;

View File

@ -82,7 +82,7 @@ class SortNode : public ExecutionNode {
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief estimateCost

View File

@ -537,7 +537,7 @@ bool TraversalConditionFinder::before(ExecutionNode* en) {
}
case EN::CALCULATION: {
auto calcNode = static_cast<CalculationNode const*>(en);
auto calcNode = ExecutionNode::castTo<CalculationNode const*>(en);
Variable const* outVar = calcNode->outVariable();
if (_filterVariables.find(outVar->id) != _filterVariables.end()) {
// This calculationNode is directly part of a filter condition
@ -551,7 +551,7 @@ bool TraversalConditionFinder::before(ExecutionNode* en) {
}
case EN::TRAVERSAL: {
auto node = static_cast<TraversalNode*>(en);
auto node = ExecutionNode::castTo<TraversalNode*>(en);
if (_condition->isEmpty()) {
// No condition, no optimize
break;

View File

@ -474,7 +474,7 @@ ExecutionNode* TraversalNode::clone(ExecutionPlan* plan, bool withDependencies,
cloneHelper(c, withDependencies, withProperties);
return static_cast<ExecutionNode*>(c);
return ExecutionNode::castTo<ExecutionNode*>(c);
}
/// @brief the cost of a traversal node