arangodb::traverser::TraverserOptions::TraverserOptions( arangodb::aql::Query* query, VPackSlice info, VPackSlice collections) : _trx(query->trx()), _baseVertexExpression(nullptr), _tmpVar(nullptr), _ctx(new aql::FixedVarExpressionContext()), _isCoordinator(arangodb::ServerState::instance()->isCoordinator()), minDepth(1), maxDepth(1), useBreadthFirst(false), uniqueVertices(UniquenessLevel::NONE), uniqueEdges(UniquenessLevel::PATH) { // NOTE collections is an array of arrays of strings VPackSlice read = info.get("minDepth"); if (!read.isInteger()) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "The options require a minDepth"); } minDepth = read.getNumber<uint64_t>(); read = info.get("maxDepth"); if (!read.isInteger()) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "The options require a maxDepth"); } maxDepth = read.getNumber<uint64_t>(); read = info.get("bfs"); if (!read.isBoolean()) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "The options require a bfs"); } useBreadthFirst = read.getBool(); read = info.get("tmpVar"); if (!read.isObject()) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "The options require a tmpVar"); } _tmpVar = query->ast()->variables()->createVariable(read); read = info.get("uniqueVertices"); if (!read.isInteger()) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "The options require a uniqueVertices"); } size_t i = read.getNumber<size_t>(); switch (i) { case 0: uniqueVertices = UniquenessLevel::NONE; break; case 1: uniqueVertices = UniquenessLevel::PATH; break; case 2: uniqueVertices = UniquenessLevel::GLOBAL; break; default: THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "The options require a uniqueVertices"); } read = info.get("uniqueEdges"); if (!read.isInteger()) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "The options require a uniqueEdges"); } i = read.getNumber<size_t>(); switch (i) { case 0: uniqueEdges = UniquenessLevel::NONE; break; case 1: uniqueEdges = UniquenessLevel::PATH; break; case 2: uniqueEdges = UniquenessLevel::GLOBAL; break; default: THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "The options require a uniqueEdges"); } read = info.get("baseLookupInfos"); if (!read.isArray()) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "The options require a baseLookupInfos"); } size_t length = read.length(); TRI_ASSERT(read.length() == collections.length()); _baseLookupInfos.reserve(length); for (size_t j = 0; j < length; ++j) { _baseLookupInfos.emplace_back(query, read.at(j), collections.at(j)); } read = info.get("depthLookupInfo"); if (!read.isNone()) { if (!read.isObject()) { THROW_ARANGO_EXCEPTION_MESSAGE( TRI_ERROR_BAD_PARAMETER, "The options require depthLookupInfo to be an object"); } _depthLookupInfo.reserve(read.length()); for (auto const& depth : VPackObjectIterator(read)) { size_t d = basics::StringUtils::uint64(depth.key.copyString()); auto it = _depthLookupInfo.emplace(d, std::vector<LookupInfo>()); TRI_ASSERT(it.second); VPackSlice list = depth.value; TRI_ASSERT(length == list.length()); it.first->second.reserve(length); for (size_t j = 0; j < length; ++j) { it.first->second.emplace_back(query, list.at(j), collections.at(j)); } } } read = info.get("vertexExpressions"); if (!read.isNone()) { if (!read.isObject()) { THROW_ARANGO_EXCEPTION_MESSAGE( TRI_ERROR_BAD_PARAMETER, "The options require vertexExpressions to be an object"); } _vertexExpressions.reserve(read.length()); for (auto const& info : VPackObjectIterator(read)) { size_t d = basics::StringUtils::uint64(info.key.copyString()); #ifdef ARANGODB_ENABLE_MAINAINER_MODE auto it = _vertexExpressions.emplace( d, new aql::Expression(query->ast(), info.value)); TRI_ASSERT(it.second); #else _vertexExpressions.emplace( d, new aql::Expression(query->ast(), info.value)); #endif } } read = info.get("baseVertexExpression"); if (!read.isNone()) { if (!read.isObject()) { THROW_ARANGO_EXCEPTION_MESSAGE( TRI_ERROR_BAD_PARAMETER, "The options require vertexExpressions to be an object"); } _baseVertexExpression = new aql::Expression(query->ast(), read); } // Check for illegal option combination: TRI_ASSERT(uniqueEdges != arangodb::traverser::TraverserOptions::UniquenessLevel::GLOBAL); TRI_ASSERT( uniqueVertices != arangodb::traverser::TraverserOptions::UniquenessLevel::GLOBAL || useBreadthFirst); }