mirror of https://gitee.com/bigwinds/arangodb
safer casts for ExecutionNode types
This commit is contained in:
parent
89d68dd748
commit
27e985d5d0
|
@ -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());
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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() &&
|
||||
|
|
|
@ -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()};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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* {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -82,7 +82,7 @@ class SortNode : public ExecutionNode {
|
|||
|
||||
cloneHelper(c, withDependencies, withProperties);
|
||||
|
||||
return static_cast<ExecutionNode*>(c);
|
||||
return ExecutionNode::castTo<ExecutionNode*>(c);
|
||||
}
|
||||
|
||||
/// @brief estimateCost
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue