1
0
Fork 0

Aql/QueryResult now only uses VelocyPack instead of TRI_json_t. Also adapted all calling places

This commit is contained in:
Michael Hackstein 2016-03-08 13:08:05 +01:00
parent 0552cd54c3
commit e60e7a3652
16 changed files with 216 additions and 194 deletions

View File

@ -141,9 +141,11 @@ Ast::~Ast() {}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief convert the AST into JSON /// @brief convert the AST into JSON
/// the caller is responsible for freeing the JSON later /// the caller is responsible for freeing the JSON later
/// @DEPRECATED
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
TRI_json_t* Ast::toJson(TRI_memory_zone_t* zone, bool verbose) const { TRI_json_t* Ast::toJson(TRI_memory_zone_t* zone, bool verbose) const {
#warning Deprecated
TRI_json_t* json = TRI_CreateArrayJson(zone); TRI_json_t* json = TRI_CreateArrayJson(zone);
if (json == nullptr) { if (json == nullptr) {
@ -160,6 +162,19 @@ TRI_json_t* Ast::toJson(TRI_memory_zone_t* zone, bool verbose) const {
return json; return json;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief convert the AST into VelocyPack
////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<VPackBuilder> Ast::toVelocyPack(bool verbose) const {
auto builder = std::make_shared<VPackBuilder>();
{
VPackArrayBuilder guard(builder.get());
_root->toVelocyPack(*builder, verbose);
}
return builder;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the AST /// @brief destroy the AST
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -184,10 +184,17 @@ class Ast {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief convert the AST into JSON /// @brief convert the AST into JSON
/// the caller is responsible for freeing the JSON later /// the caller is responsible for freeing the JSON later
/// @DEPRECATED
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
TRI_json_t* toJson(TRI_memory_zone_t*, bool) const; TRI_json_t* toJson(TRI_memory_zone_t*, bool) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief convert the AST into JSON
//////////////////////////////////////////////////////////////////////////////
std::shared_ptr<arangodb::velocypack::Builder> toVelocyPack(bool) const;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief add an operation to the root node /// @brief add an operation to the root node
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View File

@ -472,6 +472,7 @@ struct CoordinatorInstanciator : public WalkerWorker<ExecutionNode> {
EngineInfo const& info, Collection* collection, EngineInfo const& info, Collection* collection,
QueryId& connectedId, std::string const& shardId, QueryId& connectedId, std::string const& shardId,
TRI_json_t* jsonPlan) { TRI_json_t* jsonPlan) {
#warning still Json inplace. Needs to be fixed
// create a JSON representation of the plan // create a JSON representation of the plan
Json result(Json::Object); Json result(Json::Object);
@ -487,8 +488,10 @@ struct CoordinatorInstanciator : public WalkerWorker<ExecutionNode> {
"type", Json(TRI_TransactionTypeGetStr(collection->accessType)))); "type", Json(TRI_TransactionTypeGetStr(collection->accessType))));
jsonNodesList.set("collections", jsonCollectionsList); jsonNodesList.set("collections", jsonCollectionsList);
jsonNodesList.set("variables",
query->ast()->variables()->toJson(TRI_UNKNOWN_MEM_ZONE)); VPackBuilder tmp;
query->ast()->variables()->toVelocyPack(tmp);
jsonNodesList.set("variables", arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice()));
result.set("plan", jsonNodesList); result.set("plan", jsonNodesList);
if (info.part == arangodb::aql::PART_MAIN) { if (info.part == arangodb::aql::PART_MAIN) {

View File

@ -214,10 +214,12 @@ ExecutionPlan* ExecutionPlan::clone(Query const& query) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief export to JSON, returns an AUTOFREE Json object /// @brief export to JSON, returns an AUTOFREE Json object
/// DEPRECATED
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
arangodb::basics::Json ExecutionPlan::toJson(Ast* ast, TRI_memory_zone_t* zone, arangodb::basics::Json ExecutionPlan::toJson(Ast* ast, TRI_memory_zone_t* zone,
bool verbose) const { bool verbose) const {
#warning Remove this
// TODO // TODO
VPackBuilder b; VPackBuilder b;
_root->toVelocyPack(b, verbose); _root->toVelocyPack(b, verbose);
@ -247,7 +249,10 @@ arangodb::basics::Json ExecutionPlan::toJson(Ast* ast, TRI_memory_zone_t* zone,
} }
result.set("collections", jsonCollectionList); result.set("collections", jsonCollectionList);
result.set("variables", ast->variables()->toJson(TRI_UNKNOWN_MEM_ZONE));
VPackBuilder tmpTwo;
ast->variables()->toVelocyPack(tmpTwo);
result.set("variables", arangodb::basics::VelocyPackHelper::velocyPackToJson(tmpTwo.slice()));
size_t nrItems = 0; size_t nrItems = 0;
result.set("estimatedCost", arangodb::basics::Json(_root->getCost(nrItems))); result.set("estimatedCost", arangodb::basics::Json(_root->getCost(nrItems)));
result.set("estimatedNrItems", result.set("estimatedNrItems",
@ -256,6 +261,41 @@ arangodb::basics::Json ExecutionPlan::toJson(Ast* ast, TRI_memory_zone_t* zone,
return result; return result;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief export to VelocyPack
////////////////////////////////////////////////////////////////////////////////
void ExecutionPlan::toVelocyPack(Ast* ast, bool verbose,
VPackBuilder& builder) const {
_root->toVelocyPack(builder, verbose);
// set up rules
auto appliedRules(Optimizer::translateRules(_appliedRules));
builder.add(VPackValue("rules"));
{
VPackArrayBuilder guard(&builder);
for (auto const& r : appliedRules) {
builder.add(VPackValue(r));
}
}
builder.add(VPackValue("collections"));
auto usedCollections = *ast->query()->collections()->collections();
{
VPackArrayBuilder guard(&builder);
for (auto const& c : usedCollections) {
VPackObjectBuilder objGuard(&builder);
builder.add("name", VPackValue(c.first));
builder.add("type",
VPackValue(TRI_TransactionTypeGetStr(c.second->accessType)));
}
}
builder.add(VPackValue("variables"));
ast->variables()->toVelocyPack(builder);
size_t nrItems = 0;
builder.add("estimatedCost", VPackValue(_root->getCost(nrItems)));
builder.add("estimatedNrItems", VPackValue(nrItems));
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get a list of all applied rules /// @brief get a list of all applied rules
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -96,6 +96,12 @@ class ExecutionPlan {
arangodb::basics::Json toJson(Ast* ast, TRI_memory_zone_t* zone, arangodb::basics::Json toJson(Ast* ast, TRI_memory_zone_t* zone,
bool verbose) const; bool verbose) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief export to VelocyPack
//////////////////////////////////////////////////////////////////////////////
void toVelocyPack(Ast*, bool, arangodb::velocypack::Builder&) const;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief check if the plan is empty /// @brief check if the plan is empty
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View File

@ -117,7 +117,7 @@ QueryResult Parser::parse(bool withDetails) {
if (withDetails) { if (withDetails) {
result.collectionNames = _query->collectionNames(); result.collectionNames = _query->collectionNames();
result.bindParameters = _ast->bindParameters(); result.bindParameters = _ast->bindParameters();
result.json = _ast->toJson(TRI_UNKNOWN_MEM_ZONE, false); result.result = _ast->toVelocyPack(false);
} }
return result; return result;

View File

@ -612,19 +612,10 @@ QueryResult Query::execute(QueryRegistry* registry) {
if (cacheEntry != nullptr) { if (cacheEntry != nullptr) {
// got a result from the query cache // got a result from the query cache
QueryResult res(TRI_ERROR_NO_ERROR); QueryResult res(TRI_ERROR_NO_ERROR);
#warning Replace QueryResult with VPack res.warnings = warningsToVelocyPack();
VPackBuilder tmp; TRI_ASSERT(cacheEntry->_queryResult != nullptr);
tmp.openObject(); res.result = cacheEntry->_queryResult;
warningsToVelocyPack(tmp);
tmp.close();
res.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
res.json = arangodb::basics::VelocyPackHelper::velocyPackToJson(cacheEntry->_queryResult->slice());
res.cached = true; res.cached = true;
if (res.json == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
return res; return res;
} }
} }
@ -650,14 +641,13 @@ QueryResult Query::execute(QueryRegistry* registry) {
useQueryCache = false; useQueryCache = false;
} }
arangodb::basics::Json jsonResult(arangodb::basics::Json::Array, 16);
// this is the RegisterId our results can be found in
auto const resultRegister = _engine->resultRegister();
AqlItemBlock* value = nullptr; AqlItemBlock* value = nullptr;
auto resultBuilder = std::make_shared<VPackBuilder>();
try { try {
VPackArrayBuilder guard(resultBuilder.get());
// this is the RegisterId our results can be found in
auto const resultRegister = _engine->resultRegister();
if (useQueryCache) { if (useQueryCache) {
// iterate over result, return it and store it in query cache // iterate over result, return it and store it in query cache
while (nullptr != (value = _engine->getSome( while (nullptr != (value = _engine->getSome(
@ -665,14 +655,12 @@ QueryResult Query::execute(QueryRegistry* registry) {
auto doc = value->getDocumentCollection(resultRegister); auto doc = value->getDocumentCollection(resultRegister);
size_t const n = value->size(); size_t const n = value->size();
// reserve space for n additional results at once
jsonResult.reserve(n);
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
auto val = value->getValueReference(i, resultRegister); auto val = value->getValueReference(i, resultRegister);
if (!val.isEmpty()) { if (!val.isEmpty()) {
jsonResult.add(val.toJson(_trx, doc, true)); val.toVelocyPack(_trx, doc, *resultBuilder);
} }
} }
delete value; delete value;
@ -681,14 +669,8 @@ QueryResult Query::execute(QueryRegistry* registry) {
if (_warnings.empty()) { if (_warnings.empty()) {
// finally store the generated result in the query cache // finally store the generated result in the query cache
std::shared_ptr<VPackBuilder> copy(arangodb::basics::JsonHelper::toVelocyPack(jsonResult.json()));
if (copy == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
auto result = QueryCache::instance()->store( auto result = QueryCache::instance()->store(
_vocbase, queryStringHash, _queryString, _queryLength, copy, _vocbase, queryStringHash, _queryString, _queryLength, resultBuilder,
_trx->collectionNames()); _trx->collectionNames());
if (result == nullptr) { if (result == nullptr) {
@ -702,14 +684,11 @@ QueryResult Query::execute(QueryRegistry* registry) {
auto doc = value->getDocumentCollection(resultRegister); auto doc = value->getDocumentCollection(resultRegister);
size_t const n = value->size(); size_t const n = value->size();
// reserve space for n additional results at once
jsonResult.reserve(n);
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
auto val = value->getValueReference(i, resultRegister); auto val = value->getValueReference(i, resultRegister);
if (!val.isEmpty()) { if (!val.isEmpty()) {
jsonResult.add(val.toJson(_trx, doc, true)); val.toVelocyPack(_trx, doc, *resultBuilder);
} }
} }
delete value; delete value;
@ -732,13 +711,8 @@ QueryResult Query::execute(QueryRegistry* registry) {
enterState(FINALIZATION); enterState(FINALIZATION);
QueryResult result(TRI_ERROR_NO_ERROR); QueryResult result(TRI_ERROR_NO_ERROR);
#warning Replace QueryResult with VPack result.warnings = warningsToVelocyPack();
VPackBuilder tmp; result.result = resultBuilder;
tmp.openObject();
warningsToVelocyPack(tmp);
tmp.close();
result.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
result.json = jsonResult.steal();
result.stats = stats; result.stats = stats;
if (_profile != nullptr && profiling()) { if (_profile != nullptr && profiling()) {
@ -890,12 +864,7 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
enterState(FINALIZATION); enterState(FINALIZATION);
#warning Replace QueryResult with VPack result.warnings = warningsToVelocyPack();
VPackBuilder tmp;
tmp.openObject();
warningsToVelocyPack(tmp);
tmp.close();
result.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
result.stats = stats; result.stats = stats;
if (_profile != nullptr && profiling()) { if (_profile != nullptr && profiling()) {
@ -996,21 +965,21 @@ QueryResult Query::explain() {
QueryResult result(TRI_ERROR_NO_ERROR); QueryResult result(TRI_ERROR_NO_ERROR);
QueryRegistry localRegistry; QueryRegistry localRegistry;
result.result = std::make_shared<VPackBuilder>();
if (allPlans()) { if (allPlans()) {
arangodb::basics::Json out(Json::Array); {
VPackArrayBuilder guard(result.result.get());
auto plans = opt.getPlans(); auto plans = opt.getPlans();
for (auto& it : plans) { for (auto& it : plans) {
TRI_ASSERT(it != nullptr); TRI_ASSERT(it != nullptr);
it->findVarUsage(); it->findVarUsage();
it->planRegisters(); it->planRegisters();
out.add(it->toJson(parser.ast(), TRI_UNKNOWN_MEM_ZONE, verbosePlans())); it->toVelocyPack(parser.ast(), verbosePlans(), *result.result);
}
} }
result.json = out.steal();
// cacheability not available here // cacheability not available here
result.cached = false; result.cached = false;
} else { } else {
@ -1021,9 +990,7 @@ QueryResult Query::explain() {
bestPlan->findVarUsage(); bestPlan->findVarUsage();
bestPlan->planRegisters(); bestPlan->planRegisters();
result.json = bestPlan->toVelocyPack(parser.ast(), verbosePlans(), *result.result);
bestPlan->toJson(parser.ast(), TRI_UNKNOWN_MEM_ZONE, verbosePlans())
.steal();
// cacheability // cacheability
result.cached = (_queryString != nullptr && _queryLength > 0 && result.cached = (_queryString != nullptr && _queryLength > 0 &&
@ -1033,12 +1000,7 @@ QueryResult Query::explain() {
_trx->commit(); _trx->commit();
#warning Replace QueryResult with VPack result.warnings = warningsToVelocyPack();
VPackBuilder tmp;
tmp.openObject();
warningsToVelocyPack(tmp);
tmp.close();
result.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
result.stats = opt._stats.toVelocyPack(); result.stats = opt._stats.toVelocyPack();
@ -1237,7 +1199,8 @@ bool Query::getBooleanOption(char const* option, bool defaultValue) const {
/// warnings. If there are none it will not modify the builder /// warnings. If there are none it will not modify the builder
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void Query::warningsToVelocyPack(arangodb::velocypack::Builder& builder) const { void Query::addWarningsToVelocyPackObject(
arangodb::velocypack::Builder& builder) const {
TRI_ASSERT(builder.isOpenObject()); TRI_ASSERT(builder.isOpenObject());
if (_warnings.empty()) { if (_warnings.empty()) {
return; return;
@ -1254,6 +1217,28 @@ void Query::warningsToVelocyPack(arangodb::velocypack::Builder& builder) const {
} }
} }
//////////////////////////////////////////////////////////////////////////////
/// @brief transform the list of warnings to VelocyPack.
//////////////////////////////////////////////////////////////////////////////
std::shared_ptr<VPackBuilder> Query::warningsToVelocyPack() const {
if (_warnings.empty()) {
return nullptr;
}
auto result = std::make_shared<VPackBuilder>();
{
VPackArrayBuilder guard(result.get());
size_t const n = _warnings.size();
for (size_t i = 0; i < n; ++i) {
VPackObjectBuilder objGuard(result.get());
result->add("code", VPackValue(_warnings[i].first));
result->add("message", VPackValue(_warnings[i].second));
}
}
return result;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief initializes the query /// @brief initializes the query
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -398,12 +398,19 @@ class Query {
bool getBooleanOption(char const*, bool) const; bool getBooleanOption(char const*, bool) const;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief convert the list of warnings to VelocyPack. /// @brief add the list of warnings to VelocyPack.
/// Will add a new entry { ..., warnings: <warnings>, } if there are /// Will add a new entry { ..., warnings: <warnings>, } if there are
/// warnings. If there are none it will not modify the builder /// warnings. If there are none it will not modify the builder
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void warningsToVelocyPack(arangodb::velocypack::Builder&) const; void addWarningsToVelocyPackObject(arangodb::velocypack::Builder&) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief transform the list of warnings to VelocyPack.
/// NOTE: returns nullptr if there are no warnings.
//////////////////////////////////////////////////////////////////////////////
std::shared_ptr<arangodb::velocypack::Builder> warningsToVelocyPack() const;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief fetch the global query tracking value /// @brief fetch the global query tracking value

View File

@ -40,19 +40,15 @@ struct QueryResult {
code = other.code; code = other.code;
cached = other.cached; cached = other.cached;
details = other.details; details = other.details;
warnings = other.warnings; warnings.swap(other.warnings);
json = other.json; result.swap(other.result);
stats = other.stats; stats.swap(other.stats);
profile = other.profile; profile.swap(other.profile);
zone = other.zone;
clusterplan = other.clusterplan; clusterplan = other.clusterplan;
bindParameters = other.bindParameters; bindParameters = other.bindParameters;
collectionNames = other.collectionNames; collectionNames = other.collectionNames;
other.warnings = nullptr;
other.json = nullptr;
other.stats = nullptr;
other.profile = nullptr;
other.clusterplan = nullptr; other.clusterplan = nullptr;
} }
@ -60,9 +56,8 @@ struct QueryResult {
: code(code), : code(code),
cached(false), cached(false),
details(details), details(details),
zone(TRI_UNKNOWN_MEM_ZONE),
warnings(nullptr), warnings(nullptr),
json(nullptr), result(nullptr),
profile(nullptr), profile(nullptr),
clusterplan(nullptr) {} clusterplan(nullptr) {}
@ -71,12 +66,6 @@ struct QueryResult {
QueryResult() : QueryResult(TRI_ERROR_NO_ERROR) {} QueryResult() : QueryResult(TRI_ERROR_NO_ERROR) {}
virtual ~QueryResult() { virtual ~QueryResult() {
if (warnings != nullptr) {
TRI_FreeJson(zone, warnings);
}
if (json != nullptr) {
TRI_FreeJson(zone, json);
}
} }
int code; int code;
@ -84,9 +73,8 @@ struct QueryResult {
std::string details; std::string details;
std::unordered_set<std::string> bindParameters; std::unordered_set<std::string> bindParameters;
std::vector<std::string> collectionNames; std::vector<std::string> collectionNames;
TRI_memory_zone_t* zone; std::shared_ptr<arangodb::velocypack::Builder> warnings;
TRI_json_t* warnings; std::shared_ptr<arangodb::velocypack::Builder> result;
TRI_json_t* json;
std::shared_ptr<arangodb::velocypack::Builder> stats; std::shared_ptr<arangodb::velocypack::Builder> stats;
std::shared_ptr<arangodb::velocypack::Builder> profile; std::shared_ptr<arangodb::velocypack::Builder> profile;
TRI_json_t* clusterplan; TRI_json_t* clusterplan;

View File

@ -202,14 +202,9 @@ void RestAqlHandler::parseQuery() {
answerBuilder.add(VPackValue(p)); answerBuilder.add(VPackValue(p));
} }
} }
#warning res.json has to be replaced by VPack in first-place
answerBuilder.add(VPackValue("ast")); answerBuilder.add(VPackValue("ast"));
int errCode = JsonHelper::toVelocyPack(res.json, answerBuilder); answerBuilder.add(res.result->slice());
if (errCode != TRI_ERROR_NO_ERROR) { res.result = nullptr;
#warning only temporary, wrong error does not matter at all.
generateError(HttpResponse::BAD, errCode);
}
res.json = nullptr;
} catch (...) { } catch (...) {
generateError(HttpResponse::BAD, TRI_ERROR_OUT_OF_MEMORY, generateError(HttpResponse::BAD, TRI_ERROR_OUT_OF_MEMORY,
"out of memory"); "out of memory");
@ -259,19 +254,14 @@ void RestAqlHandler::explainQuery() {
VPackBuilder answerBuilder; VPackBuilder answerBuilder;
try { try {
VPackObjectBuilder guard(&answerBuilder); VPackObjectBuilder guard(&answerBuilder);
if (res.json != nullptr) { if (res.result != nullptr) {
#warning QueryResult needs to be replaced by VPack
if (query->allPlans()) { if (query->allPlans()) {
answerBuilder.add(VPackValue("plans")); answerBuilder.add(VPackValue("plans"));
} else { } else {
answerBuilder.add(VPackValue("plan")); answerBuilder.add(VPackValue("plan"));
} }
int errCode = JsonHelper::toVelocyPack(res.json, answerBuilder); answerBuilder.add(res.result->slice());
if (errCode != TRI_ERROR_NO_ERROR) { res.result = nullptr;
#warning only temporary, wrong error does not matter at all.
generateError(HttpResponse::BAD, errCode);
}
res.json = nullptr;
} }
} catch (...) { } catch (...) {
generateError(HttpResponse::BAD, TRI_ERROR_OUT_OF_MEMORY, generateError(HttpResponse::BAD, TRI_ERROR_OUT_OF_MEMORY,
@ -842,7 +832,7 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
query->getStats(answerBuilder); query->getStats(answerBuilder);
// return warnings if present // return warnings if present
query->warningsToVelocyPack(answerBuilder); query->addWarningsToVelocyPackObject(answerBuilder);
// delete the query from the registry // delete the query from the registry
_queryRegistry->destroy(_vocbase, _qId, errorCode); _queryRegistry->destroy(_vocbase, _qId, errorCode);

View File

@ -217,18 +217,14 @@ std::string VariableGenerator::nextName() {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief export to JSON, returns an AUTOFREE Json object /// @brief export to VelocyPack
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
arangodb::basics::Json VariableGenerator::toJson( void VariableGenerator::toVelocyPack(VPackBuilder& builder) const {
TRI_memory_zone_t* zone) const { VPackArrayBuilder guard(&builder);
Json jsonAllVariablesList(Json::Array, _variables.size());
for (auto const& oneVariable : _variables) { for (auto const& oneVariable : _variables) {
jsonAllVariablesList(oneVariable.second->toJson()); oneVariable.second->toVelocyPack(builder);
} }
return jsonAllVariablesList;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -107,11 +107,11 @@ class VariableGenerator {
std::string nextName(); std::string nextName();
////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief export to JSON, returns an AUTOFREE Json object /// @brief export to VelocyPack
////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
arangodb::basics::Json toJson(TRI_memory_zone_t*) const; void toVelocyPack(arangodb::velocypack::Builder& builder) const;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief import from VelocyPack /// @brief import from VelocyPack

View File

@ -131,7 +131,13 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
THROW_ARANGO_EXCEPTION_MESSAGE(queryResult.code, queryResult.details); THROW_ARANGO_EXCEPTION_MESSAGE(queryResult.code, queryResult.details);
} }
TRI_ASSERT(TRI_IsArrayJson(queryResult.json)); VPackSlice qResult = queryResult.result->slice();
if (qResult.isNone()) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
TRI_ASSERT(qResult.isArray());
{ {
createResponse(HttpResponse::CREATED); createResponse(HttpResponse::CREATED);
@ -143,7 +149,7 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
size_t batchSize = size_t batchSize =
arangodb::basics::VelocyPackHelper::getNumericValue<size_t>( arangodb::basics::VelocyPackHelper::getNumericValue<size_t>(
opts, "batchSize", 1000); opts, "batchSize", 1000);
size_t const n = TRI_LengthArrayJson(queryResult.json); size_t const n = static_cast<size_t>(qResult.length());
if (n <= batchSize) { if (n <= batchSize) {
// result is smaller than batchSize and will be returned directly. no need // result is smaller than batchSize and will be returned directly. no need
@ -153,10 +159,7 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
try { try {
VPackObjectBuilder b(&result); VPackObjectBuilder b(&result);
result.add(VPackValue("result")); result.add(VPackValue("result"));
int res = arangodb::basics::JsonHelper::toVelocyPack(queryResult.json, result); result.add(qResult);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
result.add("hasMore", VPackValue(false)); result.add("hasMore", VPackValue(false));
if (arangodb::basics::VelocyPackHelper::getBooleanValue(opts, "count", if (arangodb::basics::VelocyPackHelper::getBooleanValue(opts, "count",
false)) { false)) {
@ -192,19 +195,9 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
bool count = arangodb::basics::VelocyPackHelper::getBooleanValue( bool count = arangodb::basics::VelocyPackHelper::getBooleanValue(
opts, "count", false); opts, "count", false);
// steal the query JSON, cursor will take over the ownership // steal the query result, cursor will take over the ownership
auto j = queryResult.json;
std::shared_ptr<VPackBuilder> builder = arangodb::basics::JsonHelper::toVelocyPack(j);
{
// Temporarily validate that transformation actually worked.
// Can be removed again as soon as queryResult returns VPack
VPackSlice validate = builder->slice();
if (validate.isNone() && j != nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
}
arangodb::JsonCursor* cursor = cursors->createFromVelocyPack( arangodb::JsonCursor* cursor = cursors->createFromVelocyPack(
builder, batchSize, extra, ttl, count, queryResult.cached); queryResult.result, batchSize, extra, ttl, count, queryResult.cached);
try { try {
_response->body().appendChar('{'); _response->body().appendChar('{');
@ -358,10 +351,7 @@ std::shared_ptr<VPackBuilder> RestCursorHandler::buildExtra(
extra->close(); extra->close();
} else { } else {
extra->add(VPackValue("warnings")); extra->add(VPackValue("warnings"));
int res = arangodb::basics::JsonHelper::toVelocyPack(queryResult.warnings, *extra); extra->add(queryResult.warnings->slice());
if (res != TRI_ERROR_NO_ERROR) {
return nullptr;
}
} }
} catch (...) { } catch (...) {
return nullptr; return nullptr;

View File

@ -390,14 +390,10 @@ bool RestQueryHandler::parseQuery() {
} }
result.close(); // bindVars result.close(); // bindVars
auto tmp = VPackParser::fromJson( result.add("ast", parseResult.result->slice());
arangodb::basics::JsonHelper::toString(parseResult.json));
result.add("ast", tmp->slice());
if (parseResult.warnings != nullptr) { if (parseResult.warnings != nullptr) {
auto tmp = VPackParser::fromJson( result.add("warnings", parseResult.warnings->slice());
arangodb::basics::JsonHelper::toString(parseResult.warnings));
result.add("warnings", tmp->slice());
} }
} }

View File

@ -333,18 +333,19 @@ void RestSimpleHandler::lookupByKeys(VPackSlice const& slice) {
} }
size_t resultSize = 10; size_t resultSize = 10;
if (TRI_IsArrayJson(queryResult.json)) { VPackSlice qResult = queryResult.result->slice();
resultSize = TRI_LengthArrayJson(queryResult.json); if (qResult.isArray()) {
resultSize = static_cast<size_t>(qResult.length());
} }
VPackBuilder result;
{ {
VPackObjectBuilder guard(&result);
createResponse(HttpResponse::OK); createResponse(HttpResponse::OK);
_response->setContentType("application/json; charset=utf-8"); _response->setContentType("application/json; charset=utf-8");
arangodb::basics::Json result(arangodb::basics::Json::Object, 3);
if (TRI_IsArrayJson(queryResult.json)) { if (qResult.isArray()) {
size_t const n = TRI_LengthArrayJson(queryResult.json);
// This is for internal use of AQL Traverser only. // This is for internal use of AQL Traverser only.
// Should not be documented // Should not be documented
@ -370,54 +371,49 @@ void RestSimpleHandler::lookupByKeys(VPackSlice const& slice) {
expression.release(); expression.release();
} }
} }
result.add(VPackValue("documents"));
std::vector<std::string> filteredIds;
arangodb::basics::Json filteredDocuments( result.openArray();
arangodb::basics::Json::Array, n); for (auto const& tmp : VPackArrayIterator(qResult)) {
arangodb::basics::Json filteredIds(arangodb::basics::Json::Array); if (!tmp.isNone()) {
for (size_t i = 0; i < n; ++i) {
TRI_json_t const* tmp = TRI_LookupArrayJson(queryResult.json, i);
if (tmp != nullptr) {
bool add = true; bool add = true;
for (auto& e : expressions) { for (auto& e : expressions) {
if (!e->isEdgeAccess && !e->matchesCheck(tmp)) { if (!e->isEdgeAccess && !e->matchesCheck(tmp)) {
add = false; add = false;
try { std::string _id =
std::string _id = arangodb::basics::VelocyPackHelper::checkAndGetStringValue(
arangodb::basics::JsonHelper::checkAndGetStringValue( tmp, "_id");
tmp, "_id"); filteredIds.emplace_back(_id);
arangodb::basics::Json tmp(_id);
filteredIds.add(tmp.steal());
} catch (...) {
// This should never occur.
}
break; break;
} }
} }
if (add) { if (add) {
filteredDocuments.add(TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, tmp)); result.add(tmp);
} }
} }
} }
result.close();
result.set("documents", filteredDocuments); result.add(VPackValue("filtered"));
result.set("filtered", filteredIds); result.openArray();
for (auto const& it : filteredIds) {
result.add(VPackValue(it));
}
result.close();
} else { } else {
result.set("documents", arangodb::basics::Json( result.add(VPackValue("documents"));
TRI_UNKNOWN_MEM_ZONE, queryResult.json, result.add(qResult);
arangodb::basics::Json::AUTOFREE)); queryResult.result = nullptr;
queryResult.json = nullptr;
} }
} else { } else {
result.set("documents", arangodb::basics::Json( result.add(VPackValue("documents"));
TRI_UNKNOWN_MEM_ZONE, queryResult.json, result.add(qResult);
arangodb::basics::Json::AUTOFREE)); queryResult.result = nullptr;
queryResult.json = nullptr;
} }
result.add("error", VPackValue(false));
result.set("error", arangodb::basics::Json(false)); result.add("code", VPackValue(_response->responseCode()));
result.set("code", arangodb::basics::Json(
static_cast<double>(_response->responseCode())));
// reserve 48 bytes per result document by default // reserve 48 bytes per result document by default
int res = _response->body().reserve(48 * resultSize); int res = _response->body().reserve(48 * resultSize);
@ -426,7 +422,10 @@ void RestSimpleHandler::lookupByKeys(VPackSlice const& slice) {
THROW_ARANGO_EXCEPTION(res); THROW_ARANGO_EXCEPTION(res);
} }
result.dump(_response->body()); arangodb::basics::VPackStringBufferAdapter buffer(
_response->body().stringBuffer());
VPackDumper dumper(&buffer);
dumper.dump(result.slice());
} }
} catch (arangodb::basics::Exception const& ex) { } catch (arangodb::basics::Exception const& ex) {
unregisterQuery(); unregisterQuery();

View File

@ -1028,13 +1028,13 @@ static void JS_ParseAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
} }
result->Set(TRI_V8_ASCII_STRING("ast"), result->Set(TRI_V8_ASCII_STRING("ast"),
TRI_ObjectJson(isolate, parseResult.json)); TRI_VPackToV8(isolate, parseResult.result->slice()));
if (parseResult.warnings == nullptr) { if (parseResult.warnings == nullptr) {
result->Set(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate)); result->Set(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate));
} else { } else {
result->Set(TRI_V8_ASCII_STRING("warnings"), result->Set(TRI_V8_ASCII_STRING("warnings"),
TRI_ObjectJson(isolate, parseResult.warnings)); TRI_VPackToV8(isolate, parseResult.warnings->slice()));
} }
TRI_V8_RETURN(result); TRI_V8_RETURN(result);
@ -1147,13 +1147,13 @@ static void JS_ExplainAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
} }
v8::Handle<v8::Object> result = v8::Object::New(isolate); v8::Handle<v8::Object> result = v8::Object::New(isolate);
if (queryResult.json != nullptr) { if (queryResult.result != nullptr) {
if (query.allPlans()) { if (query.allPlans()) {
result->Set(TRI_V8_ASCII_STRING("plans"), result->Set(TRI_V8_ASCII_STRING("plans"),
TRI_ObjectJson(isolate, queryResult.json)); TRI_VPackToV8(isolate, queryResult.result->slice()));
} else { } else {
result->Set(TRI_V8_ASCII_STRING("plan"), result->Set(TRI_V8_ASCII_STRING("plan"),
TRI_ObjectJson(isolate, queryResult.json)); TRI_VPackToV8(isolate, queryResult.result->slice()));
result->Set(TRI_V8_ASCII_STRING("cacheable"), result->Set(TRI_V8_ASCII_STRING("cacheable"),
v8::Boolean::New(isolate, queryResult.cached)); v8::Boolean::New(isolate, queryResult.cached));
} }
@ -1167,7 +1167,7 @@ static void JS_ExplainAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
result->Set(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate)); result->Set(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate));
} else { } else {
result->Set(TRI_V8_ASCII_STRING("warnings"), result->Set(TRI_V8_ASCII_STRING("warnings"),
TRI_ObjectJson(isolate, queryResult.warnings)); TRI_VPackToV8(isolate, queryResult.warnings->slice()));
} }
if (queryResult.stats != nullptr) { if (queryResult.stats != nullptr) {
VPackSlice stats = queryResult.stats->slice(); VPackSlice stats = queryResult.stats->slice();
@ -1240,9 +1240,9 @@ static void JS_ExecuteAqlJson(v8::FunctionCallbackInfo<v8::Value> const& args) {
// return the array value as it is. this is a performance optimisation // return the array value as it is. this is a performance optimisation
v8::Handle<v8::Object> result = v8::Object::New(isolate); v8::Handle<v8::Object> result = v8::Object::New(isolate);
if (queryResult.json != nullptr) { if (queryResult.result != nullptr) {
result->ForceSet(TRI_V8_ASCII_STRING("json"), result->ForceSet(TRI_V8_ASCII_STRING("json"),
TRI_ObjectJson(isolate, queryResult.json)); TRI_VPackToV8(isolate, queryResult.result->slice()));
} }
if (queryResult.stats != nullptr) { if (queryResult.stats != nullptr) {
VPackSlice stats = queryResult.stats->slice(); VPackSlice stats = queryResult.stats->slice();
@ -1259,7 +1259,7 @@ static void JS_ExecuteAqlJson(v8::FunctionCallbackInfo<v8::Value> const& args) {
result->ForceSet(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate)); result->ForceSet(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate));
} else { } else {
result->ForceSet(TRI_V8_ASCII_STRING("warnings"), result->ForceSet(TRI_V8_ASCII_STRING("warnings"),
TRI_ObjectJson(isolate, queryResult.warnings)); TRI_VPackToV8(isolate, queryResult.warnings->slice()));
} }
result->ForceSet(TRI_V8_ASCII_STRING("cached"), result->ForceSet(TRI_V8_ASCII_STRING("cached"),
v8::Boolean::New(isolate, queryResult.cached)); v8::Boolean::New(isolate, queryResult.cached));
@ -1365,7 +1365,7 @@ static void JS_ExecuteAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
result->ForceSet(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate)); result->ForceSet(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate));
} else { } else {
result->ForceSet(TRI_V8_ASCII_STRING("warnings"), result->ForceSet(TRI_V8_ASCII_STRING("warnings"),
TRI_ObjectJson(isolate, queryResult.warnings)); TRI_VPackToV8(isolate, queryResult.warnings->slice()));
} }
result->ForceSet(TRI_V8_ASCII_STRING("cached"), result->ForceSet(TRI_V8_ASCII_STRING("cached"),
v8::Boolean::New(isolate, queryResult.cached)); v8::Boolean::New(isolate, queryResult.cached));