From b6f9f11e5e6ae3cd974b38702bae87dc7d11309c Mon Sep 17 00:00:00 2001 From: James Date: Fri, 29 Aug 2014 17:44:32 +0200 Subject: [PATCH] added all node types to FilterToEnumCollFinder. --- arangod/Aql/ExecutionBlock.cpp | 3 +- arangod/Aql/OptimizerRules.cpp | 233 ++++++++++++++++++--------------- 2 files changed, 133 insertions(+), 103 deletions(-) diff --git a/arangod/Aql/ExecutionBlock.cpp b/arangod/Aql/ExecutionBlock.cpp index 5e651ba32e..a67bfc6eb2 100644 --- a/arangod/Aql/ExecutionBlock.cpp +++ b/arangod/Aql/ExecutionBlock.cpp @@ -1051,7 +1051,8 @@ void IndexRangeBlock::readSkiplistIndex () { // this creates the infinite range (i.e. >= null) Json hass(Json::List); hass.add(Json(Json::Null)); - skiplistOperator = TRI_CreateIndexOperator(TRI_GE_INDEX_OPERATOR, nullptr, nullptr, hass.steal(), shaper, nullptr, 1, nullptr); + skiplistOperator = TRI_CreateIndexOperator(TRI_GE_INDEX_OPERATOR, nullptr, + nullptr, hass.steal(), shaper, nullptr, 1, nullptr); } else { skiplistOperator = TRI_CreateIndexOperator(TRI_EQ_INDEX_OPERATOR, nullptr, diff --git a/arangod/Aql/OptimizerRules.cpp b/arangod/Aql/OptimizerRules.cpp index c85205ad75..0be8f6dc2f 100644 --- a/arangod/Aql/OptimizerRules.cpp +++ b/arangod/Aql/OptimizerRules.cpp @@ -398,123 +398,152 @@ class FilterToEnumCollFinder : public WalkerWorker { bool before (ExecutionNode* en) { _canThrow = (_canThrow || en->canThrow()); // can any node walked over throw? - if (en->getType() == triagens::aql::ExecutionNode::FILTER) { - std::vector inVar = en->getVariablesUsedHere(); - TRI_ASSERT(inVar.size() == 1); - _varIds.insert(inVar[0]->id); - } - else if (en->getType() == triagens::aql::ExecutionNode::CALCULATION) { - auto outvar = en->getVariablesSetHere(); - TRI_ASSERT(outvar.size() == 1); - if (_varIds.find(outvar[0]->id) != _varIds.end()) { - auto node = static_cast(en); - std::string attr; - std::string enumCollVar; - buildRangeInfo(node->expression()->node(), enumCollVar, attr); - } - } - else if (en->getType() == triagens::aql::ExecutionNode::ENUMERATE_COLLECTION) { - auto node = static_cast(en); - auto var = node->getVariablesSetHere()[0]; // should only be 1 - auto map = _ranges->find(var->name); // check if we have any ranges with this var - - if (map != nullptr) { - // check the first components of against indexes of . . . - std::unordered_set attrs; - - bool valid = true; // are all the range infos valid - bool equality = true; // are all the range infos equalities - - for(auto x: *map) { - valid &= x.second._valid; - if (!valid) { - break; - } - equality &= x.second.is1ValueRangeInfo(); - attrs.insert(x.first); + switch (en->getType()) { + case EN::ENUMERATE_LIST: + break; + case EN::CALCULATION: { + auto outvar = en->getVariablesSetHere(); + TRI_ASSERT(outvar.size() == 1); + if (_varIds.find(outvar[0]->id) != _varIds.end()) { + auto node = static_cast(en); + std::string attr; + std::string enumCollVar; + buildRangeInfo(node->expression()->node(), enumCollVar, attr); } + break; + } + case EN::SUBQUERY: + break; + case EN::FILTER:{ + std::vector inVar = en->getVariablesUsedHere(); + TRI_ASSERT(inVar.size() == 1); + _varIds.insert(inVar[0]->id); + break; + } + case EN::INTERSECTION: + case EN::SINGLETON: + case EN::AGGREGATE: + case EN::LOOKUP_JOIN: + case EN::MERGE_JOIN: + case EN::LOOKUP_INDEX_UNIQUE: + case EN::LOOKUP_INDEX_RANGE: + case EN::LOOKUP_FULL_COLLECTION: + case EN::CONCATENATION: + case EN::MERGE: + case EN::REMOTE: + case EN::INSERT: + case EN::REMOVE: + case EN::REPLACE: + case EN::UPDATE: + case EN::RETURN: + case EN::NORESULTS: + case EN::ILLEGAL: + break; + case EN::LIMIT: + // if we meet a limit node between a filter and an enumerate collection, + // we abort . . . + return true; + case EN::SORT: + case EN::INDEX_RANGE: + break; + case EN::ENUMERATE_COLLECTION:{ + auto node = static_cast(en); + auto var = node->getVariablesSetHere()[0]; // should only be 1 + auto map = _ranges->find(var->name); // check if we have any ranges with this var + + if (map != nullptr) { + // check the first components of against indexes of . . . + std::unordered_set attrs; + + bool valid = true; // are all the range infos valid + bool equality = true; // are all the range infos equalities - if (! _canThrow) { - if (! valid) { // ranges are not valid . . . - - auto newPlan = _plan->clone(); - try { - auto parents = newPlan->getNodeById(node->id())->getParents(); - for (auto x: parents) { - auto noRes = new NoResultsNode(newPlan->nextId()); - newPlan->registerNode(noRes); - newPlan->insertDependency(x, noRes); - _opt->addPlan(newPlan, _level, true); - } - } - catch (...) { - delete newPlan; - throw; + for(auto x: *map) { + valid &= x.second._valid; + if (!valid) { + break; } + equality &= x.second.is1ValueRangeInfo(); + attrs.insert(x.first); } - else { - std::vector idxs; - std::vector prefixes; - // {idxs.at(i)->_fields[0]..idxs.at(i)->_fields[prefixes.at(i)]} - // is a subset of - node->getIndexesForIndexRangeNode(attrs, idxs, prefixes); - - // make one new plan for every index in that replaces the - // enumerate collection node with a RangeIndexNode . . . - - for (size_t i = 0; i < idxs.size(); i++) { - std::vector> rangeInfo; - rangeInfo.push_back(std::vector()); + if (! _canThrow) { + if (! valid) { // ranges are not valid . . . - // ranges must be valid and all comparisons == if hash index or == - // followed by a single <, >, >=, or <= if a skip index in the - // order of the fields of the index. - auto idx = idxs.at(i); - if (idx->_type == TRI_IDX_TYPE_HASH_INDEX && equality) { - for (size_t j = 0; j < idx->_fields._length; j++) { - auto range = map->find(std::string(idx->_fields._buffer[j])); - rangeInfo.at(0).push_back(range->second); - } - } - - if (idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) { - size_t j = 0; - auto range = map->find(std::string(idx->_fields._buffer[0])); - rangeInfo.at(0).push_back(range->second); - equality = range->second.is1ValueRangeInfo(); - while (++j < prefixes.at(i) && equality){ - range = map->find(std::string(idx->_fields._buffer[j])); - rangeInfo.at(0).push_back(range->second); - equality = equality && range->second.is1ValueRangeInfo(); - } - } - - if (rangeInfo.at(0).size() != 0) { - auto newPlan = _plan->clone(); - try { - ExecutionNode* newNode = new IndexRangeNode(newPlan->nextId(), node->vocbase(), - node->collection(), node->outVariable(), idx, rangeInfo); - newPlan->registerNode(newNode); - newPlan->replaceNode(newPlan->getNodeById(node->id()), newNode); + auto newPlan = _plan->clone(); + try { + auto parents = newPlan->getNodeById(node->id())->getParents(); + for (auto x: parents) { + auto noRes = new NoResultsNode(newPlan->nextId()); + newPlan->registerNode(noRes); + newPlan->insertDependency(x, noRes); _opt->addPlan(newPlan, _level, true); } - catch (...) { - delete newPlan; - throw; + } + catch (...) { + delete newPlan; + throw; + } + } + else { + std::vector idxs; + std::vector prefixes; + // {idxs.at(i)->_fields[0]..idxs.at(i)->_fields[prefixes.at(i)]} + // is a subset of + + node->getIndexesForIndexRangeNode(attrs, idxs, prefixes); + + // make one new plan for every index in that replaces the + // enumerate collection node with a RangeIndexNode . . . + + for (size_t i = 0; i < idxs.size(); i++) { + std::vector> rangeInfo; + rangeInfo.push_back(std::vector()); + + // ranges must be valid and all comparisons == if hash index or == + // followed by a single <, >, >=, or <= if a skip index in the + // order of the fields of the index. + auto idx = idxs.at(i); + if (idx->_type == TRI_IDX_TYPE_HASH_INDEX && equality) { + for (size_t j = 0; j < idx->_fields._length; j++) { + auto range = map->find(std::string(idx->_fields._buffer[j])); + rangeInfo.at(0).push_back(range->second); + } + } + + if (idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) { + size_t j = 0; + auto range = map->find(std::string(idx->_fields._buffer[0])); + rangeInfo.at(0).push_back(range->second); + equality = range->second.is1ValueRangeInfo(); + while (++j < prefixes.at(i) && equality){ + range = map->find(std::string(idx->_fields._buffer[j])); + rangeInfo.at(0).push_back(range->second); + equality = equality && range->second.is1ValueRangeInfo(); + } + } + + if (rangeInfo.at(0).size() != 0) { + auto newPlan = _plan->clone(); + try { + ExecutionNode* newNode = new IndexRangeNode(newPlan->nextId(), node->vocbase(), + node->collection(), node->outVariable(), idx, rangeInfo); + newPlan->registerNode(newNode); + newPlan->replaceNode(newPlan->getNodeById(node->id()), newNode); + _opt->addPlan(newPlan, _level, true); + } + catch (...) { + delete newPlan; + throw; + } } } } } } + break; } } - else if (en->getType() == triagens::aql::ExecutionNode::LIMIT) { - // if we meet a limit node between a filter and an enumerate collection, - // we abort . . . - return true; - } - return false; }