diff --git a/arangod/Agency/Constituent.cpp b/arangod/Agency/Constituent.cpp index d817862146..ccb2b4e8e5 100644 --- a/arangod/Agency/Constituent.cpp +++ b/arangod/Agency/Constituent.cpp @@ -180,7 +180,7 @@ bool Constituent::logMatches(arangodb::consensus::index_t prevLogIndex, // entry, then we know that this or a later entry was // already committed by a majority and is therefore // set in stone. Therefore the check must return true - // here and this is correct behaviour. + // here and this is correct behavior. // The other case in which we do not have the log entry // is if it is so new that we have never heard about it // in this case we can safely return true here as well, diff --git a/arangod/Aql/AqlItemBlock.cpp b/arangod/Aql/AqlItemBlock.cpp index 376906d5ec..fbc05942f2 100644 --- a/arangod/Aql/AqlItemBlock.cpp +++ b/arangod/Aql/AqlItemBlock.cpp @@ -325,7 +325,7 @@ void AqlItemBlock::rescale(size_t nrItems, RegisterId nrRegs) { // _data.capacity() might have been more accurate. Now, _data.size() stays at // _data.capacity(), or at least, is never reduced. // So I decided for now to report the memory usage based on numEntries() only, - // to mimic the previous behaviour. I'm not sure whether it should stay this + // to mimic the previous behavior. I'm not sure whether it should stay this // way; because currently, we are tracking the memory we need, instead of the // memory we have. if (targetSize > _data.size()) { diff --git a/arangod/Aql/ExecutionBlockImpl.cpp b/arangod/Aql/ExecutionBlockImpl.cpp index e0e79ce64b..74e3da0c13 100644 --- a/arangod/Aql/ExecutionBlockImpl.cpp +++ b/arangod/Aql/ExecutionBlockImpl.cpp @@ -208,7 +208,7 @@ std::unique_ptr ExecutionBlockImpl::createOutputRow( return std::make_unique(newBlock, infos().getOutputRegisters(), infos().registersToKeep(), infos().registersToClear(), - OutputAqlItemRow::CopyRowBehaviour::DoNotCopyInputRows); + OutputAqlItemRow::CopyRowBehavior::DoNotCopyInputRows); } else { return std::make_unique(newBlock, infos().getOutputRegisters(), infos().registersToKeep(), @@ -377,7 +377,7 @@ std::pair ExecutionBlockImpl::initializeCursor "initializeCursor method!"); InitializeCursor::init(_executor, _rowFetcher, _infos); - // // use this with c++17 instead of specialisation below + // // use this with c++17 instead of specialization below // if constexpr (std::is_same_v) { // if (items != nullptr) { // _executor._inputRegisterValues.reset( diff --git a/arangod/Aql/IResearchViewOptimizerRules.cpp b/arangod/Aql/IResearchViewOptimizerRules.cpp index 971676d5e5..5aabd28e6d 100644 --- a/arangod/Aql/IResearchViewOptimizerRules.cpp +++ b/arangod/Aql/IResearchViewOptimizerRules.cpp @@ -30,6 +30,7 @@ #include "Aql/Function.h" #include "Aql/IResearchViewNode.h" #include "Aql/Optimizer.h" +#include "Aql/OptimizerRule.h" #include "Aql/Query.h" #include "Aql/SortCondition.h" #include "Aql/SortNode.h" @@ -268,7 +269,7 @@ namespace iresearch { /// @brief move filters and sort conditions into views void handleViewsRule(arangodb::aql::Optimizer* opt, std::unique_ptr plan, - arangodb::aql::OptimizerRule const* rule) { + arangodb::aql::OptimizerRule const& rule) { TRI_ASSERT(plan && plan->getAst() && plan->getAst()->query()); // ensure 'Optimizer::addPlan' will be called @@ -340,7 +341,7 @@ void handleViewsRule(arangodb::aql::Optimizer* opt, void scatterViewInClusterRule(arangodb::aql::Optimizer* opt, std::unique_ptr plan, - arangodb::aql::OptimizerRule const* rule) { + arangodb::aql::OptimizerRule const& rule) { TRI_ASSERT(arangodb::ServerState::instance()->isCoordinator()); bool wasModified = false; SmallVector::allocator_type::arena_type a; diff --git a/arangod/Aql/IResearchViewOptimizerRules.h b/arangod/Aql/IResearchViewOptimizerRules.h index 313b3582b7..0591d2f4d8 100644 --- a/arangod/Aql/IResearchViewOptimizerRules.h +++ b/arangod/Aql/IResearchViewOptimizerRules.h @@ -39,14 +39,14 @@ namespace iresearch { /// @brief move filters and sort conditions into views void handleViewsRule(arangodb::aql::Optimizer* opt, std::unique_ptr plan, - arangodb::aql::OptimizerRule const* rule); + arangodb::aql::OptimizerRule const& rule); /// @brief scatter view query in cluster /// this rule inserts scatter, gather and remote nodes so operations on sharded /// views void scatterViewInClusterRule(arangodb::aql::Optimizer* opt, std::unique_ptr plan, - arangodb::aql::OptimizerRule const* rule); + arangodb::aql::OptimizerRule const& rule); } // namespace iresearch } // namespace arangodb diff --git a/arangod/Aql/Optimizer.cpp b/arangod/Aql/Optimizer.cpp index b33fba2837..65188cd222 100644 --- a/arangod/Aql/Optimizer.cpp +++ b/arangod/Aql/Optimizer.cpp @@ -60,9 +60,9 @@ bool Optimizer::runOnlyRequiredRules(size_t extraPlans) const { // @brief add a plan to the optimizer void Optimizer::addPlan(std::unique_ptr plan, - OptimizerRule const* rule, bool wasModified, int newLevel) { + OptimizerRule const& rule, bool wasModified, int newLevel) { TRI_ASSERT(plan != nullptr); - TRI_ASSERT(&_currentRule->second.rule == rule); + TRI_ASSERT(_currentRule->second.rule.level == rule.level); plan->setValidity(true); @@ -75,10 +75,10 @@ void Optimizer::addPlan(std::unique_ptr plan, } if (wasModified) { - if (!rule->isHidden) { + if (!rule.isHidden()) { // register which rules modified / created the plan // hidden rules are excluded here - plan->addAppliedRule(static_cast(rule->level)); + plan->addAppliedRule(static_cast(rule.level)); } plan->clearVarUsageComputed(); @@ -149,20 +149,20 @@ int Optimizer::createPlans(std::unique_ptr plan, auto it = _currentRule; TRI_ASSERT(it != _rules.end()); - auto& rule = it->second.rule; + auto const& rule = it->second.rule; // skip over rules if we should // however, we don't want to skip those rules that will not create // additional plans if (!it->second.enabled || - (_runOnlyRequiredRules && rule.canCreateAdditionalPlans && rule.canBeDisabled)) { + (_runOnlyRequiredRules && rule.canCreateAdditionalPlans() && rule.canBeDisabled())) { // we picked a disabled rule or we have reached the max number of // plans and just skip this rule ++it; // move it to the next rule to be processed in the next // iteration _newPlans.push_back(std::move(p), it); // nothing to do, just keep it - if (!rule.isHidden) { + if (!rule.isHidden()) { ++_stats.rulesSkipped; } @@ -185,9 +185,9 @@ int Optimizer::createPlans(std::unique_ptr plan, // thus the rule must not have deleted the plan itself or add it // back to the optimizer p->setValidity(false); - rule.func(this, std::move(p), &rule); + rule.func(this, std::move(p), rule); - if (!rule.isHidden) { + if (!rule.isHidden()) { ++_stats.rulesExecuted; } } diff --git a/arangod/Aql/Optimizer.h b/arangod/Aql/Optimizer.h index ef1ab95160..e0437cce08 100644 --- a/arangod/Aql/Optimizer.h +++ b/arangod/Aql/Optimizer.h @@ -132,7 +132,7 @@ class Optimizer { QueryOptions const& queryOptions, bool estimateAllPlans); /// @brief add a plan to the optimizer - void addPlan(std::unique_ptr, OptimizerRule const*, bool, int newLevel = 0); + void addPlan(std::unique_ptr, OptimizerRule const&, bool wasModified, int newLevel = 0); void disableRule(int rule); diff --git a/arangod/Aql/OptimizerRule.h b/arangod/Aql/OptimizerRule.h index 00e7ea669c..c83a84b6b3 100644 --- a/arangod/Aql/OptimizerRule.h +++ b/arangod/Aql/OptimizerRule.h @@ -25,6 +25,8 @@ #include "Basics/Common.h" +#include + namespace arangodb { namespace aql { class ExecutionPlan; @@ -38,10 +40,49 @@ struct OptimizerRule; /// set the level of the appended plan to the largest level of rule /// that ought to be considered as done to indicate which rule is to be /// applied next. -typedef std::function, OptimizerRule const*)> RuleFunction; +typedef void (*RuleFunction)(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief type of an optimizer rule struct OptimizerRule { + enum class Flags : int { + Default = 0, + Hidden = 1, + ClusterOnly = 2, + CanBeDisabled = 4, + CanCreateAdditionalPlans = 8, + }; + + /// @brief helper for building flags + template + static std::underlying_type::type makeFlags(Flags flag, Args... args) { + return static_cast::type>(flag) + makeFlags(args...); + } + + static std::underlying_type::type makeFlags() { + return static_cast::type>(Flags::Default); + } + + /// @brief check a flag for the rule + bool hasFlag(Flags flag) const { + return ((flags & static_cast::type>(flag)) != 0); + } + + bool canBeDisabled() const { + return hasFlag(Flags::CanBeDisabled); + } + + bool isClusterOnly() const { + return hasFlag(Flags::ClusterOnly); + } + + bool isHidden() const { + return hasFlag(Flags::Hidden); + } + + bool canCreateAdditionalPlans() const { + return hasFlag(Flags::CanCreateAdditionalPlans); + } + /// @brief optimizer rules enum RuleLevel : int { // List all the rules in the system here: @@ -56,9 +97,6 @@ struct OptimizerRule { inlineSubqueriesRule, - // split and-combined filters into multiple smaller filters - splitFiltersRule, - /// simplify some conditions in CalculationNodes simplifyConditionsRule, @@ -197,7 +235,9 @@ struct OptimizerRule { // optimize queries in the cluster so that the entire query // gets pushed to a single server - optimizeClusterSingleShardRule, + // if applied, this rule will turn all other cluster rules off + // for the current plan + clusterOneShardRule, // make operations on sharded collections use distribute distributeInClusterRule, @@ -250,20 +290,15 @@ struct OptimizerRule { std::string name; RuleFunction func; RuleLevel const level; - bool const canCreateAdditionalPlans; - bool const canBeDisabled; - bool const isHidden; + std::underlying_type::type const flags; OptimizerRule() = delete; - OptimizerRule(std::string const& name, RuleFunction const& func, RuleLevel level, - bool canCreateAdditionalPlans, bool canBeDisabled, bool isHidden) + OptimizerRule(std::string const& name, RuleFunction const& func, RuleLevel level, std::underlying_type::type flags) : name(name), func(func), level(level), - canCreateAdditionalPlans(canCreateAdditionalPlans), - canBeDisabled(canBeDisabled), - isHidden(isHidden) {} + flags(flags) {} }; } // namespace aql diff --git a/arangod/Aql/OptimizerRules.cpp b/arangod/Aql/OptimizerRules.cpp index 8086358f51..cb2318cad9 100644 --- a/arangod/Aql/OptimizerRules.cpp +++ b/arangod/Aql/OptimizerRules.cpp @@ -840,7 +840,7 @@ Collection* addCollectionToQuery(Query* query, std::string const& cname, bool as /// @brief adds a SORT operation for IN right-hand side operands void arangodb::aql::sortInValuesRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::FILTER, true); @@ -1018,7 +1018,7 @@ void arangodb::aql::sortInValuesRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::SORT, true); @@ -1168,7 +1168,7 @@ void arangodb::aql::removeRedundantSortsRule(Optimizer* opt, /// - filters that are always false will be replaced by a NoResults node void arangodb::aql::removeUnnecessaryFiltersRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::FILTER, true); @@ -1227,7 +1227,7 @@ void arangodb::aql::removeUnnecessaryFiltersRule(Optimizer* opt, /// additionally remove all unused aggregate calculations from a COLLECT void arangodb::aql::removeCollectVariablesRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::COLLECT, true); @@ -1558,7 +1558,7 @@ class PropagateConstantAttributesHelper { /// @brief propagate constant attributes in FILTERs void arangodb::aql::propagateConstantAttributesRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { PropagateConstantAttributesHelper helper(plan.get()); helper.propagateConstants(); @@ -1571,7 +1571,7 @@ void arangodb::aql::propagateConstantAttributesRule(Optimizer* opt, /// avoid redundant calculations in inner loops void arangodb::aql::moveCalculationsUpRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::CALCULATION, true); @@ -1659,7 +1659,7 @@ void arangodb::aql::moveCalculationsUpRule(Optimizer* opt, /// FILTER and LIMIT operations void arangodb::aql::moveCalculationsDownRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::CALCULATION, true); @@ -1768,7 +1768,7 @@ void arangodb::aql::moveCalculationsDownRule(Optimizer* opt, /// this rule cannot be turned off (otherwise, the query result might be wrong!) void arangodb::aql::specializeCollectRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::COLLECT, true); @@ -1859,7 +1859,7 @@ void arangodb::aql::specializeCollectRule(Optimizer* opt, if (nodes.size() > 1) { // this will tell the optimizer to optimize the cloned plan with this // specific rule again - opt->addPlan(std::move(newPlan), rule, true, static_cast(rule->level - 1)); + opt->addPlan(std::move(newPlan), rule, true, static_cast(rule.level - 1)); } else { // no need to run this specific rule again on the cloned plan opt->addPlan(std::move(newPlan), rule, true); @@ -1904,79 +1904,13 @@ void arangodb::aql::specializeCollectRule(Optimizer* opt, opt->addPlan(std::move(plan), rule, modified); } -/// @brief split and-combined filters and break them into smaller parts -void arangodb::aql::splitFiltersRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { - SmallVector::allocator_type::arena_type a; - SmallVector nodes{a}; - plan->findNodesOfType(nodes, EN::FILTER, true); - - bool modified = false; - - for (auto const& n : nodes) { - auto fn = ExecutionNode::castTo(n); - auto setter = plan->getVarSetBy(fn->inVariable()->id); - - if (setter == nullptr || setter->getType() != EN::CALCULATION) { - continue; - } - - auto cn = ExecutionNode::castTo(setter); - auto const expression = cn->expression(); - - if (!expression->isDeterministic() || - expression->node()->type != NODE_TYPE_OPERATOR_BINARY_AND) { - continue; - } - - std::vector stack{expression->nodeForModification()}; - - while (!stack.empty()) { - auto current = stack.back(); - stack.pop_back(); - - if (current->type == NODE_TYPE_OPERATOR_BINARY_AND) { - stack.emplace_back(current->getMember(0)); - stack.emplace_back(current->getMember(1)); - } else { - modified = true; - - ExecutionNode* calculationNode = nullptr; - auto outVar = plan->getAst()->variables()->createTemporaryVariable(); - auto expression = new Expression(plan.get(), plan->getAst(), current); - try { - calculationNode = - new CalculationNode(plan.get(), plan->nextId(), expression, outVar); - } catch (...) { - delete expression; - throw; - } - plan->registerNode(calculationNode); - - plan->insertDependency(n, calculationNode); - - auto filterNode = new FilterNode(plan.get(), plan->nextId(), outVar); - plan->registerNode(filterNode); - - plan->insertDependency(n, filterNode); - } - } - - if (modified) { - plan->unlinkNode(n, false); - } - } - - opt->addPlan(std::move(plan), rule, modified); -} - /// @brief move filters up in the plan /// this rule modifies the plan in place /// filters are moved as far up in the plan as possible to make result sets /// as small as possible as early as possible /// filters are not pushed beyond limits void arangodb::aql::moveFiltersUpRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::FILTER, true); @@ -2293,7 +2227,7 @@ class arangodb::aql::RedundantCalculationsReplacer final /// @brief simplify conditions in CalculationNodes void arangodb::aql::simplifyConditionsRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::CALCULATION, true); @@ -2516,7 +2450,7 @@ void arangodb::aql::simplifyConditionsRule(Optimizer* opt, /// @brief fuse filter conditions that follow each other void arangodb::aql::fuseFiltersRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::FILTER, true); @@ -2606,7 +2540,7 @@ void arangodb::aql::fuseFiltersRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::CALCULATION, true); @@ -2732,7 +2666,7 @@ void arangodb::aql::removeRedundantCalculationsRule(Optimizer* opt, /// this modifies an existing plan in place void arangodb::aql::removeUnnecessaryCalculationsRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, ::removeUnnecessaryCalculationsNodeTypes, true); @@ -2903,7 +2837,7 @@ void arangodb::aql::removeUnnecessaryCalculationsRule(Optimizer* opt, /// @brief useIndex, try to use an index for filtering void arangodb::aql::useIndexesRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { // These are all the nodes where we start traversing (including all // subqueries) SmallVector::allocator_type::arena_type a; @@ -3370,7 +3304,7 @@ struct SortToIndexNode final : public WalkerWorker { }; void arangodb::aql::useIndexForSortRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::SORT, true); @@ -3394,7 +3328,7 @@ void arangodb::aql::useIndexForSortRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::FILTER, true); @@ -3477,7 +3411,7 @@ void arangodb::aql::removeFiltersCoveredByIndexRule(Optimizer* opt, handled = true; // pass the new plan into this rule again, to optimize even // further - newLevel = static_cast(rule->level - 1); + newLevel = static_cast(rule.level - 1); } } } @@ -3536,7 +3470,7 @@ static bool NextPermutationTuple(std::vector& data, std::vector& /// @brief interchange adjacent EnumerateCollectionNodes in all possible ways void arangodb::aql::interchangeAdjacentEnumerationsRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; @@ -3653,111 +3587,12 @@ void arangodb::aql::interchangeAdjacentEnumerationsRule(Optimizer* opt, opt->addPlan(std::move(plan), rule, false); } -/// @brief optimize queries in the cluster so that the entire query gets pushed -/// to a single server -#if 0 -void arangodb::aql::optimizeClusterSingleShardRule(Optimizer* opt, - std::unique_ptr plan, - OptimizerRule const* rule) { - TRI_ASSERT(arangodb::ServerState::instance()->isCoordinator()); - bool wasModified = false; - bool done = false; - - std::unordered_set responsibleServers; - auto collections = plan->getAst()->query()->collections(); - - for (auto const& it : *(collections->collections())) { - Collection* c = it.second; - TRI_ASSERT(c != nullptr); - - if (c->numberOfShards() != 1) { - // more than one shard for this collection - done = true; - break; - } - - size_t n = c->responsibleServers(responsibleServers); - - if (n != 1) { - // more than one responsible server for this collection - done = true; - break; - } - } - - if (done || responsibleServers.size() != 1) { - opt->addPlan(std::move(plan), rule, wasModified); - return; - } - - // we only found a single responsible server, and all collections involved - // have exactly one shard - // that means we can move the entire query onto that server - - // TODO: handle Traversals and ShortestPaths here! - // TODO: properly handle subqueries here - SmallVector::allocator_type::arena_type s; - SmallVector nodes{s}; - std::vector types = {ExecutionNode::TRAVERSAL, - ExecutionNode::K_SHORTEST_PATHS, - ExecutionNode::SHORTEST_PATH, - ExecutionNode::SUBQUERY}; - plan->findNodesOfType(nodes, types, true); - - bool hasIncompatibleNodes = !nodes.empty(); - - nodes.clear(); - types = {ExecutionNode::INDEX, ExecutionNode::ENUMERATE_COLLECTION, ExecutionNode::TRAVERSAL}; - plan->findNodesOfType(nodes, types, false); - - if (!nodes.empty() && !hasIncompatibleNodes) { - // turn off all other cluster optimization rules now as they are superfluous - //opt->disableRule(OptimizerRule::optimizeClusterJoinsRule); - opt->disableRule(OptimizerRule::distributeInClusterRule); - opt->disableRule(OptimizerRule::scatterInClusterRule); - opt->disableRule(OptimizerRule::distributeFilternCalcToClusterRule); - opt->disableRule(OptimizerRule::distributeSortToClusterRule); - opt->disableRule(OptimizerRule::removeUnnecessaryRemoteScatterRule); -#ifdef USE_ENTERPRISE - opt->disableRule(OptimizerRule::removeSatelliteJoinsRule); -#endif - opt->disableRule(OptimizerRule::undistributeRemoveAfterEnumCollRule); - - // get first collection from query - Collection const* c = ::getCollection(nodes[0]); - TRI_ASSERT(c != nullptr); - - auto& vocbase = plan->getAst()->query()->vocbase(); - ExecutionNode* rootNode = plan->root(); - - // insert a remote node - ExecutionNode* remoteNode = - new RemoteNode(plan.get(), plan->nextId(), &vocbase, "", "", ""); - - plan->registerNode(remoteNode); - remoteNode->addDependency(rootNode); - - // insert a gather node - auto const sortMode = GatherNode::evaluateSortMode(c->numberOfShards()); - - auto* gatherNode = new GatherNode(plan.get(), plan->nextId(), sortMode); - - plan->registerNode(gatherNode); - gatherNode->addDependency(remoteNode); - plan->root(gatherNode, true); - wasModified = true; - } - - opt->addPlan(std::move(plan), rule, wasModified); -} -#endif - /// @brief scatter operations in cluster /// this rule inserts scatter, gather and remote nodes so operations on sharded /// collections actually work /// it will change plans in place void arangodb::aql::scatterInClusterRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { TRI_ASSERT(arangodb::ServerState::instance()->isCoordinator()); bool wasModified = false; @@ -3922,7 +3757,7 @@ void arangodb::aql::scatterInClusterRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { TRI_ASSERT(arangodb::ServerState::instance()->isCoordinator()); bool wasModified = false; // we are a coordinator, we replace the root if it is a modification node @@ -4146,7 +3981,7 @@ void arangodb::aql::distributeInClusterRule(Optimizer* opt, } void arangodb::aql::collectInClusterRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { TRI_ASSERT(arangodb::ServerState::instance()->isCoordinator()); bool wasModified = false; @@ -4450,7 +4285,7 @@ void arangodb::aql::collectInClusterRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { bool modified = false; SmallVector::allocator_type::arena_type a; @@ -4603,7 +4438,7 @@ void arangodb::aql::distributeFilternCalcToClusterRule(Optimizer* opt, /// filters are not pushed beyond limits void arangodb::aql::distributeSortToClusterRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::GATHER, true); @@ -4712,7 +4547,7 @@ void arangodb::aql::distributeSortToClusterRule(Optimizer* opt, /// only a SingletonNode and possibly some CalculationNodes as dependencies void arangodb::aql::removeUnnecessaryRemoteScatterRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::REMOTE, true); @@ -4777,7 +4612,7 @@ void arangodb::aql::removeUnnecessaryRemoteScatterRule(Optimizer* opt, /// @brief try to restrict fragments to a single shard if possible void arangodb::aql::restrictToSingleShardRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { TRI_ASSERT(arangodb::ServerState::instance()->isCoordinator()); bool wasModified = false; @@ -5200,7 +5035,7 @@ class RemoveToEnumCollFinder final : public WalkerWorker { /// @brief recognizes that a RemoveNode can be moved to the shards. void arangodb::aql::undistributeRemoveAfterEnumCollRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::REMOVE, true); @@ -5502,7 +5337,7 @@ struct OrSimplifier { // when the OR conditions are present in the same FILTER node, and refer to the // same (single) attribute. void arangodb::aql::replaceOrWithInRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::FILTER, true); @@ -5676,7 +5511,7 @@ struct RemoveRedundantOr { void arangodb::aql::removeRedundantOrRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::FILTER, true); @@ -5729,7 +5564,7 @@ void arangodb::aql::removeRedundantOrRule(Optimizer* opt, /// if not required void arangodb::aql::removeDataModificationOutVariablesRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { bool modified = false; SmallVector::allocator_type::arena_type a; @@ -5804,7 +5639,7 @@ void arangodb::aql::removeDataModificationOutVariablesRule(Optimizer* opt, /// entire collection to operate in batches void arangodb::aql::patchUpdateStatementsRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { // no need to dive into subqueries here SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; @@ -5889,7 +5724,7 @@ void arangodb::aql::patchUpdateStatementsRule(Optimizer* opt, /// merges filter nodes into graph traversal nodes void arangodb::aql::optimizeTraversalsRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector tNodes{a}; plan->findNodesOfType(tNodes, EN::TRAVERSAL, true); @@ -5948,7 +5783,7 @@ void arangodb::aql::optimizeTraversalsRule(Optimizer* opt, // remove filter nodes already covered by a traversal void arangodb::aql::removeFiltersCoveredByTraversal(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector fNodes{a}; plan->findNodesOfType(fNodes, EN::FILTER, true); @@ -6059,7 +5894,7 @@ void arangodb::aql::removeFiltersCoveredByTraversal(Optimizer* opt, /// `removeFiltersCoveredByTraversal`. Should significantly reduce overhead void arangodb::aql::removeTraversalPathVariable(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector tNodes{a}; plan->findNodesOfType(tNodes, EN::TRAVERSAL, true); @@ -6086,7 +5921,7 @@ void arangodb::aql::removeTraversalPathVariable(Optimizer* opt, /// @brief prepares traversals for execution (hidden rule) void arangodb::aql::prepareTraversalsRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector tNodes{a}; plan->findNodesOfType(tNodes, EN::TRAVERSAL, true); @@ -6135,7 +5970,7 @@ void arangodb::aql::prepareTraversalsRule(Optimizer* opt, /// LET x = tmp.test /// RETURN x.a void arangodb::aql::inlineSubqueriesRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::SUBQUERY, true); @@ -6954,7 +6789,7 @@ static bool applyGeoOptimization(ExecutionPlan* plan, LimitNode* ln, } void arangodb::aql::geoIndexRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; bool mod = false; @@ -7015,7 +6850,7 @@ void arangodb::aql::geoIndexRule(Optimizer* opt, std::unique_ptr } void arangodb::aql::sortLimitRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; bool mod = false; @@ -7057,7 +6892,7 @@ void arangodb::aql::sortLimitRule(Optimizer* opt, std::unique_ptr void arangodb::aql::optimizeSubqueriesRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { bool modified = false; SmallVector::allocator_type::arena_type a; diff --git a/arangod/Aql/OptimizerRules.h b/arangod/Aql/OptimizerRules.h index 26e6fda8a1..9719bc6a11 100644 --- a/arangod/Aql/OptimizerRules.h +++ b/arangod/Aql/OptimizerRules.h @@ -40,98 +40,99 @@ struct Collection; Collection* addCollectionToQuery(Query* query, std::string const& cname, bool assert = true); /// @brief adds a SORT operation for IN right-hand side operands -void sortInValuesRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void sortInValuesRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief remove redundant sorts /// this rule modifies the plan in place: /// - sorts that are covered by earlier sorts will be removed void removeRedundantSortsRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief remove all unnecessary filters /// this rule modifies the plan in place: /// - filters that are always true are removed completely /// - filters that are always false will be replaced by a NoResults node void removeUnnecessaryFiltersRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief remove unused INTO variable from COLLECT, or unused aggregates void removeCollectVariablesRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief propagate constant attributes in FILTERs void propagateConstantAttributesRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief move calculations up in the plan /// this rule modifies the plan in place /// it aims to move up calculations as far up in the plan as possible, to /// avoid redundant calculations in inner loops -void moveCalculationsUpRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void moveCalculationsUpRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief move calculations down in the plan /// this rule modifies the plan in place /// it aims to move down calculations as far down in the plan as possible, /// beyond FILTER and LIMIT statements void moveCalculationsDownRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief determine the "right" type of CollectNode and /// add a sort node for each COLLECT (may be removed later) /// this rule cannot be turned off (otherwise, the query result might be wrong!) -void specializeCollectRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void specializeCollectRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief split and-combined filters and break them into smaller parts -void splitFiltersRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void splitFiltersRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief move filters up in the plan /// this rule modifies the plan in place /// filters are moved as far up in the plan as possible to make result sets /// as small as possible as early as possible /// filters are not pushed beyond limits -void moveFiltersUpRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void moveFiltersUpRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief simplify some conditions in CalculationNodes -void simplifyConditionsRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void simplifyConditionsRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief fuse filter conditions that follow each other -void fuseFiltersRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void fuseFiltersRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief remove redundant CalculationNodes void removeRedundantCalculationsRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief remove CalculationNodes and SubqueryNodes that are never needed void removeUnnecessaryCalculationsRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief useIndex, try to use an index for filtering -void useIndexesRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void useIndexesRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief try to use the index for sorting -void useIndexForSortRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void useIndexForSortRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief try to remove filters which are covered by indexes void removeFiltersCoveredByIndexRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief interchange adjacent EnumerateCollectionNodes in all possible ways void interchangeAdjacentEnumerationsRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief replace single document operations in cluster by special handling -void substituteClusterSingleDocumentOperations(Optimizer* opt, - std::unique_ptr plan, - OptimizerRule const* rule); +void substituteClusterSingleDocumentOperationsRule(Optimizer* opt, + std::unique_ptr plan, + OptimizerRule const&); +#ifdef USE_ENTERPRISE /// @brief optimize queries in the cluster so that the entire query gets pushed /// to a single server -void optimizeClusterSingleShardRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); +void clusterOneShardRule(Optimizer*, std::unique_ptr, OptimizerRule const&); +#endif /// @brief scatter operations in cluster - send all incoming rows to all remote /// clients -void scatterInClusterRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void scatterInClusterRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief distribute operations in cluster - send each incoming row to every /// remote client precisely once. This happens in queries like: @@ -141,7 +142,7 @@ void scatterInClusterRule(Optimizer*, std::unique_ptr, OptimizerR /// where coll2 is sharded by _key, but not if it is sharded by anything else. /// The collections coll1 and coll2 do not have to be distinct for this. void distributeInClusterRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); #ifdef USE_ENTERPRISE ExecutionNode* distributeInClusterRuleSmartEdgeCollection(ExecutionPlan*, SubqueryNode* snode, @@ -151,29 +152,29 @@ ExecutionNode* distributeInClusterRuleSmartEdgeCollection(ExecutionPlan*, Subque /// @brief remove scatter/gather and remote nodes for satellite collections void removeSatelliteJoinsRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); void smartJoinsRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); #endif /// @brief try to restrict fragments to a single shard if possible void restrictToSingleShardRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief move collect to the DB servers in cluster -void collectInClusterRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void collectInClusterRule(Optimizer*, std::unique_ptr, OptimizerRule const&); void distributeFilternCalcToClusterRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); void distributeSortToClusterRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief try to get rid of a RemoteNode->ScatterNode combination which has /// only a SingletonNode and possibly some CalculationNodes as dependencies void removeUnnecessaryRemoteScatterRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief this rule removes Remote-Gather-Scatter/Distribute-Remote nodes from /// plans arising from queries of the form: @@ -201,7 +202,7 @@ void removeUnnecessaryRemoteScatterRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief this rule replaces expressions of the type: /// x.val == 1 || x.val == 2 || x.val == 3 @@ -209,54 +210,54 @@ void undistributeRemoveAfterEnumCollRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void replaceOrWithInRule(Optimizer*, std::unique_ptr, OptimizerRule const&); -void removeRedundantOrRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void removeRedundantOrRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief remove $OLD and $NEW variables from data-modification statements /// if not required void removeDataModificationOutVariablesRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief patch UPDATE statement on single collection that iterates over the /// entire collection to operate in batches void patchUpdateStatementsRule(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); /// @brief optimizes away unused traversal output variables and /// merges filter nodes into graph traversal nodes void optimizeTraversalsRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule); + OptimizerRule const&); /// @brief removes filter nodes already covered by the traversal and removes /// unused variables void removeFiltersCoveredByTraversal(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule); + OptimizerRule const&); /// @brief removes redundant path variables, after applying /// `removeFiltersCoveredByTraversal`. Should significantly reduce overhead void removeTraversalPathVariable(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule); + OptimizerRule const&); /// @brief prepares traversals for execution (hidden rule) void prepareTraversalsRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule); + OptimizerRule const&); /// @brief moves simple subqueries one level higher -void inlineSubqueriesRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void inlineSubqueriesRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief replace FILTER and SORT containing DISTANCE function -void geoIndexRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void geoIndexRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief make sort node aware of limit to enable internal optimizations -void sortLimitRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void sortLimitRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief push LIMIT into subqueries, and simplify them -void optimizeSubqueriesRule(Optimizer*, std::unique_ptr, OptimizerRule const*); +void optimizeSubqueriesRule(Optimizer*, std::unique_ptr, OptimizerRule const&); /// @brief replace legacy JS functions in the plan. void replaceNearWithinFulltext(Optimizer*, std::unique_ptr, - OptimizerRule const*); + OptimizerRule const&); } // namespace aql } // namespace arangodb diff --git a/arangod/Aql/OptimizerRulesCluster.cpp b/arangod/Aql/OptimizerRulesCluster.cpp index a81bbac999..1d7c0f6713 100644 --- a/arangod/Aql/OptimizerRulesCluster.cpp +++ b/arangod/Aql/OptimizerRulesCluster.cpp @@ -179,7 +179,7 @@ void replaceNode(ExecutionPlan* plan, ExecutionNode* oldNode, ExecutionNode* new } bool substituteClusterSingleDocumentOperationsIndex(Optimizer* opt, ExecutionPlan* plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { bool modified = false; SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; @@ -275,7 +275,7 @@ bool substituteClusterSingleDocumentOperationsIndex(Optimizer* opt, ExecutionPla } bool substituteClusterSingleDocumentOperationsNoIndex(Optimizer* opt, ExecutionPlan* plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { bool modified = false; SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; @@ -388,8 +388,11 @@ bool substituteClusterSingleDocumentOperationsNoIndex(Optimizer* opt, ExecutionP } // namespace -void arangodb::aql::substituteClusterSingleDocumentOperations( - Optimizer* opt, std::unique_ptr plan, OptimizerRule const* rule) { +namespace arangodb { +namespace aql { + +void substituteClusterSingleDocumentOperationsRule( + Optimizer* opt, std::unique_ptr plan, OptimizerRule const& rule) { bool modified = false; for (auto const& fun : {&::substituteClusterSingleDocumentOperationsIndex, @@ -402,3 +405,6 @@ void arangodb::aql::substituteClusterSingleDocumentOperations( opt->addPlan(std::move(plan), rule, modified); } + +} +} diff --git a/arangod/Aql/OptimizerRulesFeature.cpp b/arangod/Aql/OptimizerRulesFeature.cpp index 2db38eefe6..14c91bbdc3 100644 --- a/arangod/Aql/OptimizerRulesFeature.cpp +++ b/arangod/Aql/OptimizerRulesFeature.cpp @@ -42,16 +42,10 @@ std::map OptimizerRulesFeature::_rules; // @brief lookup from rule name to rule level std::unordered_map> OptimizerRulesFeature::_ruleLookup; -constexpr bool CreatesAdditionalPlans = true; -constexpr bool DoesNotCreateAdditionalPlans = false; -constexpr bool CanBeDisabled = true; -constexpr bool CanNotBeDisabled = false; - OptimizerRulesFeature::OptimizerRulesFeature(application_features::ApplicationServer& server) : application_features::ApplicationFeature(server, "OptimizerRules") { setOptional(false); startsAfter("V8Phase"); - startsAfter("Aql"); } @@ -65,71 +59,59 @@ void OptimizerRulesFeature::unprepare() { /// @brief register a rule void OptimizerRulesFeature::registerRule(std::string const& name, RuleFunction func, OptimizerRule::RuleLevel level, - bool canCreateAdditionalPlans, - bool canBeDisabled, bool isHidden) { - if (_ruleLookup.find(name) != _ruleLookup.end()) { - // duplicate rule names are not allowed - THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, - "duplicate optimizer rule name"); + std::underlying_type::type flags) { + // duplicate rules are not allowed + TRI_ASSERT(_ruleLookup.find(name) == _ruleLookup.end()); + TRI_ASSERT(_rules.find(level) == _rules.end()); + + OptimizerRule rule(name, func, level, flags); + + if (rule.isClusterOnly() && !ServerState::instance()->isCoordinator()) { + // cluster-only rule... however, we are not a coordinator, so we can just + // ignore this rule + return; } - _ruleLookup.emplace(name, std::make_pair(level, canBeDisabled)); - - if (_rules.find(level) != _rules.end()) { - THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, - "duplicate optimizer rule level"); - } - - _rules.emplace(level, OptimizerRule(name, func, level, canCreateAdditionalPlans, - canBeDisabled, isHidden)); + _ruleLookup.emplace(name, std::make_pair(level, rule.canBeDisabled())); + _rules.emplace(level, std::move(rule)); } /// @brief set up the optimizer rules once and forever void OptimizerRulesFeature::addRules() { -// List all the rules in the system here: -// lower level values mean earlier rule execution + // List all the rules in the system here: + // lower level values mean earlier rule execution -// note that levels must be unique - -// "Pass 1": moving nodes "up" (potentially outside loops): -#if 0 - // rule not yet tested - registerRule("split-filters", - splitFiltersRule, - splitFiltersRule, - true); -#endif + // note that levels must be unique // determine the "right" type of CollectNode and // add a sort node for each COLLECT (may be removed later) // this rule cannot be turned off (otherwise, the query result might be // wrong!) - registerHiddenRule("specialize-collect", specializeCollectRule, - OptimizerRule::specializeCollectRule, - CreatesAdditionalPlans, CanNotBeDisabled); + registerRule("specialize-collect", specializeCollectRule, OptimizerRule::specializeCollectRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanCreateAdditionalPlans, OptimizerRule::Flags::Hidden)); // inline subqueries one level higher registerRule("inline-subqueries", inlineSubqueriesRule, OptimizerRule::inlineSubqueriesRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // move calculations up the dependency chain (to pull them out of // inner loops etc.) registerRule("move-calculations-up", moveCalculationsUpRule, OptimizerRule::moveCalculationsUpRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // move filters up the dependency chain (to make result sets as small // as possible as early as possible) registerRule("move-filters-up", moveFiltersUpRule, OptimizerRule::moveFiltersUpRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // simplify conditions registerRule("simplify-conditions", simplifyConditionsRule, OptimizerRule::simplifyConditionsRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // remove redundant calculations registerRule("remove-redundant-calculations", removeRedundantCalculationsRule, OptimizerRule::removeRedundantCalculationsRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); /// "Pass 2": try to remove redundant or unnecessary nodes @@ -138,60 +120,63 @@ void OptimizerRulesFeature::addRules() { // filters that are always false will be replaced with a NoResults node registerRule("remove-unnecessary-filters", removeUnnecessaryFiltersRule, OptimizerRule::removeUnnecessaryFiltersRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // remove calculations that are never necessary registerRule("remove-unnecessary-calculations", removeUnnecessaryCalculationsRule, OptimizerRule::removeUnnecessaryCalculationsRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // remove redundant sort blocks registerRule("remove-redundant-sorts", removeRedundantSortsRule, OptimizerRule::removeRedundantSortsRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // push limits into subqueries and simplify them - registerRule("optimize-subqueries", optimizeSubqueriesRule, OptimizerRule::optimizeSubqueriesRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("optimize-subqueries", optimizeSubqueriesRule, + OptimizerRule::optimizeSubqueriesRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); /// "Pass 3": interchange EnumerateCollection nodes in all possible ways /// this is level 500, please never let new plans from higher /// levels go back to this or lower levels! registerRule("interchange-adjacent-enumerations", interchangeAdjacentEnumerationsRule, OptimizerRule::interchangeAdjacentEnumerationsRule, - CreatesAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanCreateAdditionalPlans, OptimizerRule::Flags::CanBeDisabled)); // "Pass 4": moving nodes "up" (potentially outside loops) (second try): // move calculations up the dependency chain (to pull them out of // inner loops etc.) registerRule("move-calculations-up-2", moveCalculationsUpRule, OptimizerRule::moveCalculationsUpRule2, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // move filters up the dependency chain (to make result sets as small // as possible as early as possible) - registerRule("move-filters-up-2", moveFiltersUpRule, OptimizerRule::moveFiltersUpRule2, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("move-filters-up-2", moveFiltersUpRule, + OptimizerRule::moveFiltersUpRule2, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // merge filters into traversals - registerRule("optimize-traversals", optimizeTraversalsRule, OptimizerRule::optimizeTraversalsRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("optimize-traversals", optimizeTraversalsRule, + OptimizerRule::optimizeTraversalsRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // optimize unneccessary filters already applied by the traversal registerRule("remove-filter-covered-by-traversal", removeFiltersCoveredByTraversal, OptimizerRule::removeFiltersCoveredByTraversal, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // optimize unneccessary filters already applied by the traversal. Only ever // does something if previous rules remove all filters using the path variable registerRule("remove-redundant-path-var", removeTraversalPathVariable, OptimizerRule::removeTraversalPathVariable, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // prepare traversal info - registerHiddenRule("prepare-traversals", prepareTraversalsRule, - OptimizerRule::prepareTraversalsRule, - DoesNotCreateAdditionalPlans, CanNotBeDisabled); + registerRule("prepare-traversals", prepareTraversalsRule, + OptimizerRule::prepareTraversalsRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::Hidden)); /// "Pass 5": try to remove redundant or unnecessary nodes (second try) // remove filters from the query that are not necessary at all @@ -199,151 +184,159 @@ void OptimizerRulesFeature::addRules() { // filters that are always false will be replaced with a NoResults node registerRule("remove-unnecessary-filters-2", removeUnnecessaryFiltersRule, OptimizerRule::removeUnnecessaryFiltersRule2, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // remove redundant sort node registerRule("remove-redundant-sorts-2", removeRedundantSortsRule, OptimizerRule::removeRedundantSortsRule2, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // remove unused INTO variable from COLLECT, or unused aggregates registerRule("remove-collect-variables", removeCollectVariablesRule, OptimizerRule::removeCollectVariablesRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // remove unused out variables for data-modification queries registerRule("remove-data-modification-out-variables", removeDataModificationOutVariablesRule, OptimizerRule::removeDataModificationOutVariablesRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // propagate constant attributes in FILTERs registerRule("propagate-constant-attributes", propagateConstantAttributesRule, OptimizerRule::propagateConstantAttributesRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); /// "Pass 6": use indexes if possible for FILTER and/or SORT nodes // try to replace simple OR conditions with IN - registerRule("replace-or-with-in", replaceOrWithInRule, OptimizerRule::replaceOrWithInRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("replace-or-with-in", replaceOrWithInRule, + OptimizerRule::replaceOrWithInRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // try to remove redundant OR conditions registerRule("remove-redundant-or", removeRedundantOrRule, OptimizerRule::removeRedundantOrRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // try to find a filter after an enumerate collection and find indexes - registerRule("use-indexes", useIndexesRule, OptimizerRule::useIndexesRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("use-indexes", useIndexesRule, + OptimizerRule::useIndexesRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // try to remove filters which are covered by index ranges registerRule("remove-filter-covered-by-index", removeFiltersCoveredByIndexRule, OptimizerRule::removeFiltersCoveredByIndexRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // try to find sort blocks which are superseeded by indexes - registerRule("use-index-for-sort", useIndexForSortRule, OptimizerRule::useIndexForSortRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("use-index-for-sort", useIndexForSortRule, + OptimizerRule::useIndexForSortRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // sort in-values in filters (note: must come after // remove-filter-covered-by-index rule) - registerRule("sort-in-values", sortInValuesRule, OptimizerRule::sortInValuesRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("sort-in-values", sortInValuesRule, + OptimizerRule::sortInValuesRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // remove calculations that are never necessary registerRule("remove-unnecessary-calculations-2", removeUnnecessaryCalculationsRule, OptimizerRule::removeUnnecessaryCalculationsRule2, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // fuse multiple adjacent filters into one - registerRule("fuse-filters", fuseFiltersRule, OptimizerRule::fuseFiltersRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("fuse-filters", fuseFiltersRule, + OptimizerRule::fuseFiltersRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // finally, push calculations as far down as possible registerRule("move-calculations-down", moveCalculationsDownRule, OptimizerRule::moveCalculationsDownRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // patch update statements registerRule("patch-update-statements", patchUpdateStatementsRule, OptimizerRule::patchUpdateStatementsRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); registerRule("replace-function-with-index", replaceNearWithinFulltext, OptimizerRule::replaceNearWithinFulltext, - DoesNotCreateAdditionalPlans, CanNotBeDisabled); + OptimizerRule::makeFlags()); + // move filters and sort conditions into views registerRule("handle-arangosearch-views", arangodb::iresearch::handleViewsRule, OptimizerRule::handleArangoSearchViewsRule, - DoesNotCreateAdditionalPlans, CanNotBeDisabled); + OptimizerRule::makeFlags()); // remove FILTER DISTANCE(...) and SORT DISTANCE(...) - OptimizerRulesFeature::registerRule("geo-index-optimizer", geoIndexRule, - OptimizerRule::applyGeoIndexRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("geo-index-optimizer", geoIndexRule, + OptimizerRule::applyGeoIndexRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); // make sort node aware of subsequent limit statements for internal optimizations - OptimizerRulesFeature::registerRule("sort-limit", sortLimitRule, - OptimizerRule::applySortLimitRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); - - if (arangodb::ServerState::instance()->isCoordinator()) { - registerRule("optimize-cluster-single-document-operations", - substituteClusterSingleDocumentOperations, - OptimizerRule::substituteSingleDocumentOperations, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("sort-limit", sortLimitRule, + OptimizerRule::applySortLimitRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); #if 0 - registerRule("optimize-cluster-single-shard", optimizeClusterSingleShardRule, - OptimizerRule::optimizeClusterSingleShardRule, DoesNotCreateAdditionalPlans, CanBeDisabled); +#ifdef USE_ENTERPRISE + // must be the first cluster optimizer rule + registerRule("cluster-one-shard", clusterOneShardRule, + OptimizerRule::clusterOneShardRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled, OptimizerRule::Flags::ClusterOnly)); +#endif #endif - // distribute operations in cluster - registerRule("scatter-in-cluster", scatterInClusterRule, OptimizerRule::scatterInClusterRule, - DoesNotCreateAdditionalPlans, CanNotBeDisabled); + registerRule("optimize-cluster-single-document-operations", substituteClusterSingleDocumentOperationsRule, + OptimizerRule::substituteSingleDocumentOperations, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled, OptimizerRule::Flags::ClusterOnly)); - registerRule("distribute-in-cluster", distributeInClusterRule, - OptimizerRule::distributeInClusterRule, - DoesNotCreateAdditionalPlans, CanNotBeDisabled); + // distribute operations in cluster + registerRule("scatter-in-cluster", scatterInClusterRule, + OptimizerRule::scatterInClusterRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::ClusterOnly)); - registerRule("collect-in-cluster", collectInClusterRule, OptimizerRule::collectInClusterRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("distribute-in-cluster", distributeInClusterRule, + OptimizerRule::distributeInClusterRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::ClusterOnly)); - // distribute operations in cluster - registerRule("distribute-filtercalc-to-cluster", distributeFilternCalcToClusterRule, - OptimizerRule::distributeFilternCalcToClusterRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("collect-in-cluster", collectInClusterRule, + OptimizerRule::collectInClusterRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled, OptimizerRule::Flags::ClusterOnly)); - registerRule("distribute-sort-to-cluster", distributeSortToClusterRule, - OptimizerRule::distributeSortToClusterRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + // distribute operations in cluster + registerRule("distribute-filtercalc-to-cluster", distributeFilternCalcToClusterRule, + OptimizerRule::distributeFilternCalcToClusterRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled, OptimizerRule::Flags::ClusterOnly)); - registerRule("remove-unnecessary-remote-scatter", removeUnnecessaryRemoteScatterRule, - OptimizerRule::removeUnnecessaryRemoteScatterRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("distribute-sort-to-cluster", distributeSortToClusterRule, + OptimizerRule::distributeSortToClusterRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled, OptimizerRule::Flags::ClusterOnly)); - registerRule("undistribute-remove-after-enum-coll", undistributeRemoveAfterEnumCollRule, - OptimizerRule::undistributeRemoveAfterEnumCollRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("remove-unnecessary-remote-scatter", removeUnnecessaryRemoteScatterRule, + OptimizerRule::removeUnnecessaryRemoteScatterRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled, OptimizerRule::Flags::ClusterOnly)); + + registerRule("undistribute-remove-after-enum-coll", undistributeRemoveAfterEnumCollRule, + OptimizerRule::undistributeRemoveAfterEnumCollRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled, OptimizerRule::Flags::ClusterOnly)); #ifdef USE_ENTERPRISE - registerRule("remove-satellite-joins", removeSatelliteJoinsRule, - OptimizerRule::removeSatelliteJoinsRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); - - registerRule("smart-joins", smartJoinsRule, - OptimizerRule::smartJoinsRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); + registerRule("remove-satellite-joins", removeSatelliteJoinsRule, + OptimizerRule::removeSatelliteJoinsRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled, OptimizerRule::Flags::ClusterOnly)); + + registerRule("smart-joins", smartJoinsRule, + OptimizerRule::smartJoinsRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled, OptimizerRule::Flags::ClusterOnly)); #endif - // distribute view queries in cluster - registerRule("scatter-arangosearch-view-in-cluster", - arangodb::iresearch::scatterViewInClusterRule, - OptimizerRule::scatterIResearchViewInClusterRule, - DoesNotCreateAdditionalPlans, CanNotBeDisabled); + // distribute view queries in cluster + registerRule("scatter-arangosearch-view-in-cluster", arangodb::iresearch::scatterViewInClusterRule, + OptimizerRule::scatterIResearchViewInClusterRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::ClusterOnly)); - registerRule("restrict-to-single-shard", restrictToSingleShardRule, - OptimizerRule::restrictToSingleShardRule, - DoesNotCreateAdditionalPlans, CanBeDisabled); - } + registerRule("restrict-to-single-shard", restrictToSingleShardRule, + OptimizerRule::restrictToSingleShardRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled, OptimizerRule::Flags::ClusterOnly)); // finally add the storage-engine specific rules addStorageEngineRules(); @@ -409,7 +402,7 @@ void OptimizerRulesFeature::disableRule(std::string const& name, if (arangodb::velocypack::StringRef(p, size) == "all") { // disable all rules for (auto const& it : _rules) { - if (it.second.canBeDisabled) { + if (it.second.canBeDisabled()) { disabled.emplace(it.first); } } diff --git a/arangod/Aql/OptimizerRulesFeature.h b/arangod/Aql/OptimizerRulesFeature.h index c6b6ee27fb..3986236ed3 100644 --- a/arangod/Aql/OptimizerRulesFeature.h +++ b/arangod/Aql/OptimizerRulesFeature.h @@ -44,22 +44,15 @@ class OptimizerRulesFeature final : public application_features::ApplicationFeat static std::vector translateRules(std::vector const&); /// @brief translate a single rule - static char const* translateRule(int); + static char const* translateRule(int rule); /// @brief look up the ids of all disabled rules - static std::unordered_set getDisabledRuleIds(std::vector const&); + static std::unordered_set getDisabledRuleIds(std::vector const& names); /// @brief register a rule static void registerRule(std::string const& name, RuleFunction func, - OptimizerRule::RuleLevel level, bool canCreateAdditionalPlans, - bool canBeDisabled, bool isHidden = false); - - /// @brief register a hidden rule - static void registerHiddenRule(std::string const& name, RuleFunction const& func, - OptimizerRule::RuleLevel level, - bool canCreateAdditionalPlans, bool canBeDisabled) { - registerRule(name, func, level, canCreateAdditionalPlans, canBeDisabled, true); - } + OptimizerRule::RuleLevel level, + std::underlying_type::type flags); private: void addRules(); diff --git a/arangod/Aql/OptimizerRulesReplaceFunctions.cpp b/arangod/Aql/OptimizerRulesReplaceFunctions.cpp index 33a275a5fe..c86bd49fe9 100644 --- a/arangod/Aql/OptimizerRulesReplaceFunctions.cpp +++ b/arangod/Aql/OptimizerRulesReplaceFunctions.cpp @@ -552,7 +552,7 @@ AstNode* replaceFullText(AstNode* funAstNode, ExecutionNode* calcNode, Execution //! @brief replace legacy JS Functions with pure AQL void arangodb::aql::replaceNearWithinFulltext(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { bool modified = false; SmallVector::allocator_type::arena_type a; diff --git a/arangod/Aql/OutputAqlItemRow.cpp b/arangod/Aql/OutputAqlItemRow.cpp index 2ae7ecbdc8..8b02ee2306 100644 --- a/arangod/Aql/OutputAqlItemRow.cpp +++ b/arangod/Aql/OutputAqlItemRow.cpp @@ -38,14 +38,14 @@ OutputAqlItemRow::OutputAqlItemRow( std::shared_ptr const> outputRegisters, std::shared_ptr const> registersToKeep, std::shared_ptr const> registersToClear, - CopyRowBehaviour copyRowBehaviour) + CopyRowBehavior copyRowBehavior) : _block(std::move(block)), _baseIndex(0), _lastBaseIndex(0), _inputRowCopied(false), _lastSourceRow{CreateInvalidInputRowHint{}}, _numValuesWritten(0), - _doNotCopyInputRow(copyRowBehaviour == CopyRowBehaviour::DoNotCopyInputRows), + _doNotCopyInputRow(copyRowBehavior == CopyRowBehavior::DoNotCopyInputRows), _outputRegisters(std::move(outputRegisters)), _registersToKeep(std::move(registersToKeep)), _registersToClear(std::move(registersToClear)), diff --git a/arangod/Aql/OutputAqlItemRow.h b/arangod/Aql/OutputAqlItemRow.h index 3ca258b258..c33bc1bf65 100644 --- a/arangod/Aql/OutputAqlItemRow.h +++ b/arangod/Aql/OutputAqlItemRow.h @@ -44,14 +44,14 @@ struct AqlValue; */ class OutputAqlItemRow { public: - // TODO Implement this behaviour via a template parameter instead? - enum class CopyRowBehaviour { CopyInputRows, DoNotCopyInputRows }; + // TODO Implement this behavior via a template parameter instead? + enum class CopyRowBehavior { CopyInputRows, DoNotCopyInputRows }; explicit OutputAqlItemRow(SharedAqlItemBlockPtr block, std::shared_ptr const> outputRegisters, std::shared_ptr const> registersToKeep, std::shared_ptr const> registersToClear, - CopyRowBehaviour = CopyRowBehaviour::CopyInputRows); + CopyRowBehavior = CopyRowBehavior::CopyInputRows); OutputAqlItemRow(OutputAqlItemRow const&) = delete; OutputAqlItemRow& operator=(OutputAqlItemRow const&) = delete; diff --git a/arangod/Auth/User.cpp b/arangod/Auth/User.cpp index dd44184783..9fe8b0ad47 100644 --- a/arangod/Auth/User.cpp +++ b/arangod/Auth/User.cpp @@ -424,7 +424,7 @@ void auth::User::grantDatabase(std::string const& dbname, auth::Level level) { it->second._databaseAuthLevel = level; } else { // grantDatabase is not supposed to change any rights on the - // collection level code which relies on the old behaviour + // collection level code which relies on the old behavior // will need to be adjusted _dbAccess.emplace(dbname, DBAuthContext(level, CollLevelMap())); } diff --git a/arangod/Cluster/ClusterComm.cpp b/arangod/Cluster/ClusterComm.cpp index 49aab25a24..157bd49bb3 100644 --- a/arangod/Cluster/ClusterComm.cpp +++ b/arangod/Cluster/ClusterComm.cpp @@ -448,7 +448,7 @@ OperationID ClusterComm::getOperationID() { return TRI_NewTickServer(); } /// limit the time to send the initial request away. If `initTimeout` /// is negative (as for example in the default value), then `initTimeout` /// is taken to be the same as `timeout`. The idea behind the two timeouts -/// is to be able to specify correct behaviour for automatic failover. +/// is to be able to specify correct behavior for automatic failover. /// The idea is that if the initial request cannot be sent within /// `initTimeout`, one can retry after a potential failover. //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Cluster/ClusterComm.h b/arangod/Cluster/ClusterComm.h index fd11bd48f0..d824153377 100644 --- a/arangod/Cluster/ClusterComm.h +++ b/arangod/Cluster/ClusterComm.h @@ -246,7 +246,7 @@ struct ClusterCommResult { if (response == nullptr) { status = CL_COMM_ERROR; } else { - // mop: wow..this is actually the old behaviour :S + // mop: wow..this is actually the old behavior :S fromResponse(std::move(response)); } } @@ -255,14 +255,14 @@ struct ClusterCommResult { void fromResponse(std::unique_ptr response) { sendWasComplete = true; errorCode = TRI_ERROR_NO_ERROR; - // mop: simulate the old behaviour where the original request + // mop: simulate the old behavior where the original request // was sent to the recipient and was simply accepted. Then the backend would // do its work and send a request to the target containing the result of // that // operation in this request. This is mind boggling but this is how it used // to // work....now it gets even funnier: as the new system only does - // request => response we simulate the old behaviour now and fake a request + // request => response we simulate the old behavior now and fake a request // containing the body of our response // :snake: OPST_CIRCUS auto httpResponse = dynamic_cast(response.get()); diff --git a/arangod/Cluster/ClusterMethods.cpp b/arangod/Cluster/ClusterMethods.cpp index b97b375b0f..e2f9732f8e 100644 --- a/arangod/Cluster/ClusterMethods.cpp +++ b/arangod/Cluster/ClusterMethods.cpp @@ -2925,7 +2925,7 @@ std::vector> ClusterMethods::persistCollectio size_t replicationFactor = col->replicationFactor(); size_t numberOfShards = col->numberOfShards(); - // the default behaviour however is to bail out and inform the user + // the default behavior however is to bail out and inform the user // that the requested replicationFactor is not possible right now if (dbServers.size() < replicationFactor) { LOG_TOPIC("9ce2e", DEBUG, Logger::CLUSTER) diff --git a/arangod/Cluster/SynchronizeShard.cpp b/arangod/Cluster/SynchronizeShard.cpp index 33d0965f77..a4b4a74e73 100644 --- a/arangod/Cluster/SynchronizeShard.cpp +++ b/arangod/Cluster/SynchronizeShard.cpp @@ -868,7 +868,7 @@ bool SynchronizeShard::first() { auto sy = details->slice(); auto const endTime = system_clock::now(); - // Long shard sync initialisation + // Long shard sync initialization if (endTime - startTime > seconds(5)) { LOG_TOPIC("ca7e3", INFO, Logger::MAINTENANCE) << "synchronizeOneShard: long call to syncCollection for shard" diff --git a/arangod/ClusterEngine/ClusterCollection.h b/arangod/ClusterEngine/ClusterCollection.h index ca195eaab7..b8462faa68 100644 --- a/arangod/ClusterEngine/ClusterCollection.h +++ b/arangod/ClusterEngine/ClusterCollection.h @@ -167,7 +167,7 @@ class ClusterCollection final : public PhysicalCollection { private: void addIndex(std::shared_ptr idx); - // keep locks just to adhere to behaviour in other collections + // keep locks just to adhere to behavior in other collections mutable basics::ReadWriteLock _exclusiveLock; ClusterEngineType _engineType; velocypack::Builder _info; diff --git a/arangod/Graph/GraphOperations.h b/arangod/Graph/GraphOperations.h index 663fbab3c2..d38322b830 100644 --- a/arangod/Graph/GraphOperations.h +++ b/arangod/Graph/GraphOperations.h @@ -58,7 +58,7 @@ class GraphOperations { : _graph(graph_), _vocbase(vocbase) {} // TODO I added the complex result type for the get* methods to exactly - // reproduce (in the RestGraphHandler) the behaviour of the similar methods + // reproduce (in the RestGraphHandler) the behavior of the similar methods // in the RestDocumentHandler. A simpler type, e.g. ResultT, // would be preferable. diff --git a/arangod/Graph/KShortestPathsFinder.h b/arangod/Graph/KShortestPathsFinder.h index 77d21e3a39..36986cb2d5 100644 --- a/arangod/Graph/KShortestPathsFinder.h +++ b/arangod/Graph/KShortestPathsFinder.h @@ -68,7 +68,7 @@ class KShortestPathsFinder : public ShortestPathFinder { double _weight; // Where this path branched off the previous shortest path - // This is an optimisation because we only need to consider + // This is an optimization because we only need to consider // spur paths from after the branch point size_t _branchpoint; diff --git a/arangod/IResearch/IResearchFeature.cpp b/arangod/IResearch/IResearchFeature.cpp index b342c14386..f3ee9d5103 100644 --- a/arangod/IResearch/IResearchFeature.cpp +++ b/arangod/IResearch/IResearchFeature.cpp @@ -178,7 +178,7 @@ bool upgradeSingleServerArangoSearchView0_1( // In order to upgrade ArangoSearch views from version 0 to version 1 we need to // differentiate between single server and cluster, therefore we temporary set role in 'ServerState', // actually supplied by a user, only for the duration of task to avoid other upgrade tasks, that - // potentially rely on the original behaviour, to be affected. + // potentially rely on the original behavior, to be affected. struct ServerRoleGuard { ServerRoleGuard() { auto const* clusterFeature = ApplicationServer::lookupFeature("Cluster"); diff --git a/arangod/IResearch/IResearchLink.cpp b/arangod/IResearch/IResearchLink.cpp index 3ccbbaf91c..09cd871e26 100644 --- a/arangod/IResearch/IResearchLink.cpp +++ b/arangod/IResearch/IResearchLink.cpp @@ -686,7 +686,7 @@ arangodb::Result IResearchLink::drop() { ); // may occur if the link was already unlinked from the view via another instance - // this behaviour was seen user-access-right-drop-view-arangosearch-spec.js + // this behavior was seen user-access-right-drop-view-arangosearch-spec.js // where the collection drop was called through REST, // the link was dropped as a result of the collection drop call // then the view was dropped via a separate REST call diff --git a/arangod/IResearch/IResearchViewCoordinator.cpp b/arangod/IResearch/IResearchViewCoordinator.cpp index a617fbd877..68ce7b53da 100644 --- a/arangod/IResearch/IResearchViewCoordinator.cpp +++ b/arangod/IResearch/IResearchViewCoordinator.cpp @@ -137,9 +137,9 @@ struct IResearchViewCoordinator::ViewFactory : public arangodb::ViewFactory { std::to_string(impl->id())); // refresh view from Agency if (view) { - view->open(); // open view to match the behaviour in + view->open(); // open view to match the behavior in // StorageEngine::openExistingDatabase(...) and original - // behaviour of TRI_vocbase_t::createView(...) + // behavior of TRI_vocbase_t::createView(...) } return arangodb::Result(); diff --git a/arangod/MMFiles/MMFilesOptimizerRules.cpp b/arangod/MMFiles/MMFilesOptimizerRules.cpp index d58be82934..59f71dfa67 100644 --- a/arangod/MMFiles/MMFilesOptimizerRules.cpp +++ b/arangod/MMFiles/MMFilesOptimizerRules.cpp @@ -43,13 +43,14 @@ using EN = arangodb::aql::ExecutionNode; void MMFilesOptimizerRules::registerResources() { // remove SORT RAND() if appropriate OptimizerRulesFeature::registerRule("remove-sort-rand", removeSortRandRule, - OptimizerRule::removeSortRandRule, false, true); + OptimizerRule::removeSortRandRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); } /// @brief remove SORT RAND() if appropriate void MMFilesOptimizerRules::removeSortRandRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::SORT, true); diff --git a/arangod/MMFiles/MMFilesOptimizerRules.h b/arangod/MMFiles/MMFilesOptimizerRules.h index ef8baf49d6..be2208f42b 100644 --- a/arangod/MMFiles/MMFilesOptimizerRules.h +++ b/arangod/MMFiles/MMFilesOptimizerRules.h @@ -38,7 +38,7 @@ struct MMFilesOptimizerRules { static void removeSortRandRule(aql::Optimizer* opt, std::unique_ptr plan, - aql::OptimizerRule const* rule); + aql::OptimizerRule const& rule); }; } // namespace arangodb diff --git a/arangod/RestHandler/RestAdminServerHandler.cpp b/arangod/RestHandler/RestAdminServerHandler.cpp index 5745e0bac4..62fb4e7181 100644 --- a/arangod/RestHandler/RestAdminServerHandler.cpp +++ b/arangod/RestHandler/RestAdminServerHandler.cpp @@ -67,7 +67,7 @@ void RestAdminServerHandler::handleId() { auto instance = ServerState::instance(); if (!instance->isRunningInCluster()) { - // old behaviour...klingt komisch, is aber so + // old behavior...klingt komisch, is aber so generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_HTTP_SERVER_ERROR); return; } diff --git a/arangod/RestHandler/RestGraphHandler.cpp b/arangod/RestHandler/RestGraphHandler.cpp index 1fe8a237f9..b30e8d04a7 100644 --- a/arangod/RestHandler/RestGraphHandler.cpp +++ b/arangod/RestHandler/RestGraphHandler.cpp @@ -113,7 +113,7 @@ Result RestGraphHandler::executeGharial() { // most operations. So fetching an edge via // /_api/gharial/{graph}/vertex/{coll}/{key} works just fine. Should this be // changed? One way or the other, make sure there are tests for the desired - // behaviour! + // behavior! /* if (collType == vertex) { if (graph->vertexCollections().find(setName) == diff --git a/arangod/RestHandler/RestReplicationHandler.cpp b/arangod/RestHandler/RestReplicationHandler.cpp index 28db40ca53..eff1a3716d 100644 --- a/arangod/RestHandler/RestReplicationHandler.cpp +++ b/arangod/RestHandler/RestReplicationHandler.cpp @@ -2427,7 +2427,7 @@ void RestReplicationHandler::handleCommandHoldReadLockCollection() { // This is an optional parameter, it may not be set (backwards compatible) // If it is not set it will default to a hard-lock, otherwise we do a - // potentially faster soft-lock synchronisation with a smaller hard-lock + // potentially faster soft-lock synchronization with a smaller hard-lock // phase. bool doSoftLock = VelocyPackHelper::getBooleanValue(body, "doSoftLockOnly", false); diff --git a/arangod/RocksDBEngine/RocksDBOptimizerRules.cpp b/arangod/RocksDBEngine/RocksDBOptimizerRules.cpp index 6856db3d88..3cc92189c5 100644 --- a/arangod/RocksDBEngine/RocksDBOptimizerRules.cpp +++ b/arangod/RocksDBEngine/RocksDBOptimizerRules.cpp @@ -55,19 +55,20 @@ std::vector const reduceExtractionToProjectionTypes = { void RocksDBOptimizerRules::registerResources() { // simplify an EnumerationCollectionNode that fetches an entire document to a // projection of this document - OptimizerRulesFeature::registerRule("reduce-extraction-to-projection", - reduceExtractionToProjectionRule, + OptimizerRulesFeature::registerRule("reduce-extraction-to-projection", reduceExtractionToProjectionRule, OptimizerRule::reduceExtractionToProjectionRule, - false, true); + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); + // remove SORT RAND() LIMIT 1 if appropriate OptimizerRulesFeature::registerRule("remove-sort-rand-limit-1", removeSortRandRule, - OptimizerRule::removeSortRandRule, false, true); + OptimizerRule::removeSortRandRule, + OptimizerRule::makeFlags(OptimizerRule::Flags::CanBeDisabled)); } // simplify an EnumerationCollectionNode that fetches an entire document to a // projection of this document void RocksDBOptimizerRules::reduceExtractionToProjectionRule( - Optimizer* opt, std::unique_ptr plan, OptimizerRule const* rule) { + Optimizer* opt, std::unique_ptr plan, OptimizerRule const& rule) { // These are all the nodes where we start traversing (including all // subqueries) SmallVector::allocator_type::arena_type a; @@ -349,7 +350,7 @@ void RocksDBOptimizerRules::reduceExtractionToProjectionRule( /// @brief remove SORT RAND() if appropriate void RocksDBOptimizerRules::removeSortRandRule(Optimizer* opt, std::unique_ptr plan, - OptimizerRule const* rule) { + OptimizerRule const& rule) { SmallVector::allocator_type::arena_type a; SmallVector nodes{a}; plan->findNodesOfType(nodes, EN::SORT, true); diff --git a/arangod/RocksDBEngine/RocksDBOptimizerRules.h b/arangod/RocksDBEngine/RocksDBOptimizerRules.h index bd7307480e..e87ced7224 100644 --- a/arangod/RocksDBEngine/RocksDBOptimizerRules.h +++ b/arangod/RocksDBEngine/RocksDBOptimizerRules.h @@ -39,11 +39,11 @@ struct RocksDBOptimizerRules { // projection of this document static void reduceExtractionToProjectionRule(aql::Optimizer* opt, std::unique_ptr plan, - aql::OptimizerRule const* rule); + aql::OptimizerRule const& rule); // remove SORT RAND() LIMIT 1 if appropriate static void removeSortRandRule(aql::Optimizer* opt, std::unique_ptr plan, - aql::OptimizerRule const* rule); + aql::OptimizerRule const& rule); }; } // namespace arangodb diff --git a/arangod/RocksDBEngine/RocksDBReplicationContext.cpp b/arangod/RocksDBEngine/RocksDBReplicationContext.cpp index d419397926..c41b81c5c0 100644 --- a/arangod/RocksDBEngine/RocksDBReplicationContext.cpp +++ b/arangod/RocksDBEngine/RocksDBReplicationContext.cpp @@ -228,7 +228,7 @@ Result RocksDBReplicationContext::getInventory(TRI_vocbase_t& vocbase, bool incl TRI_ASSERT(_snapshot != nullptr); // FIXME is it technically correct to include newly created collections ? - // simon: I think no, but this has been the behaviour since 3.2 + // simon: I think no, but this has been the behavior since 3.2 TRI_voc_tick_t tick = TRI_NewTickServer(); // = _lastArangoTick if (global) { // global inventory diff --git a/arangod/Transaction/Methods.cpp b/arangod/Transaction/Methods.cpp index c2da1433b7..7a4ec51311 100644 --- a/arangod/Transaction/Methods.cpp +++ b/arangod/Transaction/Methods.cpp @@ -3063,7 +3063,7 @@ Result transaction::Methods::addCollection(TRI_voc_cid_t cid, std::string const& }); if (!resolver()->visitCollections(visitor, cid) || res.fail()) { - // trigger exception as per the original behaviour (tests depend on this) + // trigger exception as per the original behavior (tests depend on this) if (res.ok() && !visited) { addCollectionCallback(cid); // will throw on error } diff --git a/arangod/VocBase/LogicalView.cpp b/arangod/VocBase/LogicalView.cpp index b2caa7e9ee..0e04bbb5bb 100644 --- a/arangod/VocBase/LogicalView.cpp +++ b/arangod/VocBase/LogicalView.cpp @@ -288,9 +288,9 @@ Result LogicalView::rename(std::string&& newName) { std::to_string(impl->id())); // refresh view from Agency if (view) { - view->open(); // open view to match the behaviour in + view->open(); // open view to match the behavior in // StorageEngine::openExistingDatabase(...) and original - // behaviour of TRI_vocbase_t::createView(...) + // behavior of TRI_vocbase_t::createView(...) } return Result(); diff --git a/arangod/VocBase/vocbase.h b/arangod/VocBase/vocbase.h index f9d4e5879c..539ae3d0c8 100644 --- a/arangod/VocBase/vocbase.h +++ b/arangod/VocBase/vocbase.h @@ -127,7 +127,7 @@ struct TRI_vocbase_t { TEST_VIRTUAL ~TRI_vocbase_t(); private: - // explicitly document implicit behaviour (due to presence of locks) + // explicitly document implicit behavior (due to presence of locks) TRI_vocbase_t(TRI_vocbase_t&&) = delete; TRI_vocbase_t(TRI_vocbase_t const&) = delete; TRI_vocbase_t& operator=(TRI_vocbase_t&&) = delete; diff --git a/tests/arangodbRspecLib/arangodb.rb b/tests/arangodbRspecLib/arangodb.rb index 285dd5ac0b..1d9e3703ff 100644 --- a/tests/arangodbRspecLib/arangodb.rb +++ b/tests/arangodbRspecLib/arangodb.rb @@ -380,7 +380,7 @@ end end end -# super carrot fix for strange SSL behaviour on windows +# super carrot fix for strange SSL behavior on windows # on some windowses the first SSL request somehow throws strange SSL errors # after that everything is fine...so make a dummy request first if $ssl == '1' diff --git a/tests/js/client/shell/shell-analyzer-rest-api.js b/tests/js/client/shell/shell-analyzer-rest-api.js index a4f524f7ff..c9341278ff 100644 --- a/tests/js/client/shell/shell-analyzer-rest-api.js +++ b/tests/js/client/shell/shell-analyzer-rest-api.js @@ -244,6 +244,7 @@ function testSuite() { arango.DELETE("/_api/analyzer/" + name + j); } }, + testAnalyzerLinks : function() { let body = JSON.stringify({ name : name, diff --git a/tests/js/common/shell/shell-collection-cache-rocksdb-noncluster-nondeterministic-grey.js b/tests/js/common/shell/shell-collection-cache-rocksdb-noncluster-nondeterministic-grey.js index 53089526fd..5ae6f5580a 100644 --- a/tests/js/common/shell/shell-collection-cache-rocksdb-noncluster-nondeterministic-grey.js +++ b/tests/js/common/shell/shell-collection-cache-rocksdb-noncluster-nondeterministic-grey.js @@ -115,7 +115,7 @@ function CollectionCacheSuite () { }); }, - testCollectionCacheBehaviour : function () { + testCollectionCacheBehavior : function () { let c = db._create(cn, {cacheEnabled:true}); let p = c.properties(); assertTrue(p.cacheEnabled, p); diff --git a/tests/js/common/shell/shell-collection-rocksdb-noncluster.js b/tests/js/common/shell/shell-collection-rocksdb-noncluster.js index 3b606b1168..821887f744 100644 --- a/tests/js/common/shell/shell-collection-rocksdb-noncluster.js +++ b/tests/js/common/shell/shell-collection-rocksdb-noncluster.js @@ -404,9 +404,8 @@ function CollectionSuite () { c.unload(); }, - testEdgeCacheBehaviour : function() { - - var cn = "UnitLoadBehaviour123"; + testEdgeCacheBehavior : function() { + var cn = "UnitLoadBehavior123"; db._drop(cn); var c = db._createEdgeCollection(cn); c.load(); diff --git a/tests/js/common/shell/shell-pregel-start-cluster.js b/tests/js/common/shell/shell-pregel-start-cluster.js index f98091700a..b526e9d009 100644 --- a/tests/js/common/shell/shell-pregel-start-cluster.js +++ b/tests/js/common/shell/shell-pregel-start-cluster.js @@ -237,12 +237,12 @@ function basicTestSuite() { }, testPageRank: function () { - // should test correct convergence behaviour, might fail if EPS is too low + // should test correct convergence behavior, might fail if EPS is too low testAlgo("pagerank", { threshold: EPS / 10, resultField: "result", store: true }); }, testPageRankMMap: function () { - // should test correct convergence behaviour, might fail if EPS is too low + // should test correct convergence behavior, might fail if EPS is too low testAlgo("pagerank", { threshold: EPS / 10, resultField: "result", store: true, useMemoryMaps: true }); }, diff --git a/tests/js/server/shell/shell-pregel.js b/tests/js/server/shell/shell-pregel.js index a04745ad90..2673d15d88 100644 --- a/tests/js/server/shell/shell-pregel.js +++ b/tests/js/server/shell/shell-pregel.js @@ -148,12 +148,12 @@ function basicTestSuite() { }, testPageRank: function () { - // should test correct convergence behaviour, might fail if EPS is too low + // should test correct convergence behavior, might fail if EPS is too low testAlgo("pagerank", { threshold: EPS / 10, resultField: "result", store: true }); }, testPageRankMMap: function () { - // should test correct convergence behaviour, might fail if EPS is too low + // should test correct convergence behavior, might fail if EPS is too low testAlgo("pagerank", { threshold: EPS / 10, resultField: "result", store: true, useMemoryMaps: true }); },