void operator()(VPackSlice const& v, std::vector<VPackSlice>& resEdges, std::vector<VPackSlice>& neighbors) { int res = TRI_ERROR_NO_ERROR; for (auto const& edgeCollection : _block->_collectionInfos) { VPackBuilder result; TRI_ASSERT(edgeCollection != nullptr); if (_isReverse) { res = edgeCollection->getReverseEdgesCoordinator(v, result); } else { res = edgeCollection->getEdgesCoordinator(v, result); } if (res != TRI_ERROR_NO_ERROR) { THROW_ARANGO_EXCEPTION(res); } VPackSlice edges = result.slice().get("edges"); for (auto const& edge : VPackArrayIterator(edges)) { VPackSlice from = arangodb::Transaction::extractFromFromDocument(edge); if (from == v) { VPackSlice to = arangodb::Transaction::extractToFromDocument(edge); if (to != v) { resEdges.emplace_back(edge); neighbors.emplace_back(to); } } else { resEdges.emplace_back(edge); neighbors.emplace_back(from); } } // Make sure the data Slices are pointing to is not running out of scope. // This is not thread-safe! _block->_coordinatorCache.emplace_back(result.steal()); } }
arangodb::traverser::TraverserOptions::LookupInfo::LookupInfo( arangodb::aql::Query* query, VPackSlice const& info, VPackSlice const& shards) { TRI_ASSERT(shards.isArray()); idxHandles.reserve(shards.length()); conditionNeedUpdate = arangodb::basics::VelocyPackHelper::getBooleanValue( info, "condNeedUpdate", false); conditionMemberToUpdate = arangodb::basics::VelocyPackHelper::getNumericValue<size_t>( info, "condMemberToUpdate", 0); VPackSlice read = info.get("handle"); if (!read.isObject()) { THROW_ARANGO_EXCEPTION_MESSAGE( TRI_ERROR_BAD_PARAMETER, "Each lookup requires handle to be an object"); } read = read.get("id"); if (!read.isString()) { THROW_ARANGO_EXCEPTION_MESSAGE( TRI_ERROR_BAD_PARAMETER, "Each handle requires id to be a string"); } std::string idxId = read.copyString(); auto trx = query->trx(); for (auto const& it : VPackArrayIterator(shards)) { if (!it.isString()) { THROW_ARANGO_EXCEPTION_MESSAGE( TRI_ERROR_BAD_PARAMETER, "Shards have to be a list of strings"); } idxHandles.emplace_back(trx->getIndexByIdentifier(it.copyString(), idxId)); } read = info.get("expression"); if (!read.isObject()) { THROW_ARANGO_EXCEPTION_MESSAGE( TRI_ERROR_BAD_PARAMETER, "Each lookup requires expression to be an object"); } expression = new aql::Expression(query->ast(), read); read = info.get("condition"); if (!read.isObject()) { THROW_ARANGO_EXCEPTION_MESSAGE( TRI_ERROR_BAD_PARAMETER, "Each lookup requires condition to be an object"); } indexCondition = new aql::AstNode(query->ast(), read); }
void operator()(VPackSlice const& source, std::vector<ArangoDBPathFinder::Step*>& result) { int res = TRI_ERROR_NO_ERROR; for (auto const& edgeCollection : _block->_collectionInfos) { TRI_ASSERT(edgeCollection != nullptr); VPackBuilder edgesBuilder; if (_reverse) { res = edgeCollection->getReverseEdgesCoordinator(source, edgesBuilder); } else { res = edgeCollection->getEdgesCoordinator(source, edgesBuilder); } if (res != TRI_ERROR_NO_ERROR) { THROW_ARANGO_EXCEPTION(res); } std::unordered_map<VPackSlice, size_t> candidates; auto inserter = [&](VPackSlice const& s, VPackSlice const& t, double currentWeight, VPackSlice const& edge) { auto cand = candidates.find(t); if (cand == candidates.end()) { // Add weight auto step = std::make_unique<ArangoDBPathFinder::Step>( t, s, currentWeight, std::move(edge)); result.emplace_back(step.release()); candidates.emplace(t, result.size() - 1); } else { // Compare weight auto old = result[cand->second]; auto oldWeight = old->weight(); if (currentWeight < oldWeight) { old->setWeight(currentWeight); old->_predecessor = s; old->_edge = edge; } } }; VPackSlice edges = edgesBuilder.slice().get("edges"); for (auto const& edge : VPackArrayIterator(edges)) { VPackSlice from = arangodb::Transaction::extractFromFromDocument(edge); VPackSlice to = arangodb::Transaction::extractToFromDocument(edge); double currentWeight = edgeCollection->weightEdge(edge); if (from == source) { inserter(from, to, currentWeight, edge); } else { inserter(to, from, currentWeight, edge); } } _block->_coordinatorCache.emplace_back(edgesBuilder.steal()); } }
bool Node::handle<PREPEND>(VPackSlice const& slice) { if (!slice.hasKey("new")) { LOG_TOPIC(WARN, Logger::AGENCY) << "Operator prepend without new value: " << slice.toJson(); return false; } Builder tmp; tmp.openArray(); tmp.add(slice.get("new")); if (this->slice().isArray()) { for (auto const& old : VPackArrayIterator(this->slice())) tmp.add(old); } tmp.close(); *this = tmp.slice(); return true; }
void VelocyPackHelper::SanitizeExternals(VPackSlice const input, VPackBuilder& output) { if (input.isExternal()) { output.add(input.resolveExternal()); } else if (input.isObject()) { output.openObject(); for (auto const& it : VPackObjectIterator(input)) { output.add(VPackValue(it.key.copyString())); SanitizeExternals(it.value, output); } output.close(); } else if (input.isArray()) { output.openArray(); for (auto const& it : VPackArrayIterator(input)) { SanitizeExternals(it, output); } output.close(); } else { output.add(input); } }
bool TraverserExpression::matchesCheck(arangodb::Transaction* trx, VPackSlice const& element) const { TRI_ASSERT(trx != nullptr); VPackSlice base = arangodb::basics::VelocyPackHelper::EmptyObjectValue(); VPackSlice value = element.resolveExternal(); // initialize compare value to Null VPackSlice result = arangodb::basics::VelocyPackHelper::NullValue(); // perform recursive check. this may modify value if (recursiveCheck(varAccess, value, base)) { result = value; } // hack for _id attribute TransactionBuilderLeaser builder(trx); if (result.isCustom() && base.isObject()) { builder->add(VPackValue(trx->extractIdString(base))); result = builder->slice(); } TRI_ASSERT(compareTo != nullptr); VPackOptions* options = trx->transactionContext()->getVPackOptions(); switch (comparisonType) { case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_EQ: return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), false, options) == 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_NE: return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), false, options) != 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_LT: return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) < 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_LE: return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) <= 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_GE: return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) >= 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_GT: return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) > 0; case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_IN: { // In means any of the elements in compareTo is identical VPackSlice compareArray = compareTo->slice(); for (auto const& cmp : VPackArrayIterator(compareArray)) { if (arangodb::basics::VelocyPackHelper::compare(result, cmp, false, options) == 0) { // One is identical return true; } } // If we get here non is identical return false; } case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_NIN: { // NIN means none of the elements in compareTo is identical VPackSlice compareArray = compareTo->slice(); for (auto const& cmp : VPackArrayIterator(compareArray)) { if (arangodb::basics::VelocyPackHelper::compare(result, cmp, false, options) == 0) { // One is identical return false; } } // If we get here non is identical return true; } default: TRI_ASSERT(false); } return false; }