mirror of https://gitee.com/bigwinds/arangodb
Converted rest handler for explain from JS to C++. (#2907)
This commit is contained in:
parent
871ee6a85f
commit
5f772b09a7
|
@ -283,6 +283,7 @@ SET(ARANGOD_SOURCES
|
|||
RestHandler/RestEdgesHandler.cpp
|
||||
RestHandler/RestEndpointHandler.cpp
|
||||
RestHandler/RestEngineHandler.cpp
|
||||
RestHandler/RestExplainHandler.cpp
|
||||
RestHandler/RestImportHandler.cpp
|
||||
RestHandler/RestIndexHandler.cpp
|
||||
RestHandler/RestJobHandler.cpp
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "RestHandler/RestEdgesHandler.h"
|
||||
#include "RestHandler/RestEndpointHandler.h"
|
||||
#include "RestHandler/RestEngineHandler.h"
|
||||
#include "RestHandler/RestExplainHandler.h"
|
||||
#include "RestHandler/RestHandlerCreator.h"
|
||||
#include "RestHandler/RestImportHandler.h"
|
||||
#include "RestHandler/RestIndexHandler.h"
|
||||
|
@ -422,6 +423,9 @@ void GeneralServerFeature::defineHandlers() {
|
|||
"/_api/aql-builtin",
|
||||
RestHandlerCreator<RestAqlFunctionsHandler>::createNoData);
|
||||
|
||||
_handlerFactory->addPrefixHandler(
|
||||
"/_api/explain", RestHandlerCreator<RestExplainHandler>::createNoData);
|
||||
|
||||
_handlerFactory->addPrefixHandler(
|
||||
"/_api/query", RestHandlerCreator<RestQueryHandler>::createNoData);
|
||||
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Dr. Frank Celler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RestExplainHandler.h"
|
||||
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/QueryString.h"
|
||||
#include "Logger/Logger.h"
|
||||
|
||||
#include <velocypack/Builder.h>
|
||||
|
||||
using namespace arangodb;
|
||||
using namespace arangodb::basics;
|
||||
using namespace arangodb::rest;
|
||||
|
||||
RestExplainHandler::RestExplainHandler(GeneralRequest* request,
|
||||
GeneralResponse* response)
|
||||
: RestVocbaseBaseHandler(request, response) {}
|
||||
|
||||
RestStatus RestExplainHandler::execute() {
|
||||
// extract the sub-request type
|
||||
auto const type = _request->requestType();
|
||||
|
||||
// execute one of the CRUD methods
|
||||
switch (type) {
|
||||
case rest::RequestType::POST:
|
||||
explainQuery();
|
||||
break;
|
||||
default: { generateNotImplemented("Unsupported method"); }
|
||||
}
|
||||
|
||||
// this handler is done
|
||||
return RestStatus::DONE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief was docuBlock REST_DOCUMENT_CREATE
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RestExplainHandler::explainQuery() {
|
||||
std::vector<std::string> const& suffixes = _request->suffixes();
|
||||
if (suffixes.size() != 0) {
|
||||
generateError(rest::ResponseCode::NOT_FOUND, TRI_ERROR_HTTP_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_vocbase == nullptr) {
|
||||
generateError(rest::ResponseCode::NOT_FOUND,
|
||||
TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
bool parseSuccess = true;
|
||||
std::shared_ptr<VPackBuilder> parsedBody = parseVelocyPackBody(parseSuccess);
|
||||
|
||||
if (!parseSuccess) {
|
||||
return;
|
||||
}
|
||||
VPackSlice body = parsedBody.get()->slice();
|
||||
|
||||
auto badParamError = [&](std::string const& msg) -> void {
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_BAD_PARAMETER, msg);
|
||||
};
|
||||
|
||||
if (!body.isObject() || body.length() < 1 || body.length() > 3) {
|
||||
badParamError(
|
||||
"expected usage: AQL_EXPLAIN(<queryString>, <bindVars>, "
|
||||
"<options>)");
|
||||
return;
|
||||
}
|
||||
|
||||
VPackSlice const querySlice = body.get("query");
|
||||
if (!querySlice.isString()) {
|
||||
badParamError("expecting string for <queryString>");
|
||||
return;
|
||||
}
|
||||
std::string const queryString(querySlice.copyString());
|
||||
|
||||
VPackSlice const bindSlice = body.get("bindVars");
|
||||
if (!bindSlice.isNone() && !bindSlice.isObject()) {
|
||||
badParamError("expecting object for <bindVars>");
|
||||
return;
|
||||
}
|
||||
|
||||
VPackSlice const optionsSlice = body.get("options");
|
||||
if (!optionsSlice.isNone() && !optionsSlice.isObject()) {
|
||||
badParamError("expecting object for <options>");
|
||||
return;
|
||||
}
|
||||
|
||||
auto bindBuilder = std::make_shared<VPackBuilder>();
|
||||
bindBuilder->add(bindSlice);
|
||||
|
||||
auto optionsBuilder = std::make_shared<VPackBuilder>();
|
||||
optionsBuilder->add(optionsSlice);
|
||||
|
||||
arangodb::aql::Query query(false, _vocbase, aql::QueryString(queryString),
|
||||
bindBuilder, optionsBuilder,
|
||||
arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.explain();
|
||||
|
||||
if (queryResult.code != TRI_ERROR_NO_ERROR) {
|
||||
auto code = rest::ResponseCode::BAD;
|
||||
|
||||
switch (queryResult.code) {
|
||||
case TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND:
|
||||
code = rest::ResponseCode::NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
generateError(code, queryResult.code, queryResult.details);
|
||||
return;
|
||||
}
|
||||
|
||||
VPackBuilder result;
|
||||
result.openObject();
|
||||
|
||||
if (query.queryOptions().allPlans) {
|
||||
result.add("plans", queryResult.result->slice());
|
||||
} else {
|
||||
result.add("plan", queryResult.result->slice());
|
||||
result.add("cacheable", VPackValue(queryResult.cached));
|
||||
}
|
||||
|
||||
if (queryResult.warnings == nullptr) {
|
||||
result.add("warnings", VPackSlice::emptyArraySlice());
|
||||
} else {
|
||||
result.add("warnings", queryResult.warnings->slice());
|
||||
}
|
||||
if (queryResult.stats != nullptr) {
|
||||
VPackSlice stats = queryResult.stats->slice();
|
||||
if (stats.isNone()) {
|
||||
result.add("stats", VPackSlice::noneSlice());
|
||||
} else {
|
||||
result.add("stats", stats);
|
||||
}
|
||||
} else {
|
||||
result.add("stats", VPackSlice::noneSlice());
|
||||
}
|
||||
|
||||
result.add("error", VPackValue(false));
|
||||
result.add("code", VPackValue(static_cast<int>(rest::ResponseCode::OK)));
|
||||
|
||||
result.close();
|
||||
|
||||
generateResult(rest::ResponseCode::OK, result.slice());
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Dr. Frank Celler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_REST_HANDLER_REST_EXPLAIN_HANDLER_H
|
||||
#define ARANGOD_REST_HANDLER_REST_EXPLAIN_HANDLER_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "RestHandler/RestVocbaseBaseHandler.h"
|
||||
|
||||
namespace arangodb {
|
||||
class RestExplainHandler : public RestVocbaseBaseHandler {
|
||||
public:
|
||||
RestExplainHandler(GeneralRequest*, GeneralResponse*);
|
||||
|
||||
public:
|
||||
RestStatus execute() override final;
|
||||
char const* name() const override final { return "RestExplainHandler"; }
|
||||
|
||||
protected:
|
||||
void explainQuery();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,99 +0,0 @@
|
|||
/* jshint strict: false */
|
||||
/* global AQL_EXPLAIN */
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
// / @brief query explain actions
|
||||
// /
|
||||
// / @file
|
||||
// /
|
||||
// / DISCLAIMER
|
||||
// /
|
||||
// / Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
||||
// /
|
||||
// / Licensed under the Apache License, Version 2.0 (the "License")
|
||||
// / you may not use this file except in compliance with the License.
|
||||
// / You may obtain a copy of the License at
|
||||
// /
|
||||
// / http://www.apache.org/licenses/LICENSE-2.0
|
||||
// /
|
||||
// / Unless required by applicable law or agreed to in writing, software
|
||||
// / distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// / WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// / See the License for the specific language governing permissions and
|
||||
// / limitations under the License.
|
||||
// /
|
||||
// / Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
// /
|
||||
// / @author Jan Steemann
|
||||
// / @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
||||
// / @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var actions = require('@arangodb/actions');
|
||||
var ERRORS = require('internal').errors;
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
// / @brief was docuBlock JSF_post_api_explain
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function post_api_explain (req, res) {
|
||||
if (req.suffix.length !== 0) {
|
||||
actions.resultNotFound(req,
|
||||
res,
|
||||
ERRORS.ERROR_HTTP_NOT_FOUND.code,
|
||||
ERRORS.ERROR_HTTP_NOT_FOUND.message);
|
||||
return;
|
||||
}
|
||||
|
||||
var json = actions.getJsonBody(req, res);
|
||||
|
||||
if (json === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
var result = AQL_EXPLAIN(json.query, json.bindVars, json.options || { });
|
||||
|
||||
if (result instanceof Error) {
|
||||
actions.resultException(req, res, result, undefined, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.hasOwnProperty('plans')) {
|
||||
result = {
|
||||
plans: result.plans,
|
||||
warnings: result.warnings,
|
||||
stats: result.stats
|
||||
};
|
||||
} else {
|
||||
result = {
|
||||
plan: result.plan,
|
||||
warnings: result.warnings,
|
||||
stats: result.stats,
|
||||
cacheable: result.cacheable
|
||||
};
|
||||
}
|
||||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
// / @brief explain gateway
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url: '_api/explain',
|
||||
|
||||
callback: function (req, res) {
|
||||
try {
|
||||
switch (req.requestType) {
|
||||
case actions.POST:
|
||||
post_api_explain(req, res);
|
||||
break;
|
||||
|
||||
default:
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
} catch (err) {
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue