diff --git a/arangod/Aql/Index.h b/arangod/Aql/Index.h index 2f64e2e667..0e6d7d0472 100644 --- a/arangod/Aql/Index.h +++ b/arangod/Aql/Index.h @@ -179,8 +179,9 @@ namespace triagens { arango::IndexIterator* getIterator (arango::IndexIteratorContext* context, triagens::aql::Ast* ast, triagens::aql::AstNode const* condition, - triagens::aql::Variable const* reference) const { - return getInternals()->iteratorForCondition(context, ast, condition, reference); + triagens::aql::Variable const* reference, + bool const reverse) const { + return getInternals()->iteratorForCondition(context, ast, condition, reference, reverse); } triagens::aql::AstNode* specializeCondition (triagens::aql::AstNode const* node, diff --git a/arangod/Aql/IndexBlock.cpp b/arangod/Aql/IndexBlock.cpp index e8d937e52c..39e9fe0468 100644 --- a/arangod/Aql/IndexBlock.cpp +++ b/arangod/Aql/IndexBlock.cpp @@ -150,6 +150,10 @@ int IndexBlock::initialize () { }; auto outVariable = static_cast(getPlanNode())->outVariable(); + if (_condition == nullptr) { + // This Node has no condition. Iterate over the complete index. + return TRI_ERROR_NO_ERROR; + } for (size_t i = 0; i < _condition->numMembers(); ++i) { auto andCond = _condition->getMemberUnchecked(i); @@ -255,14 +259,25 @@ bool IndexBlock::initIndexes () { } _currentIndex = 0; - auto outVariable = static_cast(getPlanNode())->outVariable(); - auto ast = static_cast(getPlanNode())->_plan->getAst(); - _iterator = _indexes[_currentIndex]->getIterator(_context, ast, _condition->getMember(_currentIndex), outVariable); + IndexNode const* node = static_cast(getPlanNode()); + auto outVariable = node->outVariable(); + auto ast = node->_plan->getAst(); + if (_condition == nullptr) { + _iterator = _indexes[_currentIndex]->getIterator(_context, ast, nullptr, outVariable, node->_reverse); + } + else { + _iterator = _indexes[_currentIndex]->getIterator(_context, ast, _condition->getMember(_currentIndex), outVariable, node->_reverse); + } while (_iterator == nullptr) { ++_currentIndex; if (_currentIndex < _indexes.size()) { - _iterator = _indexes[_currentIndex]->getIterator(_context, ast, _condition->getMember(_currentIndex), outVariable); + if (_condition == nullptr) { + _iterator = _indexes[_currentIndex]->getIterator(_context, ast, nullptr, outVariable, node->_reverse); + } + else { + _iterator = _indexes[_currentIndex]->getIterator(_context, ast, _condition->getMember(_currentIndex), outVariable, node->_reverse); + } } else { // We were not able to initialize any index with this condition @@ -280,10 +295,11 @@ void IndexBlock::startNextIterator () { ++_currentIndex; if (_currentIndex < _indexes.size()) { - auto outVariable = static_cast(getPlanNode())->outVariable(); - auto ast = static_cast(getPlanNode())->_plan->getAst(); + IndexNode const* node = static_cast(getPlanNode()); + auto outVariable = node->outVariable(); + auto ast = node->_plan->getAst(); - _iterator = _indexes[_currentIndex]->getIterator(_context, ast, _condition->getMember(_currentIndex), outVariable); + _iterator = _indexes[_currentIndex]->getIterator(_context, ast, _condition->getMember(_currentIndex), outVariable, node->_reverse); } /* else { diff --git a/arangod/Indexes/EdgeIndex.cpp b/arangod/Indexes/EdgeIndex.cpp index 91319b3bae..f0d13bcb93 100644 --- a/arangod/Indexes/EdgeIndex.cpp +++ b/arangod/Indexes/EdgeIndex.cpp @@ -616,7 +616,8 @@ bool EdgeIndex::supportsFilterCondition (triagens::aql::AstNode const* node, IndexIterator* EdgeIndex::iteratorForCondition (IndexIteratorContext* context, triagens::aql::Ast* ast, triagens::aql::AstNode const* node, - triagens::aql::Variable const* reference) const { + triagens::aql::Variable const* reference, + bool const reverse) const { TRI_ASSERT(node->type == aql::NODE_TYPE_OPERATOR_NARY_AND); SimpleAttributeEqualityMatcher matcher({ diff --git a/arangod/Indexes/EdgeIndex.h b/arangod/Indexes/EdgeIndex.h index ecd5956462..8158271871 100644 --- a/arangod/Indexes/EdgeIndex.h +++ b/arangod/Indexes/EdgeIndex.h @@ -181,7 +181,8 @@ namespace triagens { IndexIterator* iteratorForCondition (IndexIteratorContext*, triagens::aql::Ast*, triagens::aql::AstNode const*, - triagens::aql::Variable const*) const override; + triagens::aql::Variable const*, + bool const) const override; // ----------------------------------------------------------------------------- // --SECTION-- private methods diff --git a/arangod/Indexes/HashIndex.cpp b/arangod/Indexes/HashIndex.cpp index 5d84db710b..10f47fc8c6 100644 --- a/arangod/Indexes/HashIndex.cpp +++ b/arangod/Indexes/HashIndex.cpp @@ -793,7 +793,8 @@ bool HashIndex::supportsFilterCondition (triagens::aql::AstNode const* node, IndexIterator* HashIndex::iteratorForCondition (IndexIteratorContext* context, triagens::aql::Ast* ast, triagens::aql::AstNode const* node, - triagens::aql::Variable const* reference) const { + triagens::aql::Variable const* reference, + bool const reverse) const { TRI_ASSERT(node->type == aql::NODE_TYPE_OPERATOR_NARY_AND); SimpleAttributeEqualityMatcher matcher(fields()); diff --git a/arangod/Indexes/HashIndex.h b/arangod/Indexes/HashIndex.h index 04d41f0aa4..ca1d7a5805 100644 --- a/arangod/Indexes/HashIndex.h +++ b/arangod/Indexes/HashIndex.h @@ -185,7 +185,8 @@ namespace triagens { IndexIterator* iteratorForCondition (IndexIteratorContext*, triagens::aql::Ast*, triagens::aql::AstNode const*, - triagens::aql::Variable const*) const override; + triagens::aql::Variable const*, + bool const) const override; triagens::aql::AstNode* specializeCondition (triagens::aql::AstNode const*, triagens::aql::Variable const*) const override; diff --git a/arangod/Indexes/Index.cpp b/arangod/Indexes/Index.cpp index 548e76b9c6..9eb0a63ea9 100644 --- a/arangod/Indexes/Index.cpp +++ b/arangod/Indexes/Index.cpp @@ -461,7 +461,8 @@ bool Index::supportsSortCondition (triagens::aql::SortCondition const*, IndexIterator* Index::iteratorForCondition (IndexIteratorContext*, triagens::aql::Ast*, triagens::aql::AstNode const*, - triagens::aql::Variable const*) const { + triagens::aql::Variable const*, + bool const) const { // the super class index cannot create an iterator // the derived index classes have to manage this. return nullptr; diff --git a/arangod/Indexes/Index.h b/arangod/Indexes/Index.h index a611079f94..d801ea165c 100644 --- a/arangod/Indexes/Index.h +++ b/arangod/Indexes/Index.h @@ -352,7 +352,8 @@ namespace triagens { virtual IndexIterator* iteratorForCondition (IndexIteratorContext*, triagens::aql::Ast*, triagens::aql::AstNode const*, - triagens::aql::Variable const*) const; + triagens::aql::Variable const*, + bool const) const; virtual triagens::aql::AstNode* specializeCondition (triagens::aql::AstNode const*, triagens::aql::Variable const*) const; diff --git a/arangod/Indexes/PrimaryIndex.cpp b/arangod/Indexes/PrimaryIndex.cpp index 10965e38b0..791b581d2c 100644 --- a/arangod/Indexes/PrimaryIndex.cpp +++ b/arangod/Indexes/PrimaryIndex.cpp @@ -323,7 +323,8 @@ bool PrimaryIndex::supportsFilterCondition (triagens::aql::AstNode const* node, IndexIterator* PrimaryIndex::iteratorForCondition (IndexIteratorContext* context, triagens::aql::Ast* ast, triagens::aql::AstNode const* node, - triagens::aql::Variable const* reference) const { + triagens::aql::Variable const* reference, + bool const reverse) const { TRI_ASSERT(node->type == aql::NODE_TYPE_OPERATOR_NARY_AND); SimpleAttributeEqualityMatcher matcher({ diff --git a/arangod/Indexes/PrimaryIndex.h b/arangod/Indexes/PrimaryIndex.h index b0ad39df75..2d1d668917 100644 --- a/arangod/Indexes/PrimaryIndex.h +++ b/arangod/Indexes/PrimaryIndex.h @@ -205,7 +205,8 @@ namespace triagens { IndexIterator* iteratorForCondition (IndexIteratorContext*, triagens::aql::Ast*, triagens::aql::AstNode const*, - triagens::aql::Variable const*) const override; + triagens::aql::Variable const*, + bool const) const override; // ----------------------------------------------------------------------------- // --SECTION-- private methods diff --git a/arangod/Indexes/SkiplistIndex.cpp b/arangod/Indexes/SkiplistIndex.cpp index 20ac7cf887..1e0ead1bf0 100644 --- a/arangod/Indexes/SkiplistIndex.cpp +++ b/arangod/Indexes/SkiplistIndex.cpp @@ -31,12 +31,14 @@ #include "Aql/AstNode.h" #include "Aql/SortCondition.h" #include "Basics/AttributeNameParser.h" +#include "Basics/json-utilities.h" #include "Basics/logging.h" #include "VocBase/document-collection.h" #include "VocBase/transaction.h" #include "VocBase/VocShaper.h" using namespace triagens::arango; +using Json = triagens::basics::Json; // ----------------------------------------------------------------------------- // --SECTION-- private functions @@ -1176,9 +1178,20 @@ bool SkiplistIndex::supportsSortCondition (triagens::aql::SortCondition const* s IndexIterator* SkiplistIndex::iteratorForCondition (IndexIteratorContext* context, triagens::aql::Ast* ast, - triagens::aql::AstNode const*node, - triagens::aql::Variable const* reference) const { + triagens::aql::AstNode const* node, + triagens::aql::Variable const* reference, + bool const reverse) const { // Create the skiplistOperator for the IndexLookup + if (node == nullptr) { + // We have no condition, we just use sort + Json nullArray(Json::Array); + nullArray.add(Json(Json::Null)); + std::unique_ptr unboundOperator(TRI_CreateIndexOperator(TRI_GE_INDEX_OPERATOR, nullptr, + nullptr, nullArray.steal(), _shaper, 1)); + std::vector searchValues({unboundOperator.get()}); + unboundOperator.release(); + return new SkiplistIndexIterator(this, searchValues, reverse); + } std::unordered_map> found; size_t unused = 0; matchAttributes(node, reference, found, unused); @@ -1378,7 +1391,7 @@ IndexIterator* SkiplistIndex::iteratorForCondition (IndexIteratorContext* contex } } - return new SkiplistIndexIterator(this, searchValues); + return new SkiplistIndexIterator(this, searchValues, reverse); } // ----------------------------------------------------------------------------- diff --git a/arangod/Indexes/SkiplistIndex.h b/arangod/Indexes/SkiplistIndex.h index 3de3a376ef..e91346cf9b 100644 --- a/arangod/Indexes/SkiplistIndex.h +++ b/arangod/Indexes/SkiplistIndex.h @@ -178,10 +178,11 @@ namespace triagens { public: SkiplistIndexIterator (SkiplistIndex const* index, - std::vector op) + std::vector op, + bool reverse) : _index(index), _operators(op), - _reverse(false), + _reverse(reverse), _currentOperator(0), _iterator(nullptr) { } @@ -310,7 +311,8 @@ namespace triagens { IndexIterator* iteratorForCondition (IndexIteratorContext*, triagens::aql::Ast*, triagens::aql::AstNode const*, - triagens::aql::Variable const*) const override; + triagens::aql::Variable const*, + bool const) const override; // -----------------------------------------------------------------------------