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
/// the caller is responsible for freeing the JSON later
/// @DEPRECATED
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* Ast::toJson(TRI_memory_zone_t* zone, bool verbose) const {
#warning Deprecated
TRI_json_t* json = TRI_CreateArrayJson(zone);
if (json == nullptr) {
@ -160,6 +162,19 @@ TRI_json_t* Ast::toJson(TRI_memory_zone_t* zone, bool verbose) const {
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
////////////////////////////////////////////////////////////////////////////////

View File

@ -184,10 +184,17 @@ class Ast {
//////////////////////////////////////////////////////////////////////////////
/// @brief convert the AST into JSON
/// the caller is responsible for freeing the JSON later
/// @DEPRECATED
//////////////////////////////////////////////////////////////////////////////
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
//////////////////////////////////////////////////////////////////////////////

View File

@ -472,6 +472,7 @@ struct CoordinatorInstanciator : public WalkerWorker<ExecutionNode> {
EngineInfo const& info, Collection* collection,
QueryId& connectedId, std::string const& shardId,
TRI_json_t* jsonPlan) {
#warning still Json inplace. Needs to be fixed
// create a JSON representation of the plan
Json result(Json::Object);
@ -487,8 +488,10 @@ struct CoordinatorInstanciator : public WalkerWorker<ExecutionNode> {
"type", Json(TRI_TransactionTypeGetStr(collection->accessType))));
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);
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
/// DEPRECATED
////////////////////////////////////////////////////////////////////////////////
arangodb::basics::Json ExecutionPlan::toJson(Ast* ast, TRI_memory_zone_t* zone,
bool verbose) const {
#warning Remove this
// TODO
VPackBuilder b;
_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("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;
result.set("estimatedCost", arangodb::basics::Json(_root->getCost(nrItems)));
result.set("estimatedNrItems",
@ -256,6 +261,41 @@ arangodb::basics::Json ExecutionPlan::toJson(Ast* ast, TRI_memory_zone_t* zone,
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
////////////////////////////////////////////////////////////////////////////////

View File

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

View File

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

View File

@ -612,19 +612,10 @@ QueryResult Query::execute(QueryRegistry* registry) {
if (cacheEntry != nullptr) {
// got a result from the query cache
QueryResult res(TRI_ERROR_NO_ERROR);
#warning Replace QueryResult with VPack
VPackBuilder tmp;
tmp.openObject();
warningsToVelocyPack(tmp);
tmp.close();
res.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
res.json = arangodb::basics::VelocyPackHelper::velocyPackToJson(cacheEntry->_queryResult->slice());
res.warnings = warningsToVelocyPack();
TRI_ASSERT(cacheEntry->_queryResult != nullptr);
res.result = cacheEntry->_queryResult;
res.cached = true;
if (res.json == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
return res;
}
}
@ -650,14 +641,13 @@ QueryResult Query::execute(QueryRegistry* registry) {
useQueryCache = false;
}
arangodb::basics::Json jsonResult(arangodb::basics::Json::Array, 16);
AqlItemBlock* value = nullptr;
auto resultBuilder = std::make_shared<VPackBuilder>();
try {
VPackArrayBuilder guard(resultBuilder.get());
// this is the RegisterId our results can be found in
auto const resultRegister = _engine->resultRegister();
AqlItemBlock* value = nullptr;
try {
if (useQueryCache) {
// iterate over result, return it and store it in query cache
while (nullptr != (value = _engine->getSome(
@ -665,14 +655,12 @@ QueryResult Query::execute(QueryRegistry* registry) {
auto doc = value->getDocumentCollection(resultRegister);
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) {
auto val = value->getValueReference(i, resultRegister);
if (!val.isEmpty()) {
jsonResult.add(val.toJson(_trx, doc, true));
val.toVelocyPack(_trx, doc, *resultBuilder);
}
}
delete value;
@ -681,14 +669,8 @@ QueryResult Query::execute(QueryRegistry* registry) {
if (_warnings.empty()) {
// 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(
_vocbase, queryStringHash, _queryString, _queryLength, copy,
_vocbase, queryStringHash, _queryString, _queryLength, resultBuilder,
_trx->collectionNames());
if (result == nullptr) {
@ -702,14 +684,11 @@ QueryResult Query::execute(QueryRegistry* registry) {
auto doc = value->getDocumentCollection(resultRegister);
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) {
auto val = value->getValueReference(i, resultRegister);
if (!val.isEmpty()) {
jsonResult.add(val.toJson(_trx, doc, true));
val.toVelocyPack(_trx, doc, *resultBuilder);
}
}
delete value;
@ -732,13 +711,8 @@ QueryResult Query::execute(QueryRegistry* registry) {
enterState(FINALIZATION);
QueryResult result(TRI_ERROR_NO_ERROR);
#warning Replace QueryResult with VPack
VPackBuilder tmp;
tmp.openObject();
warningsToVelocyPack(tmp);
tmp.close();
result.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
result.json = jsonResult.steal();
result.warnings = warningsToVelocyPack();
result.result = resultBuilder;
result.stats = stats;
if (_profile != nullptr && profiling()) {
@ -890,12 +864,7 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
enterState(FINALIZATION);
#warning Replace QueryResult with VPack
VPackBuilder tmp;
tmp.openObject();
warningsToVelocyPack(tmp);
tmp.close();
result.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
result.warnings = warningsToVelocyPack();
result.stats = stats;
if (_profile != nullptr && profiling()) {
@ -996,9 +965,11 @@ QueryResult Query::explain() {
QueryResult result(TRI_ERROR_NO_ERROR);
QueryRegistry localRegistry;
result.result = std::make_shared<VPackBuilder>();
if (allPlans()) {
arangodb::basics::Json out(Json::Array);
{
VPackArrayBuilder guard(result.result.get());
auto plans = opt.getPlans();
for (auto& it : plans) {
@ -1006,11 +977,9 @@ QueryResult Query::explain() {
it->findVarUsage();
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
result.cached = false;
} else {
@ -1021,9 +990,7 @@ QueryResult Query::explain() {
bestPlan->findVarUsage();
bestPlan->planRegisters();
result.json =
bestPlan->toJson(parser.ast(), TRI_UNKNOWN_MEM_ZONE, verbosePlans())
.steal();
bestPlan->toVelocyPack(parser.ast(), verbosePlans(), *result.result);
// cacheability
result.cached = (_queryString != nullptr && _queryLength > 0 &&
@ -1033,12 +1000,7 @@ QueryResult Query::explain() {
_trx->commit();
#warning Replace QueryResult with VPack
VPackBuilder tmp;
tmp.openObject();
warningsToVelocyPack(tmp);
tmp.close();
result.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
result.warnings = warningsToVelocyPack();
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
//////////////////////////////////////////////////////////////////////////////
void Query::warningsToVelocyPack(arangodb::velocypack::Builder& builder) const {
void Query::addWarningsToVelocyPackObject(
arangodb::velocypack::Builder& builder) const {
TRI_ASSERT(builder.isOpenObject());
if (_warnings.empty()) {
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
////////////////////////////////////////////////////////////////////////////////

View File

@ -398,12 +398,19 @@ class Query {
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
/// 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

View File

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

View File

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

View File

@ -131,7 +131,13 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
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);
@ -143,7 +149,7 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
size_t batchSize =
arangodb::basics::VelocyPackHelper::getNumericValue<size_t>(
opts, "batchSize", 1000);
size_t const n = TRI_LengthArrayJson(queryResult.json);
size_t const n = static_cast<size_t>(qResult.length());
if (n <= batchSize) {
// result is smaller than batchSize and will be returned directly. no need
@ -153,10 +159,7 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
try {
VPackObjectBuilder b(&result);
result.add(VPackValue("result"));
int res = arangodb::basics::JsonHelper::toVelocyPack(queryResult.json, result);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
result.add(qResult);
result.add("hasMore", VPackValue(false));
if (arangodb::basics::VelocyPackHelper::getBooleanValue(opts, "count",
false)) {
@ -192,19 +195,9 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
bool count = arangodb::basics::VelocyPackHelper::getBooleanValue(
opts, "count", false);
// steal the query JSON, 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);
}
}
// steal the query result, cursor will take over the ownership
arangodb::JsonCursor* cursor = cursors->createFromVelocyPack(
builder, batchSize, extra, ttl, count, queryResult.cached);
queryResult.result, batchSize, extra, ttl, count, queryResult.cached);
try {
_response->body().appendChar('{');
@ -358,10 +351,7 @@ std::shared_ptr<VPackBuilder> RestCursorHandler::buildExtra(
extra->close();
} else {
extra->add(VPackValue("warnings"));
int res = arangodb::basics::JsonHelper::toVelocyPack(queryResult.warnings, *extra);
if (res != TRI_ERROR_NO_ERROR) {
return nullptr;
}
extra->add(queryResult.warnings->slice());
}
} catch (...) {
return nullptr;

View File

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

View File

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

View File

@ -1028,13 +1028,13 @@ static void JS_ParseAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
}
result->Set(TRI_V8_ASCII_STRING("ast"),
TRI_ObjectJson(isolate, parseResult.json));
TRI_VPackToV8(isolate, parseResult.result->slice()));
if (parseResult.warnings == nullptr) {
result->Set(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate));
} else {
result->Set(TRI_V8_ASCII_STRING("warnings"),
TRI_ObjectJson(isolate, parseResult.warnings));
TRI_VPackToV8(isolate, parseResult.warnings->slice()));
}
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);
if (queryResult.json != nullptr) {
if (queryResult.result != nullptr) {
if (query.allPlans()) {
result->Set(TRI_V8_ASCII_STRING("plans"),
TRI_ObjectJson(isolate, queryResult.json));
TRI_VPackToV8(isolate, queryResult.result->slice()));
} else {
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"),
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));
} else {
result->Set(TRI_V8_ASCII_STRING("warnings"),
TRI_ObjectJson(isolate, queryResult.warnings));
TRI_VPackToV8(isolate, queryResult.warnings->slice()));
}
if (queryResult.stats != nullptr) {
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
v8::Handle<v8::Object> result = v8::Object::New(isolate);
if (queryResult.json != nullptr) {
if (queryResult.result != nullptr) {
result->ForceSet(TRI_V8_ASCII_STRING("json"),
TRI_ObjectJson(isolate, queryResult.json));
TRI_VPackToV8(isolate, queryResult.result->slice()));
}
if (queryResult.stats != nullptr) {
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));
} else {
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"),
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));
} else {
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"),
v8::Boolean::New(isolate, queryResult.cached));