1
0
Fork 0

Merge branch 'spdvpk' of https://github.com/arangodb/arangodb into spdvpk

This commit is contained in:
Jan Steemann 2016-03-07 20:29:12 +01:00
commit 25c937b03e
15 changed files with 228 additions and 311 deletions

View File

@ -534,7 +534,9 @@ AstNode::AstNode(Ast* ast, arangodb::basics::Json const& json)
break;
}
case NODE_TYPE_VARIABLE: {
auto variable = ast->variables()->createVariable(json);
#warning Fix this
auto builder = JsonHelper::toVelocyPack(json.json());
auto variable = ast->variables()->createVariable(builder->slice());
TRI_ASSERT(variable != nullptr);
setData(variable);
break;

View File

@ -377,7 +377,9 @@ ExecutionNode::ExecutionNode(ExecutionPlan* plan,
len = jsonvarsUsedLater.size();
_varsUsedLater.reserve(len);
for (size_t i = 0; i < len; i++) {
auto oneVarUsedLater = std::make_unique<Variable>(jsonvarsUsedLater.at(i));
#warning Still Json Version. Ignore return val
auto builder = JsonHelper::toVelocyPack(jsonvarsUsedLater.at(i).json());
auto oneVarUsedLater = std::make_unique<Variable>(builder->slice());
Variable* oneVariable = allVars->getVariable(oneVarUsedLater->id);
if (oneVariable == nullptr) {
@ -398,7 +400,9 @@ ExecutionNode::ExecutionNode(ExecutionPlan* plan,
len = jsonvarsValidList.size();
_varsValid.reserve(len);
for (size_t i = 0; i < len; i++) {
auto oneVarValid = std::make_unique<Variable>(jsonvarsValidList.at(i));
#warning Deprecated
auto builder = JsonHelper::toVelocyPack(jsonvarsValidList.at(i).json());
auto oneVarValid = std::make_unique<Variable>(builder->slice());
Variable* oneVariable = allVars->getVariable(oneVarValid->id);
if (oneVariable == nullptr) {
@ -629,8 +633,9 @@ Variable* ExecutionNode::varFromJson(Ast* ast,
"Mandatory variable \"" + std::string(variableName) + "\" not found.";
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, msg.c_str());
}
return ast->variables()->createVariable(variableJson);
#warning Deprecated
auto builder = JsonHelper::toVelocyPack(variableJson.json());
return ast->variables()->createVariable(builder->slice());
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -42,6 +42,9 @@
#include "Basics/tri-strings.h"
#include "Basics/VelocyPackHelper.h"
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb::aql;
using namespace arangodb::basics;
@ -97,48 +100,47 @@ ExecutionPlan* ExecutionPlan::instantiateFromAst(Ast* ast) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief process the list of collections in a JSON
/// @brief process the list of collections in a VelocyPack
////////////////////////////////////////////////////////////////////////////////
void ExecutionPlan::getCollectionsFromJson(Ast* ast,
arangodb::basics::Json const& json) {
void ExecutionPlan::getCollectionsFromVelocyPack(Ast* ast,
VPackSlice const slice) {
TRI_ASSERT(ast != nullptr);
arangodb::basics::Json jsonCollections = json.get("collections");
VPackSlice collectionsSlice = slice.get("collections");
if (!jsonCollections.isArray()) {
if (!collectionsSlice.isArray()) {
THROW_ARANGO_EXCEPTION_MESSAGE(
TRI_ERROR_INTERNAL,
"json node \"collections\" not found or not an array");
}
auto const size = jsonCollections.size();
for (size_t i = 0; i < size; i++) {
arangodb::basics::Json oneJsonCollection =
jsonCollections.at(static_cast<int>(i));
auto typeStr = arangodb::basics::JsonHelper::checkAndGetStringValue(
oneJsonCollection.json(), "type");
for (auto const& collection : VPackArrayIterator(collectionsSlice)) {
auto typeStr = arangodb::basics::VelocyPackHelper::checkAndGetStringValue(
collection, "type");
ast->query()->collections()->add(
arangodb::basics::JsonHelper::checkAndGetStringValue(
oneJsonCollection.json(), "name"),
arangodb::basics::VelocyPackHelper::checkAndGetStringValue(collection,
"name"),
TRI_GetTransactionTypeFromStr(
arangodb::basics::JsonHelper::checkAndGetStringValue(
oneJsonCollection.json(), "type").c_str()));
arangodb::basics::VelocyPackHelper::checkAndGetStringValue(
collection, "type")
.c_str()));
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an execution plan from JSON
/// @brief create an execution plan from VelocyPack
////////////////////////////////////////////////////////////////////////////////
ExecutionPlan* ExecutionPlan::instantiateFromJson(
Ast* ast, arangodb::basics::Json const& json) {
ExecutionPlan* ExecutionPlan::instantiateFromVelocyPack(
Ast* ast, VPackSlice const slice) {
TRI_ASSERT(ast != nullptr);
auto plan = std::make_unique<ExecutionPlan>(ast);
#warning In place slice => Json
Json json(TRI_UNKNOWN_MEM_ZONE,
arangodb::basics::VelocyPackHelper::velocyPackToJson(slice));
plan->_root = plan->fromJson(json);
plan->_varUsageComputed = true;

View File

@ -63,18 +63,18 @@ class ExecutionPlan {
static ExecutionPlan* instantiateFromAst(Ast*);
//////////////////////////////////////////////////////////////////////////////
/// @brief process the list of collections in a JSON
/// @brief process the list of collections in a VelocyPack
//////////////////////////////////////////////////////////////////////////////
static void getCollectionsFromJson(Ast* ast,
arangodb::basics::Json const& Json);
static void getCollectionsFromVelocyPack(Ast* ast,
arangodb::velocypack::Slice const);
//////////////////////////////////////////////////////////////////////////////
/// @brief create an execution plan from JSON
/// @brief create an execution plan from VelocyPack
//////////////////////////////////////////////////////////////////////////////
static ExecutionPlan* instantiateFromJson(Ast* ast,
arangodb::basics::Json const& Json);
static ExecutionPlan* instantiateFromVelocyPack(
Ast* ast, arangodb::velocypack::Slice const);
//////////////////////////////////////////////////////////////////////////////
/// @brief clone the plan by recursively cloning starting from the root

View File

@ -47,6 +47,7 @@
#include "VocBase/Graphs.h"
#include <velocypack/Builder.h>
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
@ -146,19 +147,6 @@ std::shared_ptr<VPackBuilder> Profile::toVelocyPack() {
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief convert the profile to JSON
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* Profile::toJson(TRI_memory_zone_t*) {
arangodb::basics::Json result(arangodb::basics::Json::Object);
for (auto const& it : results) {
result.set(StateNames[static_cast<int>(it.first)].c_str(),
arangodb::basics::Json(it.second));
}
return result.steal();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not query tracking is disabled globally
////////////////////////////////////////////////////////////////////////////////
@ -172,7 +160,7 @@ bool Query::DoDisableQueryTracking = false;
Query::Query(arangodb::ApplicationV8* applicationV8,
bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
char const* queryString, size_t queryLength,
std::shared_ptr<VPackBuilder> bindParameters, VPackSlice const options, QueryPart part)
std::shared_ptr<VPackBuilder> const bindParameters, std::shared_ptr<VPackBuilder> const options, QueryPart part)
: _id(0),
_applicationV8(applicationV8),
_vocbase(vocbase),
@ -180,9 +168,9 @@ Query::Query(arangodb::ApplicationV8* applicationV8,
_context(nullptr),
_queryString(queryString),
_queryLength(queryLength),
_queryJson(),
_queryBuilder(),
_bindParameters(bindParameters),
_options(arangodb::basics::VelocyPackHelper::velocyPackToJson(options)),
_options(options),
_collections(vocbase),
_strings(),
_shortStringStorage(1024),
@ -205,98 +193,14 @@ Query::Query(arangodb::ApplicationV8* applicationV8,
TRI_ASSERT(_vocbase != nullptr);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief creates a query
////////////////////////////////////////////////////////////////////////////////
Query::Query(arangodb::ApplicationV8* applicationV8,
bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
char const* queryString, size_t queryLength,
std::shared_ptr<VPackBuilder> bindParameters, TRI_json_t* options, QueryPart part)
: _id(0),
_applicationV8(applicationV8),
_vocbase(vocbase),
_executor(nullptr),
_context(nullptr),
_queryString(queryString),
_queryLength(queryLength),
_queryJson(),
_bindParameters(bindParameters),
_options(options),
_collections(vocbase),
_strings(),
_shortStringStorage(1024),
_ast(nullptr),
_profile(nullptr),
_state(INVALID_STATE),
_plan(nullptr),
_parser(nullptr),
_trx(nullptr),
_engine(nullptr),
_maxWarningCount(10),
_warnings(),
_startTime(TRI_microtime()),
_part(part),
_contextOwnedByExterior(contextOwnedByExterior),
_killed(false),
_isModificationQuery(false) {
// std::cout << TRI_CurrentThreadId() << ", QUERY " << this << " CTOR: " <<
// queryString << "\n";
TRI_ASSERT(_vocbase != nullptr);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief creates a query from Json
////////////////////////////////////////////////////////////////////////////////
Query::Query(arangodb::ApplicationV8* applicationV8,
bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
arangodb::basics::Json queryStruct, TRI_json_t* options,
QueryPart part)
: _id(0),
_applicationV8(applicationV8),
_vocbase(vocbase),
_executor(nullptr),
_context(nullptr),
_queryString(nullptr),
_queryLength(0),
_queryJson(queryStruct),
_bindParameters(nullptr),
_options(options),
_collections(vocbase),
_strings(),
_shortStringStorage(1024),
_ast(nullptr),
_profile(nullptr),
_state(INVALID_STATE),
_plan(nullptr),
_parser(nullptr),
_trx(nullptr),
_engine(nullptr),
_maxWarningCount(10),
_warnings(),
_startTime(TRI_microtime()),
_part(part),
_contextOwnedByExterior(contextOwnedByExterior),
_killed(false),
_isModificationQuery(false) {
// std::cout << TRI_CurrentThreadId() << ", QUERY " << this << " CTOR (JSON):
// " << _queryJson.toString() << "\n";
TRI_ASSERT(_vocbase != nullptr);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief creates a query from VelocyPack
////////////////////////////////////////////////////////////////////////////////
Query::Query(arangodb::ApplicationV8* applicationV8,
bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
std::shared_ptr<VPackBuilder> queryStruct,
VPackSlice const options, QueryPart part)
std::shared_ptr<VPackBuilder> const queryStruct,
std::shared_ptr<VPackBuilder> const options, QueryPart part)
: _id(0),
_applicationV8(applicationV8),
_vocbase(vocbase),
@ -304,10 +208,9 @@ Query::Query(arangodb::ApplicationV8* applicationV8,
_context(nullptr),
_queryString(nullptr),
_queryLength(0),
_queryJson(TRI_UNKNOWN_MEM_ZONE, arangodb::basics::VelocyPackHelper::velocyPackToJson(
queryStruct->slice())),
_queryBuilder(queryStruct),
_bindParameters(nullptr),
_options(arangodb::basics::VelocyPackHelper::velocyPackToJson(options)),
_options(options),
_collections(vocbase),
_strings(),
_shortStringStorage(1024),
@ -343,11 +246,6 @@ Query::~Query() {
delete _profile;
_profile = nullptr;
if (_options != nullptr) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _options);
_options = nullptr;
}
delete _executor;
_executor = nullptr;
@ -390,21 +288,11 @@ Query::~Query() {
////////////////////////////////////////////////////////////////////////////////
Query* Query::clone(QueryPart part, bool withPlan) {
std::unique_ptr<TRI_json_t> options;
if (_options != nullptr) {
options.reset(TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, _options));
if (options == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
}
std::unique_ptr<Query> clone;
clone.reset(new Query(_applicationV8, false, _vocbase, _queryString,
_queryLength, std::shared_ptr<VPackBuilder>(), options.get(), part));
options.release();
_queryLength, std::shared_ptr<VPackBuilder>(), _options, part));
if (_plan != nullptr) {
if (withPlan) {
@ -618,11 +506,13 @@ QueryResult Query::prepare(QueryRegistry* registry) {
// Now plan and all derived plans belong to the optimizer
plan.reset(opt.stealBest()); // Now we own the best one again
planRegisters = true;
} else { // no queryString, we are instantiating from _queryJson
} else { // no queryString, we are instantiating from _queryBuilder
enterState(PLAN_INSTANTIATION);
ExecutionPlan::getCollectionsFromJson(parser->ast(), _queryJson);
parser->ast()->variables()->fromJson(_queryJson);
VPackSlice const querySlice = _queryBuilder->slice();
ExecutionPlan::getCollectionsFromVelocyPack(parser->ast(), querySlice);
parser->ast()->variables()->fromVelocyPack(querySlice);
// creating the plan may have produced some collections
// we need to add them to the transaction now (otherwise the query will
// fail)
@ -637,8 +527,8 @@ QueryResult Query::prepare(QueryRegistry* registry) {
return transactionError(res);
}
// we have an execution plan in JSON format
plan.reset(ExecutionPlan::instantiateFromJson(parser->ast(), _queryJson));
// we have an execution plan in VelocyPack format
plan.reset(ExecutionPlan::instantiateFromVelocyPack(parser->ast(), _queryBuilder->slice()));
if (plan.get() == nullptr) {
// oops
return QueryResult(TRI_ERROR_INTERNAL);
@ -721,7 +611,12 @@ QueryResult Query::execute(QueryRegistry* registry) {
if (cacheEntry != nullptr) {
// got a result from the query cache
QueryResult res(TRI_ERROR_NO_ERROR);
res.warnings = warningsToJson(TRI_UNKNOWN_MEM_ZONE);
#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 = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, cacheEntry->_queryResult);
res.cached = true;
@ -838,12 +733,17 @@ QueryResult Query::execute(QueryRegistry* registry) {
enterState(FINALIZATION);
QueryResult result(TRI_ERROR_NO_ERROR);
result.warnings = warningsToJson(TRI_UNKNOWN_MEM_ZONE);
#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.stats = stats;
if (_profile != nullptr && profiling()) {
result.profile = _profile->toJson(TRI_UNKNOWN_MEM_ZONE);
result.profile = _profile->toVelocyPack();
}
return result;
@ -992,11 +892,16 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
enterState(FINALIZATION);
result.warnings = warningsToJson(TRI_UNKNOWN_MEM_ZONE);
#warning Replace QueryResult with VPack
VPackBuilder tmp;
tmp.openObject();
warningsToVelocyPack(tmp);
tmp.close();
result.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
result.stats = stats;
if (_profile != nullptr && profiling()) {
result.profile = _profile->toJson(TRI_UNKNOWN_MEM_ZONE);
result.profile = _profile->toVelocyPack();
}
return result;
@ -1130,7 +1035,13 @@ QueryResult Query::explain() {
_trx->commit();
result.warnings = warningsToJson(TRI_UNKNOWN_MEM_ZONE);
#warning Replace QueryResult with VPack
VPackBuilder tmp;
tmp.openObject();
warningsToVelocyPack(tmp);
tmp.close();
result.warnings = arangodb::basics::VelocyPackHelper::velocyPackToJson(tmp.slice().get("warnings"));
result.stats = opt._stats.toVelocyPack();
return result;
@ -1308,16 +1219,17 @@ void Query::getStats(VPackBuilder& builder) {
////////////////////////////////////////////////////////////////////////////////
bool Query::getBooleanOption(char const* option, bool defaultValue) const {
if (!TRI_IsObjectJson(_options)) {
VPackSlice options = _options->slice();
if (!options.isObject()) {
return defaultValue;
}
TRI_json_t const* valueJson = TRI_LookupObjectJson(_options, option);
if (!TRI_IsBooleanJson(valueJson)) {
VPackSlice value = options.get(option);
if (!value.isBoolean()) {
return defaultValue;
}
return valueJson->_value._boolean;
return value.getBool();
}
@ -1327,43 +1239,21 @@ 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&) const {
#warning Needs to be implemented.
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief convert the list of warnings to JSON
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* Query::warningsToJson(TRI_memory_zone_t* zone) const {
void Query::warningsToVelocyPack(arangodb::velocypack::Builder& builder) const {
TRI_ASSERT(builder.isOpenObject());
if (_warnings.empty()) {
return nullptr;
return;
}
size_t const n = _warnings.size();
TRI_json_t* json = TRI_CreateArrayJson(zone, n);
if (json != nullptr) {
builder.add(VPackValue("warnings"));
{
VPackArrayBuilder guard(&builder);
for (size_t i = 0; i < n; ++i) {
TRI_json_t* error = TRI_CreateObjectJson(zone, 2);
if (error != nullptr) {
TRI_Insert3ObjectJson(
zone, error, "code",
TRI_CreateNumberJson(zone,
static_cast<double>(_warnings[i].first)));
TRI_Insert3ObjectJson(
zone, error, "message",
TRI_CreateStringCopyJson(zone, _warnings[i].second.c_str(),
_warnings[i].second.size()));
TRI_PushBack3ArrayJson(zone, json, error);
}
VPackObjectBuilder objGuard(&builder);
builder.add("code", VPackValue(_warnings[i].first));
builder.add("message", VPackValue(_warnings[i].second));
}
}
return json;
}
////////////////////////////////////////////////////////////////////////////////
@ -1470,16 +1360,17 @@ bool Query::canUseQueryCache() const {
////////////////////////////////////////////////////////////////////////////////
double Query::getNumericOption(char const* option, double defaultValue) const {
if (!TRI_IsObjectJson(_options)) {
VPackSlice options = _options->slice();
if (!options.isObject()) {
return defaultValue;
}
TRI_json_t const* valueJson = TRI_LookupObjectJson(_options, option);
if (!TRI_IsNumberJson(valueJson)) {
VPackSlice value = options.get(option);
if (!value.isNumber()) {
return defaultValue;
}
return valueJson->_value._number;
return value.getNumericValue<double>();
}
////////////////////////////////////////////////////////////////////////////////
@ -1507,21 +1398,19 @@ QueryResult Query::transactionError(int errorCode) const {
////////////////////////////////////////////////////////////////////////////////
bool Query::inspectSimplePlans() const {
if (!TRI_IsObjectJson(_options)) {
VPackSlice options = _options->slice();
if (!options.isObject()) {
return true; // default
}
TRI_json_t const* optJson = TRI_LookupObjectJson(_options, "optimizer");
VPackSlice opt = options.get("optimizer");
if (!TRI_IsObjectJson(optJson)) {
if (!opt.isObject()) {
return true; // default
}
TRI_json_t const* j = TRI_LookupObjectJson(optJson, "inspectSimplePlans");
if (TRI_IsBooleanJson(j)) {
return j->_value._boolean;
}
return true; // default;
return arangodb::basics::VelocyPackHelper::getBooleanValue(
opt, "inspectSimplePlans", true);
}
////////////////////////////////////////////////////////////////////////////////
@ -1531,31 +1420,27 @@ bool Query::inspectSimplePlans() const {
std::vector<std::string> Query::getRulesFromOptions() const {
std::vector<std::string> rules;
if (!TRI_IsObjectJson(_options)) {
VPackSlice options = _options->slice();
if (!options.isObject()){
return rules;
}
TRI_json_t const* optJson = TRI_LookupObjectJson(_options, "optimizer");
VPackSlice opt = options.get("optimizer");
if (!TRI_IsObjectJson(optJson)) {
if (!opt.isObject()) {
return rules;
}
TRI_json_t const* rulesJson = TRI_LookupObjectJson(optJson, "rules");
VPackSlice rulesList = opt.get("rules");
if (!TRI_IsArrayJson(rulesJson)) {
if (!rulesList.isArray()) {
return rules;
}
size_t const n = TRI_LengthArrayJson(rulesJson);
for (size_t i = 0; i < n; ++i) {
TRI_json_t const* rule = static_cast<TRI_json_t const*>(
TRI_AtVector(&rulesJson->_value._objects, i));
if (TRI_IsStringJson(rule)) {
rules.emplace_back(rule->_value._string.data,
rule->_value._string.length - 1);
for (auto const& rule : VPackArrayIterator(rulesList)) {
if (rule.isString()){
rules.emplace_back(rule.copyString());
}
}

View File

@ -38,7 +38,6 @@
#include <velocypack/Builder.h>
struct TRI_json_t;
struct TRI_vocbase_t;
namespace arangodb {
@ -97,8 +96,6 @@ struct Profile {
std::shared_ptr<arangodb::velocypack::Builder> toVelocyPack();
TRI_json_t* toJson(TRI_memory_zone_t*);
Query* query;
std::vector<std::pair<ExecutionState, double>> results;
double stamp;
@ -116,19 +113,12 @@ class Query {
public:
Query(arangodb::ApplicationV8*, bool, TRI_vocbase_t*, char const*, size_t,
std::shared_ptr<arangodb::velocypack::Builder>, struct TRI_json_t*,
QueryPart);
Query(arangodb::ApplicationV8*, bool, TRI_vocbase_t*, char const*, size_t,
std::shared_ptr<arangodb::velocypack::Builder>,
arangodb::velocypack::Slice const, QueryPart);
std::shared_ptr<arangodb::velocypack::Builder> const,
std::shared_ptr<arangodb::velocypack::Builder> const, QueryPart);
Query(arangodb::ApplicationV8*, bool, TRI_vocbase_t*,
arangodb::basics::Json queryStruct, struct TRI_json_t*, QueryPart);
Query(arangodb::ApplicationV8*, bool, TRI_vocbase_t*,
std::shared_ptr<arangodb::velocypack::Builder>,
arangodb::velocypack::Slice const, QueryPart);
std::shared_ptr<arangodb::velocypack::Builder> const,
std::shared_ptr<arangodb::velocypack::Builder> const, QueryPart);
~Query();
@ -407,12 +397,6 @@ class Query {
bool getBooleanOption(char const*, bool) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief convert the list of warnings to JSON
//////////////////////////////////////////////////////////////////////////////
TRI_json_t* warningsToJson(TRI_memory_zone_t*) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief convert the list of warnings to VelocyPack.
/// Will add a new entry { ..., warnings: <warnings>, } if there are
@ -582,10 +566,10 @@ class Query {
size_t const _queryLength;
//////////////////////////////////////////////////////////////////////////////
/// @brief query in a JSON structure
/// @brief query in a VelocyPack structure
//////////////////////////////////////////////////////////////////////////////
arangodb::basics::Json const _queryJson;
std::shared_ptr<arangodb::velocypack::Builder> const _queryBuilder;
//////////////////////////////////////////////////////////////////////////////
/// @brief bind parameters for the query
@ -597,7 +581,7 @@ class Query {
/// @brief query options
//////////////////////////////////////////////////////////////////////////////
TRI_json_t* _options;
std::shared_ptr<arangodb::velocypack::Builder> _options;
//////////////////////////////////////////////////////////////////////////////
/// @brief collections used in the query

View File

@ -77,9 +77,6 @@ struct QueryResult {
if (json != nullptr) {
TRI_FreeJson(zone, json);
}
if (profile != nullptr) {
TRI_FreeJson(zone, profile);
}
}
int code;
@ -91,7 +88,7 @@ struct QueryResult {
TRI_json_t* warnings;
TRI_json_t* json;
std::shared_ptr<arangodb::velocypack::Builder> stats;
TRI_json_t* profile;
std::shared_ptr<arangodb::velocypack::Builder> profile;
TRI_json_t* clusterplan;
};
}

View File

@ -92,7 +92,8 @@ void RestAqlHandler::createQueryFromVelocyPack() {
return;
}
VPackSlice options = querySlice.get("options");
auto options = std::make_shared<VPackBuilder>(
VPackBuilder::clone(querySlice.get("options")));
std::string const part = VelocyPackHelper::getStringValue(querySlice, "part", "");
@ -240,10 +241,9 @@ void RestAqlHandler::explainQuery() {
return;
}
#warning Can we use Builder::clone(Slice) here?
auto bindVars = std::make_shared<VPackBuilder>(VPackBuilder::clone(querySlice.get("parameters")));
VPackSlice options = querySlice.get("options");
auto options = std::make_shared<VPackBuilder>(VPackBuilder::clone(querySlice.get("options")));
auto query = new Query(_applicationV8, false, _vocbase, queryString.c_str(),
queryString.size(), bindVars, options, PART_MAIN);
@ -314,9 +314,10 @@ void RestAqlHandler::createQueryFromString() {
return;
}
auto bindVars = std::make_shared<VPackBuilder>(VPackBuilder::clone(querySlice.get("parameters")));
VPackSlice options = querySlice.get("options");
auto bindVars = std::make_shared<VPackBuilder>(
VPackBuilder::clone(querySlice.get("parameters")));
auto options = std::make_shared<VPackBuilder>(
VPackBuilder::clone(querySlice.get("options")));
auto query =
new Query(_applicationV8, false, _vocbase, queryString.c_str(),

View File

@ -22,12 +22,11 @@
////////////////////////////////////////////////////////////////////////////////
#include "Variable.h"
#include "Basics/JsonHelper.h"
#include "Basics/VelocyPackHelper.h"
#include <velocypack/velocypack-aliases.h>
using namespace arangodb::aql;
using JsonHelper = arangodb::basics::JsonHelper;
////////////////////////////////////////////////////////////////////////////////
/// @brief name of $OLD variable
@ -54,10 +53,11 @@ char const* const Variable::NAME_CURRENT = "$CURRENT";
Variable::Variable(std::string const& name, VariableId id)
: name(name), value(nullptr), id(id) {}
Variable::Variable(arangodb::basics::Json const& json)
: Variable(
JsonHelper::checkAndGetStringValue(json.json(), "name"),
JsonHelper::checkAndGetNumericValue<VariableId>(json.json(), "id")) {}
Variable::Variable(arangodb::velocypack::Slice const slice)
: Variable(arangodb::basics::VelocyPackHelper::checkAndGetStringValue(
slice, "name"),
arangodb::basics::VelocyPackHelper::checkAndGetNumericValue<
VariableId>(slice, "id")) {}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the variable

View File

@ -25,10 +25,19 @@
#define ARANGOD_AQL_VARIABLE_H 1
#include "Basics/Common.h"
#include "Basics/JsonHelper.h"
#include "Aql/types.h"
namespace arangodb {
namespace velocypack {
class Builder;
class Slice;
}
namespace basics {
class Json;
}
namespace aql {
struct Variable {
@ -38,7 +47,7 @@ struct Variable {
Variable(std::string const&, VariableId);
explicit Variable(basics::Json const& json);
explicit Variable(arangodb::velocypack::Slice const);
Variable* clone() const { return new Variable(name, id); }

View File

@ -24,6 +24,11 @@
#include "Aql/VariableGenerator.h"
#include "Basics/Exceptions.h"
#include <velocypack/Iterator.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb::aql;
using Json = arangodb::basics::Json;
@ -130,12 +135,12 @@ Variable* VariableGenerator::createVariable(Variable const* original) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generate a variable from JSON
/// @brief generate a variable from VelocyPack
////////////////////////////////////////////////////////////////////////////////
Variable* VariableGenerator::createVariable(
arangodb::basics::Json const& json) {
auto variable = new Variable(json);
VPackSlice const slice) {
auto variable = new Variable(slice);
auto existing = getVariable(variable->id);
if (existing != nullptr) {
@ -227,21 +232,22 @@ arangodb::basics::Json VariableGenerator::toJson(
}
////////////////////////////////////////////////////////////////////////////////
/// @brief import from JSON
/// @brief import from VelocyPack
////////////////////////////////////////////////////////////////////////////////
void VariableGenerator::fromJson(Json const& query) {
Json jsonAllVariablesList = query.get("variables");
void VariableGenerator::fromVelocyPack(VPackSlice const& query) {
VPackSlice allVariablesList = query.get("variables");
if (!jsonAllVariablesList.isArray()) {
if (!allVariablesList.isArray()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"variables needs to be an array");
}
auto len = jsonAllVariablesList.size();
auto len = allVariablesList.length();
_variables.reserve(len);
for (size_t i = 0; i < len; i++) {
createVariable(jsonAllVariablesList.at(i));
for (auto const& var : VPackArrayIterator(allVariablesList)) {
createVariable(var);
}
}

View File

@ -66,10 +66,10 @@ class VariableGenerator {
Variable* createVariable(std::string const&, bool);
//////////////////////////////////////////////////////////////////////////////
/// @brief generate a variable from JSON
/// @brief generate a variable from VelocyPack
//////////////////////////////////////////////////////////////////////////////
Variable* createVariable(arangodb::basics::Json const&);
Variable* createVariable(arangodb::velocypack::Slice const);
//////////////////////////////////////////////////////////////////////////////
/// @brief clones a variable from an existing one
@ -114,10 +114,10 @@ class VariableGenerator {
arangodb::basics::Json toJson(TRI_memory_zone_t*) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief import from JSON
/// @brief import from VelocyPack
//////////////////////////////////////////////////////////////////////////////
void fromJson(arangodb::basics::Json const& jsonAllVariablesList);
void fromVelocyPack(arangodb::velocypack::Slice const& allVariablesList);
private:
//////////////////////////////////////////////////////////////////////////////

View File

@ -108,15 +108,14 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
bindVarsBuilder->add(bindVars);
}
VPackBuilder optionsBuilder = buildOptions(slice);
VPackSlice options = optionsBuilder.slice();
auto options = std::make_shared<VPackBuilder>(buildOptions(slice));
VPackValueLength l;
char const* queryString = querySlice.getString(l);
arangodb::aql::Query query(
_applicationV8, false, _vocbase, queryString, static_cast<size_t>(l),
bindVarsBuilder,
arangodb::basics::VelocyPackHelper::velocyPackToJson(options),
options,
arangodb::aql::PART_MAIN);
registerQuery(&query);
@ -139,10 +138,11 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
_response->setContentType("application/json; charset=utf-8");
std::shared_ptr<VPackBuilder> extra = buildExtra(queryResult);
VPackSlice opts = options->slice();
size_t batchSize =
arangodb::basics::VelocyPackHelper::getNumericValue<size_t>(
options, "batchSize", 1000);
opts, "batchSize", 1000);
size_t const n = TRI_LengthArrayJson(queryResult.json);
if (n <= batchSize) {
@ -158,7 +158,7 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
result.add("hasMore", VPackValue(false));
if (arangodb::basics::VelocyPackHelper::getBooleanValue(options, "count",
if (arangodb::basics::VelocyPackHelper::getBooleanValue(opts, "count",
false)) {
result.add("count", VPackValue(n));
}
@ -188,9 +188,9 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
TRI_ASSERT(cursors != nullptr);
double ttl = arangodb::basics::VelocyPackHelper::getNumericValue<double>(
options, "ttl", 30);
opts, "ttl", 30);
bool count = arangodb::basics::VelocyPackHelper::getBooleanValue(
options, "count", false);
opts, "count", false);
// steal the query JSON, cursor will take over the ownership
auto j = queryResult.json;
@ -350,10 +350,7 @@ std::shared_ptr<VPackBuilder> RestCursorHandler::buildExtra(
}
if (queryResult.profile != nullptr) {
extra->add(VPackValue("profile"));
int res = arangodb::basics::JsonHelper::toVelocyPack(queryResult.profile, *extra);
if (res != TRI_ERROR_NO_ERROR) {
return nullptr;
}
extra->add(queryResult.profile->slice());
queryResult.profile = nullptr;
}
if (queryResult.warnings == nullptr) {

View File

@ -1120,22 +1120,24 @@ static void JS_ExplainAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
}
}
std::unique_ptr<TRI_json_t> options;
auto options = std::make_shared<VPackBuilder>();
if (args.Length() > 2) {
// handle options
if (!args[2]->IsObject()) {
TRI_V8_THROW_TYPE_ERROR("expecting object for <options>");
}
options.reset(TRI_ObjectToJson(isolate, args[2]));
int res = TRI_V8ToVPack(isolate, *options, args[2], false);
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_THROW_EXCEPTION(res);
}
}
// bind parameters will be freed by the query later
TRI_GET_GLOBALS();
arangodb::aql::Query query(v8g->_applicationV8, true, vocbase,
queryString.c_str(), queryString.size(),
bindVars, options.release(),
bindVars, options,
arangodb::aql::PART_MAIN);
auto queryResult = query.explain();
@ -1205,8 +1207,13 @@ static void JS_ExecuteAqlJson(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_THROW_TYPE_ERROR("expecting object for <queryjson>");
}
std::unique_ptr<TRI_json_t> queryjson(TRI_ObjectToJson(isolate, args[0]));
std::unique_ptr<TRI_json_t> options;
auto queryBuilder = std::make_shared<VPackBuilder>();
int res = TRI_V8ToVPack(isolate, *queryBuilder, args[0], false);
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_THROW_EXCEPTION(res);
}
auto options = std::make_shared<VPackBuilder>();
if (args.Length() > 1) {
// we have options! yikes!
@ -1214,15 +1221,15 @@ static void JS_ExecuteAqlJson(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_THROW_TYPE_ERROR("expecting object for <options>");
}
options.reset(TRI_ObjectToJson(isolate, args[1]));
res = TRI_V8ToVPack(isolate, *options, args[1], false);
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_THROW_EXCEPTION(res);
}
}
TRI_GET_GLOBALS();
arangodb::aql::Query query(v8g->_applicationV8, true, vocbase,
Json(TRI_UNKNOWN_MEM_ZONE, queryjson.release()),
options.get(), arangodb::aql::PART_MAIN);
options.release();
arangodb::aql::Query query(v8g->_applicationV8, true, vocbase, queryBuilder,
options, arangodb::aql::PART_MAIN);
auto queryResult = query.execute(
static_cast<arangodb::aql::QueryRegistry*>(v8g->_queryRegistry));
@ -1246,7 +1253,7 @@ static void JS_ExecuteAqlJson(v8::FunctionCallbackInfo<v8::Value> const& args) {
}
if (queryResult.profile != nullptr) {
result->ForceSet(TRI_V8_ASCII_STRING("profile"),
TRI_ObjectJson(isolate, queryResult.profile));
TRI_VPackToV8(isolate, queryResult.profile->slice()));
}
if (queryResult.warnings == nullptr) {
result->ForceSet(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate));
@ -1291,7 +1298,7 @@ static void JS_ExecuteAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
std::shared_ptr<VPackBuilder> bindVars;
// options
std::unique_ptr<TRI_json_t> options;
auto options = std::make_shared<VPackBuilder>();
if (args.Length() > 1) {
if (!args[1]->IsUndefined() && !args[1]->IsNull() && !args[1]->IsObject()) {
@ -1313,17 +1320,17 @@ static void JS_ExecuteAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_THROW_TYPE_ERROR("expecting object for <options>");
}
options.reset(TRI_ObjectToJson(isolate, args[2]));
int res = TRI_V8ToVPack(isolate, *options, args[2], false);
if (res != TRI_ERROR_NO_ERROR) {
TRI_V8_THROW_EXCEPTION(res);
}
}
// bind parameters will be freed by the query later
TRI_GET_GLOBALS();
arangodb::aql::Query query(v8g->_applicationV8, true, vocbase,
queryString.c_str(), queryString.size(),
bindVars, options.get(),
arangodb::aql::PART_MAIN);
options.release();
queryString.c_str(), queryString.size(), bindVars,
options, arangodb::aql::PART_MAIN);
auto queryResult = query.executeV8(
isolate, static_cast<arangodb::aql::QueryRegistry*>(v8g->_queryRegistry));
@ -1352,7 +1359,7 @@ static void JS_ExecuteAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
}
if (queryResult.profile != nullptr) {
result->ForceSet(TRI_V8_ASCII_STRING("profile"),
TRI_ObjectJson(isolate, queryResult.profile));
TRI_VPackToV8(isolate, queryResult.profile->slice()));
}
if (queryResult.warnings == nullptr) {
result->ForceSet(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate));

View File

@ -126,6 +126,28 @@ class VelocyPackHelper {
static std::string checkAndGetStringValue(VPackSlice const&, char const*);
//////////////////////////////////////////////////////////////////////////////
/// @brief returns a Numeric sub-element, or throws if <name> does not exist
/// or it is not a Number
//////////////////////////////////////////////////////////////////////////////
template <typename T>
static T checkAndGetNumericValue(VPackSlice const& slice, char const* name) {
TRI_ASSERT(slice.isObject());
if (!slice.hasKey(name)) {
std::string msg =
"The attribute '" + std::string(name) + "' was not found.";
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, msg);
}
VPackSlice const sub = slice.get(name);
if (!sub.isNumber()) {
std::string msg =
"The attribute '" + std::string(name) + "' is not a number.";
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, msg);
}
return sub.getNumericValue<T>();
}
//////////////////////////////////////////////////////////////////////////////
/// @brief returns a string value, or the default value if it is not a string
//////////////////////////////////////////////////////////////////////////////