diff --git a/arangod/Aql/Query.cpp b/arangod/Aql/Query.cpp index 9fb2194d0f..e4285aa7f2 100644 --- a/arangod/Aql/Query.cpp +++ b/arangod/Aql/Query.cpp @@ -541,10 +541,10 @@ QueryResult Query::execute(QueryRegistry* registry) { } } - QueryResult res = prepare(registry); + QueryResult result = prepare(registry); - if (res.code != TRI_ERROR_NO_ERROR) { - return res; + if (result.code != TRI_ERROR_NO_ERROR) { + return result; } if (_queryString == nullptr) { @@ -631,11 +631,12 @@ QueryResult Query::execute(QueryRegistry* registry) { auto stats = std::make_shared(); _engine->_stats.toVelocyPack(*(stats.get())); + result.context = _trx->transactionContext(); + cleanupPlanAndEngine(TRI_ERROR_NO_ERROR); enterState(FINALIZATION); - QueryResult result(TRI_ERROR_NO_ERROR); result.warnings = warningsToVelocyPack(); result.result = resultBuilder; result.stats = stats; @@ -700,10 +701,10 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) { } } - QueryResultV8 res = prepare(registry); + QueryResultV8 result = prepare(registry); - if (res.code != TRI_ERROR_NO_ERROR) { - return res; + if (result.code != TRI_ERROR_NO_ERROR) { + return result; } work.reset(new AqlWorkStack(_vocbase, _id, _queryString, _queryLength)); @@ -715,7 +716,6 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) { useQueryCache = false; } - QueryResultV8 result(TRI_ERROR_NO_ERROR); result.result = v8::Array::New(isolate); // this is the RegisterId our results can be found in @@ -781,6 +781,8 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) { auto stats = std::make_shared(); _engine->_stats.toVelocyPack(*(stats.get())); + result.context = _trx->transactionContext(); + cleanupPlanAndEngine(TRI_ERROR_NO_ERROR); enterState(FINALIZATION); diff --git a/arangod/Aql/QueryResult.h b/arangod/Aql/QueryResult.h index 34b44292db..7e2e692ca0 100644 --- a/arangod/Aql/QueryResult.h +++ b/arangod/Aql/QueryResult.h @@ -30,23 +30,14 @@ namespace arangodb { namespace velocypack { class Builder; } + +class TransactionContext; + namespace aql { struct QueryResult { QueryResult& operator=(QueryResult const& other) = delete; - - QueryResult(QueryResult&& other) { - code = other.code; - cached = other.cached; - details = other.details; - warnings.swap(other.warnings); - result.swap(other.result); - stats.swap(other.stats); - profile.swap(other.profile); - - bindParameters = other.bindParameters; - collectionNames = other.collectionNames; - } + QueryResult(QueryResult&& other) = default; QueryResult(int code, std::string const& details) : code(code), @@ -54,7 +45,8 @@ struct QueryResult { details(details), warnings(nullptr), result(nullptr), - profile(nullptr) {} + profile(nullptr), + context(nullptr) {} explicit QueryResult(int code) : QueryResult(code, "") {} @@ -71,6 +63,7 @@ struct QueryResult { std::shared_ptr result; std::shared_ptr stats; std::shared_ptr profile; + std::shared_ptr context; }; } } diff --git a/arangod/RestHandler/RestCursorHandler.cpp b/arangod/RestHandler/RestCursorHandler.cpp index 80b53ade46..a9b9d0cc01 100644 --- a/arangod/RestHandler/RestCursorHandler.cpp +++ b/arangod/RestHandler/RestCursorHandler.cpp @@ -177,10 +177,9 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) { THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); } - auto transactionContext = std::make_shared(_vocbase); arangodb::basics::VPackStringBufferAdapter bufferAdapter( _response->body().stringBuffer()); - VPackDumper dumper(&bufferAdapter, transactionContext->getVPackOptions()); + VPackDumper dumper(&bufferAdapter, queryResult.context->getVPackOptions()); dumper.dump(result.slice()); return; } @@ -195,8 +194,8 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) { opts, "count", false); // steal the query result, cursor will take over the ownership - arangodb::JsonCursor* cursor = cursors->createFromVelocyPack( - queryResult.result, batchSize, extra, ttl, count, queryResult.cached); + arangodb::VelocyPackCursor* cursor = cursors->createFromQueryResult( + std::move(queryResult), batchSize, extra, ttl, count); try { _response->body().appendChar('{'); diff --git a/arangod/Utils/Cursor.cpp b/arangod/Utils/Cursor.cpp index eb3398c1d4..fe3adc91f0 100644 --- a/arangod/Utils/Cursor.cpp +++ b/arangod/Utils/Cursor.cpp @@ -22,7 +22,6 @@ //////////////////////////////////////////////////////////////////////////////// #include "Cursor.h" -#include "Basics/JsonHelper.h" #include "Basics/VelocyPackHelper.h" #include "Basics/VPackStringBufferAdapter.h" #include "Utils/CollectionExport.h" @@ -63,20 +62,20 @@ VPackSlice Cursor::extra() const { return _extra->slice(); } -JsonCursor::JsonCursor(TRI_vocbase_t* vocbase, CursorId id, - std::shared_ptr json, size_t batchSize, - std::shared_ptr extra, double ttl, - bool hasCount, bool cached) +VelocyPackCursor::VelocyPackCursor(TRI_vocbase_t* vocbase, CursorId id, + aql::QueryResult&& result, size_t batchSize, + std::shared_ptr extra, + double ttl, bool hasCount) : Cursor(id, batchSize, extra, ttl, hasCount), _vocbase(vocbase), - _json(json), - _size(json->slice().length()), - _cached(cached) { - TRI_ASSERT(json->slice().isArray()); + _result(std::move(result)), + _size(result.result->slice().length()), + _cached(result.cached) { + TRI_ASSERT(result.result->slice().isArray()); TRI_UseVocBase(vocbase); } -JsonCursor::~JsonCursor() { +VelocyPackCursor::~VelocyPackCursor() { freeJson(); TRI_ReleaseVocBase(_vocbase); @@ -86,7 +85,7 @@ JsonCursor::~JsonCursor() { /// @brief check whether the cursor contains more data //////////////////////////////////////////////////////////////////////////////// -bool JsonCursor::hasNext() { +bool VelocyPackCursor::hasNext() { if (_position < _size) { return true; } @@ -99,10 +98,10 @@ bool JsonCursor::hasNext() { /// @brief return the next element //////////////////////////////////////////////////////////////////////////////// -VPackSlice JsonCursor::next() { - TRI_ASSERT(_json != nullptr); +VPackSlice VelocyPackCursor::next() { + TRI_ASSERT(_result.result != nullptr); TRI_ASSERT(_position < _size); - VPackSlice slice = _json->slice(); + VPackSlice slice = _result.result->slice(); return slice.at(_position++); } @@ -110,13 +109,13 @@ VPackSlice JsonCursor::next() { /// @brief return the cursor size //////////////////////////////////////////////////////////////////////////////// -size_t JsonCursor::count() const { return _size; } +size_t VelocyPackCursor::count() const { return _size; } //////////////////////////////////////////////////////////////////////////////// /// @brief dump the cursor contents into a string buffer //////////////////////////////////////////////////////////////////////////////// -void JsonCursor::dump(arangodb::basics::StringBuffer& buffer) { +void VelocyPackCursor::dump(arangodb::basics::StringBuffer& buffer) { buffer.appendText("\"result\":["); size_t const n = batchSize(); @@ -135,6 +134,9 @@ void JsonCursor::dump(arangodb::basics::StringBuffer& buffer) { } } + arangodb::basics::VPackStringBufferAdapter bufferAdapter( + buffer.stringBuffer()); + VPackDumper dumper(&bufferAdapter, transactionContext->getVPackOptions()); for (size_t i = 0; i < n; ++i) { if (!hasNext()) { break; @@ -149,9 +151,6 @@ void JsonCursor::dump(arangodb::basics::StringBuffer& buffer) { THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); } - arangodb::basics::VPackStringBufferAdapter bufferAdapter( - buffer.stringBuffer()); - VPackDumper dumper(&bufferAdapter, transactionContext->getVPackOptions()); try { dumper.dump(row); } catch (...) { @@ -198,9 +197,7 @@ void JsonCursor::dump(arangodb::basics::StringBuffer& buffer) { /// @brief free the internals //////////////////////////////////////////////////////////////////////////////// -void JsonCursor::freeJson() { - _json = nullptr; - +void VelocyPackCursor::freeJson() { _isDeleted = true; } diff --git a/arangod/Utils/Cursor.h b/arangod/Utils/Cursor.h index 7e94ba06d4..4b9a25749e 100644 --- a/arangod/Utils/Cursor.h +++ b/arangod/Utils/Cursor.h @@ -26,6 +26,7 @@ #include "Basics/Common.h" #include "Basics/StringBuffer.h" +#include "Aql/QueryResult.h" #include "VocBase/voc-types.h" struct TRI_vocbase_t; @@ -107,14 +108,13 @@ class Cursor { bool _isUsed; }; -class JsonCursor : public Cursor { +class VelocyPackCursor : public Cursor { public: - JsonCursor(TRI_vocbase_t*, CursorId, - std::shared_ptr, size_t, - std::shared_ptr, double, bool, - bool); + VelocyPackCursor(TRI_vocbase_t*, CursorId, aql::QueryResult&&, size_t, + std::shared_ptr, double, + bool); - ~JsonCursor(); + ~VelocyPackCursor(); public: bool hasNext() override final; @@ -130,7 +130,7 @@ class JsonCursor : public Cursor { private: TRI_vocbase_t* _vocbase; - std::shared_ptr _json; + aql::QueryResult _result; size_t const _size; bool _cached; }; diff --git a/arangod/Utils/CursorRepository.cpp b/arangod/Utils/CursorRepository.cpp index 39cc8cab6a..dfb50de8b2 100644 --- a/arangod/Utils/CursorRepository.cpp +++ b/arangod/Utils/CursorRepository.cpp @@ -91,17 +91,15 @@ CursorRepository::~CursorRepository() { /// the cursor will take ownership of both json and extra //////////////////////////////////////////////////////////////////////////////// -JsonCursor* CursorRepository::createFromVelocyPack( - std::shared_ptr json, size_t batchSize, - std::shared_ptr extra, double ttl, bool count, bool cached) { - - TRI_ASSERT(json != nullptr); +VelocyPackCursor* CursorRepository::createFromQueryResult( + aql::QueryResult&& result, size_t batchSize, std::shared_ptr extra, + double ttl, bool count) { + TRI_ASSERT(result.result != nullptr); CursorId const id = TRI_NewTickServer(); - arangodb::JsonCursor* cursor = nullptr; - cursor = new arangodb::JsonCursor(_vocbase, id, json, batchSize, extra, ttl, - count, cached); + arangodb::VelocyPackCursor* cursor = new arangodb::VelocyPackCursor( + _vocbase, id, std::move(result), batchSize, extra, ttl, count); cursor->use(); try { diff --git a/arangod/Utils/CursorRepository.h b/arangod/Utils/CursorRepository.h index adff37aabe..1d2ae7439b 100644 --- a/arangod/Utils/CursorRepository.h +++ b/arangod/Utils/CursorRepository.h @@ -36,6 +36,10 @@ namespace velocypack { class Builder; } +namespace aql { +struct QueryResult; +} + class CollectionExport; class CursorRepository { @@ -60,9 +64,9 @@ class CursorRepository { /// the cursor will retain a shared pointer of both json and extra ////////////////////////////////////////////////////////////////////////////// - JsonCursor* createFromVelocyPack( - std::shared_ptr, size_t, - std::shared_ptr, double, bool, bool); + VelocyPackCursor* createFromQueryResult( + aql::QueryResult&&, size_t, std::shared_ptr, + double, bool); ////////////////////////////////////////////////////////////////////////////// /// @brief creates a cursor and stores it in the registry diff --git a/arangod/V8Server/v8-voccursor.cpp b/arangod/V8Server/v8-voccursor.cpp index a73f447787..401ea5b885 100644 --- a/arangod/V8Server/v8-voccursor.cpp +++ b/arangod/V8Server/v8-voccursor.cpp @@ -25,6 +25,7 @@ #include "Basics/conversions.h" #include "Utils/Cursor.h" #include "Utils/CursorRepository.h" +#include "Utils/StandaloneTransactionContext.h" #include "V8/v8-conv.h" #include "V8/v8-vpack.h" #include "V8Server/v8-voccursor.h" @@ -88,9 +89,14 @@ static void JS_CreateCursor(v8::FunctionCallbackInfo const& args) { auto cursors = static_cast(vocbase->_cursorRepository); + arangodb::aql::QueryResult result(TRI_ERROR_NO_ERROR); + result.result = builder; + result.cached = false; + result.context = std::make_shared(vocbase); + try { - arangodb::Cursor* cursor = cursors->createFromVelocyPack( - builder, static_cast(batchSize), nullptr, ttl, true, false); + arangodb::Cursor* cursor = cursors->createFromQueryResult( + std::move(result), static_cast(batchSize), nullptr, ttl, true); TRI_ASSERT(cursor != nullptr); cursors->release(cursor);