From c00d0cbc4d2b67dd052914b8c51ada7889d1f2dc Mon Sep 17 00:00:00 2001 From: Michael Hackstein Date: Fri, 18 Dec 2015 15:12:39 +0100 Subject: [PATCH] Improved stability of AQL Traverser. Also added checks for illegal edge cases --- arangod/Aql/ExecutionPlan.cpp | 20 ++++++++++++++++++++ arangod/Aql/TraversalBlock.cpp | 14 +++++++++----- arangod/VocBase/Traverser.h | 4 ++-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/arangod/Aql/ExecutionPlan.cpp b/arangod/Aql/ExecutionPlan.cpp index aa36aa215d..f5168f7eeb 100644 --- a/arangod/Aql/ExecutionPlan.cpp +++ b/arangod/Aql/ExecutionPlan.cpp @@ -648,6 +648,26 @@ ExecutionNode* ExecutionPlan::fromNodeTraversal (ExecutionNode* previous, AstNode const* start = node->getMember(1); AstNode const* graph = node->getMember(2); + if (start->type == NODE_TYPE_OBJECT && + start->isConstant()) { + size_t n = start->numMembers(); + for (size_t i = 0; i < n; ++i) { + auto member = start->getMember(i); + if (member->type == NODE_TYPE_OBJECT_ELEMENT && + strncmp(member->getStringValue(), TRI_VOC_ATTRIBUTE_ID, member->getStringLength()) == 0) { + start = member->getMember(0); + break; + } + } + } + + if (start->type != NODE_TYPE_REFERENCE && + start->type != NODE_TYPE_VALUE) { + // operand is some misc expression + auto calc = createTemporaryCalculation(start, previous); + start = _ast->createNodeReference(getOutVariable(calc)); + previous = calc; + } // First create the node auto travNode = new TraversalNode(this, nextId(), _ast->query()->vocbase(), direction, start, graph); diff --git a/arangod/Aql/TraversalBlock.cpp b/arangod/Aql/TraversalBlock.cpp index eb47e9ac0c..e9839c1a4f 100644 --- a/arangod/Aql/TraversalBlock.cpp +++ b/arangod/Aql/TraversalBlock.cpp @@ -115,7 +115,7 @@ TraversalBlock::TraversalBlock (ExecutionEngine* engine, _trx, _expressions)); } - if (!ep->usesInVariable()) { + if (! ep->usesInVariable()) { _vertexId = ep->getStartVertex(); } else { @@ -365,12 +365,16 @@ void TraversalBlock::initializePaths (AqlItemBlock const* items) { } } } - else if (in._type == AqlValue::DOCVEC) { - THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_QUERY_PARSE, - std::string("Only one start vertex allowed. Embed it in a FOR loop.")); + else if (in.isString()) { + _vertexId = in.toString(); + VertexId v = triagens::arango::traverser::IdStringToVertexId ( + _resolver, + _vertexId + ); + _traverser->setStartVertex(v); } else { - TRI_ASSERT(in.getTypeString() == ""); + _engine->getQuery()->registerWarning(TRI_ERROR_BAD_PARAMETER, "Invalid input for traversal: Only strings or objects with _id are allowed"); } } } diff --git a/arangod/VocBase/Traverser.h b/arangod/VocBase/Traverser.h index 68465126b6..2e47609148 100644 --- a/arangod/VocBase/Traverser.h +++ b/arangod/VocBase/Traverser.h @@ -269,7 +269,7 @@ namespace triagens { : _readDocuments(0), _filteredPaths(0), _pruneNext(false), - _done(false), + _done(true), _expressions(nullptr) { } @@ -282,7 +282,7 @@ namespace triagens { : _readDocuments(0), _filteredPaths(0), _pruneNext(false), - _done(false), + _done(true), _opts(opts), _expressions(expressions) { }