diff --git a/arangod/Aql/RestAqlHandler.cpp b/arangod/Aql/RestAqlHandler.cpp index 886b87e4b3..c9a4f4812e 100644 --- a/arangod/Aql/RestAqlHandler.cpp +++ b/arangod/Aql/RestAqlHandler.cpp @@ -119,19 +119,13 @@ void RestAqlHandler::createQueryFromJson () { Json plan; Json options; - try { - plan = queryJson.get("plan").copy(); - } - catch (...) { + plan = queryJson.get("plan").copy(); // cannot throw + if (plan.isEmpty()) { generateError(HttpResponse::BAD, TRI_ERROR_INTERNAL, "body must be an object with attribute \"plan\""); return; } - try { - options = queryJson.get("options").copy(); - } - catch (...) { - } + options = queryJson.get("options").copy(); auto query = new Query(vocbase, plan, options.steal()); QueryResult res = query->prepare(); @@ -193,6 +187,33 @@ void RestAqlHandler::parseQuery () { //////////////////////////////////////////////////////////////////////////////// void RestAqlHandler::explainQuery () { + Json queryJson(TRI_UNKNOWN_MEM_ZONE, parseJsonBody()); + if (queryJson.isEmpty()) { + return; + } + + TRI_vocbase_t* vocbase = GetContextVocBase(); + if (vocbase == nullptr) { + generateError(HttpResponse::BAD, + TRI_ERROR_INTERNAL, "cannot get vocbase from context"); + return; + } + + Json queryString; + Json parameters; + Json options; + + queryString = queryJson.get("plan").copy(); // cannot throw + if (queryString.isEmpty()) { + generateError(HttpResponse::BAD, TRI_ERROR_INTERNAL, + "body must be an object with attribute \"plan\""); + return; + } + parameters = queryJson.get("parameters").copy(); // cannot throw + options = queryJson.get("options").copy(); // cannot throw + + // ... + _response = createResponse(triagens::rest::HttpResponse::OK); _response->setContentType("application/json; charset=utf-8"); Json answerBody(Json::Array, 1); diff --git a/arangod/RestServer/ArangoServer.cpp b/arangod/RestServer/ArangoServer.cpp index 2d42bf16c8..7a3e7f3da5 100644 --- a/arangod/RestServer/ArangoServer.cpp +++ b/arangod/RestServer/ArangoServer.cpp @@ -846,6 +846,7 @@ int ArangoServer::startupServer () { _pairForAql = new std::pair; _pairForAql->first = _applicationV8; _pairForAql->second = _queryRegistry; + _server->_queryRegistry = static_cast(_queryRegistry); // ........................................................................... // create endpoints and handlers @@ -915,6 +916,8 @@ int ArangoServer::startupServer () { _applicationServer->stop(); + _server->_queryRegistry = nullptr; + delete _queryRegistry; _queryRegistry = nullptr; delete _pairForAql; diff --git a/arangod/VocBase/server.cpp b/arangod/VocBase/server.cpp index 5b14d14767..3a581e941d 100644 --- a/arangod/VocBase/server.cpp +++ b/arangod/VocBase/server.cpp @@ -35,6 +35,7 @@ #include +#include "Aql/QueryRegistry.h" #include "Basics/conversions.h" #include "Basics/files.h" #include "Basics/hashes.h" @@ -1493,6 +1494,12 @@ static void DatabaseManager (void* data) { } usleep(DATABASE_MANAGER_INTERVAL); + // The following is only necessary after a wait: + auto queryRegistry = static_cast + (server->_queryRegistry); + if (queryRegistry != nullptr) { + queryRegistry->expireQueries(); + } } // next iteration @@ -1626,6 +1633,8 @@ int TRI_InitServer (TRI_server_t* server, server->_disableReplicationAppliers = disableAppliers; + server->_queryRegistry = nullptr; // will be filled in later + server->_initialised = true; return TRI_ERROR_NO_ERROR; diff --git a/arangod/VocBase/server.h b/arangod/VocBase/server.h index 512aa136ca..f3aa0db507 100644 --- a/arangod/VocBase/server.h +++ b/arangod/VocBase/server.h @@ -74,6 +74,7 @@ typedef struct TRI_server_s { bool _hasCreatedSystemDatabase; bool _initialised; + void* _queryRegistry; } TRI_server_t;