1
0
Fork 0

Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel

This commit is contained in:
Heiko Kernbach 2014-10-17 12:14:32 +02:00
commit 751812e483
11 changed files with 191 additions and 45 deletions

View File

@ -111,6 +111,23 @@ std::vector<std::string> Collection::shardIds () const {
return ids;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the shard keys of a collection
////////////////////////////////////////////////////////////////////////////////
std::vector<std::string> Collection::shardKeys () const {
auto clusterInfo = triagens::arango::ClusterInfo::instance();
auto collectionInfo = clusterInfo->getCollection(std::string(vocbase->_name), name);
if (collectionInfo.get() == nullptr) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "collection not found");
}
std::vector<std::string> keys;
for (auto const& x : collectionInfo.get()->shardKeys()) {
keys.emplace_back(x);
}
return keys;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the indexes of the collection
////////////////////////////////////////////////////////////////////////////////

View File

@ -145,6 +145,12 @@ namespace triagens {
std::vector<std::string> shardIds () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the shard keys of a collection
////////////////////////////////////////////////////////////////////////////////
std::vector<std::string> shardKeys () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the indexes of the collection
////////////////////////////////////////////////////////////////////////////////

View File

@ -2448,7 +2448,6 @@ void DistributeNode::toJsonHelper (triagens::basics::Json& nodes,
("collection", triagens::basics::Json(_collection->getName()))
("varId", triagens::basics::Json(static_cast<int>(_varId)));
// And add it:
nodes(json);
}

View File

@ -421,6 +421,16 @@ void Executor::generateCodeString (char const* value) {
_buffer->appendChar('"');
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generates code for a string value
////////////////////////////////////////////////////////////////////////////////
void Executor::generateCodeString (std::string const& value) {
_buffer->appendChar('"');
_buffer->appendJsonEncoded(value.c_str());
_buffer->appendChar('"');
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generate JavaScript code for a list
////////////////////////////////////////////////////////////////////////////////

View File

@ -27,8 +27,8 @@
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_AQL_V8_EXECUTOR_H
#define ARANGODB_AQL_V8_EXECUTOR_H 1
#ifndef ARANGODB_AQL_EXECUTOR_H
#define ARANGODB_AQL_EXECUTOR_H 1
#include "Basics/Common.h"
#include "Aql/Function.h"
@ -121,6 +121,12 @@ namespace triagens {
void generateCodeString (char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief generates code for a string value
////////////////////////////////////////////////////////////////////////////////
void generateCodeString (std::string const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief generate JavaScript code for a list
////////////////////////////////////////////////////////////////////////////////

View File

@ -1688,7 +1688,6 @@ int triagens::aql::scatterInCluster (Optimizer* opt,
// re-link with the remote node
node->addDependency(remoteNode);
// insert another remote node
remoteNode = new RemoteNode(plan, plan->nextId(), vocbase, collection, "", "", "");
@ -1742,21 +1741,30 @@ int triagens::aql::distributeInCluster (Optimizer* opt,
auto const nodeType = node->getType();
if (nodeType != ExecutionNode::INSERT &&
nodeType != ExecutionNode::UPDATE &&
nodeType != ExecutionNode::REPLACE &&
nodeType != ExecutionNode::REMOVE) {
opt->addPlan(plan, rule->level, wasModified);
return TRI_ERROR_NO_ERROR;
}
Collection const* collection = static_cast<ModificationNode*>(node)->collection();
if (nodeType == ExecutionNode::REMOVE) {
// check if collection shard keys are only _key
std::vector<std::string> shardKeys = collection->shardKeys();
if (shardKeys.size() != 1 || shardKeys[0] != "_key") {
opt->addPlan(plan, rule->level, wasModified);
return TRI_ERROR_NO_ERROR;
}
}
auto deps = node->getDependencies();
TRI_ASSERT(deps.size() == 1);
// unlink the node
plan->unlinkNode(node, true);
// extract database and collection from plan node
// extract database from plan node
TRI_vocbase_t* vocbase = static_cast<ModificationNode*>(node)->vocbase();
Collection const* collection = static_cast<ModificationNode*>(node)->collection();
// insert a distribute node
TRI_ASSERT(node->getVariablesUsedHere().size() == 1);
@ -1782,6 +1790,7 @@ int triagens::aql::distributeInCluster (Optimizer* opt,
opt->addPlan(plan, rule->level, wasModified);
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief move filters up into the cluster distribution part of the plan
/// this rule modifies the plan in place

View File

@ -37,6 +37,7 @@
#include "Basics/JsonHelper.h"
#include "Basics/json.h"
#include "Basics/tri-strings.h"
#include "Cluster/ServerState.h"
#include "Utils/AqlTransaction.h"
#include "Utils/Exception.h"
#include "Utils/V8TransactionContext.h"
@ -117,6 +118,7 @@ TRI_json_t* Profile::toJson (TRI_memory_zone_t*) {
////////////////////////////////////////////////////////////////////////////////
Query::Query (triagens::arango::ApplicationV8* applicationV8,
bool contextOwnedByExterior,
TRI_vocbase_t* vocbase,
char const* queryString,
size_t queryLength,
@ -126,6 +128,7 @@ Query::Query (triagens::arango::ApplicationV8* applicationV8,
: _applicationV8(applicationV8),
_vocbase(vocbase),
_executor(nullptr),
_context(nullptr),
_queryString(queryString),
_queryLength(queryLength),
_queryJson(),
@ -140,7 +143,9 @@ Query::Query (triagens::arango::ApplicationV8* applicationV8,
_parser(nullptr),
_trx(nullptr),
_engine(nullptr),
_part(part) {
_part(part),
_clusterStatus(-1),
_contextOwnedByExterior(contextOwnedByExterior) {
TRI_ASSERT(_vocbase != nullptr);
@ -160,6 +165,7 @@ Query::Query (triagens::arango::ApplicationV8* applicationV8,
////////////////////////////////////////////////////////////////////////////////
Query::Query (triagens::arango::ApplicationV8* applicationV8,
bool contextOwnedByExterior,
TRI_vocbase_t* vocbase,
triagens::basics::Json queryStruct,
TRI_json_t* options,
@ -167,6 +173,7 @@ Query::Query (triagens::arango::ApplicationV8* applicationV8,
: _applicationV8(applicationV8),
_vocbase(vocbase),
_executor(nullptr),
_context(nullptr),
_queryString(nullptr),
_queryLength(0),
_queryJson(queryStruct),
@ -181,7 +188,9 @@ Query::Query (triagens::arango::ApplicationV8* applicationV8,
_parser(nullptr),
_trx(nullptr),
_engine(nullptr),
_part(part) {
_part(part),
_clusterStatus(-1),
_contextOwnedByExterior(contextOwnedByExterior) {
TRI_ASSERT(_vocbase != nullptr);
@ -218,6 +227,12 @@ Query::~Query () {
_executor = nullptr;
}
if (_context != nullptr) {
TRI_ASSERT(! _contextOwnedByExterior);
_applicationV8->exitContext(_context);
_context = nullptr;
}
if (_ast != nullptr) {
delete _ast;
_ast = nullptr;
@ -247,7 +262,8 @@ Query* Query::clone (QueryPart part) {
std::unique_ptr<Query> clone;
try {
clone.reset(new Query(_applicationV8,
clone.reset(new Query(_applicationV8,
false,
_vocbase,
_queryString,
_queryLength,
@ -765,6 +781,55 @@ char* Query::registerString (std::string const& p,
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not we are running in a cluster
////////////////////////////////////////////////////////////////////////////////
bool Query::isRunningInCluster () {
if (_clusterStatus == -1) {
// not yet determined
_clusterStatus = 0;
if (triagens::arango::ServerState::instance()->isRunningInCluster()) {
_clusterStatus = 1;
}
}
TRI_ASSERT(_clusterStatus == 0 || _clusterStatus == 1);
return (_clusterStatus == 1);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief enter a V8 context
////////////////////////////////////////////////////////////////////////////////
void Query::enterContext () {
if (! _contextOwnedByExterior) {
if (_context == nullptr) {
_context = _applicationV8->enterContext("STANDARD", _vocbase, false, false);
if (_context == nullptr) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "cannot enter V8 context");
}
}
TRI_ASSERT(_context != nullptr);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a V8 context
////////////////////////////////////////////////////////////////////////////////
void Query::exitContext () {
if (! _contextOwnedByExterior) {
if (_context != nullptr) {
if (isRunningInCluster()) {
_applicationV8->exitContext(_context);
_context = nullptr;
}
}
TRI_ASSERT(_context == nullptr);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief fetch a boolean value from the options
////////////////////////////////////////////////////////////////////////////////

View File

@ -38,15 +38,12 @@
#include "Aql/types.h"
#include "Utils/AqlTransaction.h"
#include "Utils/V8TransactionContext.h"
#include "V8Server/ApplicationV8.h"
struct TRI_json_t;
struct TRI_vocbase_s;
namespace triagens {
namespace arango {
class ApplicationV8;
}
namespace aql {
struct AstNode;
@ -132,6 +129,7 @@ namespace triagens {
public:
Query (triagens::arango::ApplicationV8*,
bool,
struct TRI_vocbase_s*,
char const*,
size_t,
@ -140,6 +138,7 @@ namespace triagens {
QueryPart);
Query (triagens::arango::ApplicationV8*,
bool,
struct TRI_vocbase_s*,
triagens::basics::Json queryStruct,
struct TRI_json_t*,
@ -368,10 +367,28 @@ namespace triagens {
void setPlan (ExecutionPlan *plan);
////////////////////////////////////////////////////////////////////////////////
/// @brief enter a V8 context
////////////////////////////////////////////////////////////////////////////////
void enterContext ();
////////////////////////////////////////////////////////////////////////////////
/// @brief exits a V8 context
////////////////////////////////////////////////////////////////////////////////
void exitContext ();
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not we are running in a cluster
////////////////////////////////////////////////////////////////////////////////
bool isRunningInCluster ();
////////////////////////////////////////////////////////////////////////////////
/// @brief fetch a boolean value from the options
////////////////////////////////////////////////////////////////////////////////
@ -426,98 +443,104 @@ namespace triagens {
/// @brief application v8 used in the query, we need this for V8 context access
////////////////////////////////////////////////////////////////////////////////
triagens::arango::ApplicationV8* _applicationV8;
triagens::arango::ApplicationV8* _applicationV8;
////////////////////////////////////////////////////////////////////////////////
/// @brief all nodes created in the AST - will be used for freeing them later
////////////////////////////////////////////////////////////////////////////////
std::vector<AstNode*> _nodes;
std::vector<AstNode*> _nodes;
////////////////////////////////////////////////////////////////////////////////
/// @brief pointer to vocbase the query runs in
////////////////////////////////////////////////////////////////////////////////
struct TRI_vocbase_s* _vocbase;
struct TRI_vocbase_s* _vocbase;
////////////////////////////////////////////////////////////////////////////////
/// @brief V8 code executor
////////////////////////////////////////////////////////////////////////////////
Executor* _executor;
Executor* _executor;
////////////////////////////////////////////////////////////////////////////////
/// @brief the currently used V8 context
////////////////////////////////////////////////////////////////////////////////
triagens::arango::ApplicationV8::V8Context* _context;
////////////////////////////////////////////////////////////////////////////////
/// @brief the actual query string
////////////////////////////////////////////////////////////////////////////////
char const* _queryString;
char const* _queryString;
////////////////////////////////////////////////////////////////////////////////
/// @brief length of the query string in bytes
////////////////////////////////////////////////////////////////////////////////
size_t const _queryLength;
size_t const _queryLength;
////////////////////////////////////////////////////////////////////////////////
/// @brief query in a JSON structure
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json const _queryJson;
triagens::basics::Json const _queryJson;
////////////////////////////////////////////////////////////////////////////////
/// @brief bind parameters for the query
////////////////////////////////////////////////////////////////////////////////
BindParameters _bindParameters;
BindParameters _bindParameters;
////////////////////////////////////////////////////////////////////////////////
/// @brief query options
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* _options;
TRI_json_t* _options;
////////////////////////////////////////////////////////////////////////////////
/// @brief collections used in the query
////////////////////////////////////////////////////////////////////////////////
Collections _collections;
Collections _collections;
////////////////////////////////////////////////////////////////////////////////
/// @brief all strings created in the query - used for easy memory deallocation
////////////////////////////////////////////////////////////////////////////////
std::vector<char const*> _strings;
std::vector<char const*> _strings;
////////////////////////////////////////////////////////////////////////////////
/// @brief _ast, we need an ast to manage the memory for AstNodes, even
/// if we do not have a parser, because AstNodes occur in plans and engines
////////////////////////////////////////////////////////////////////////////////
Ast* _ast;
Ast* _ast;
////////////////////////////////////////////////////////////////////////////////
/// @brief query execution profile
////////////////////////////////////////////////////////////////////////////////
Profile* _profile;
Profile* _profile;
////////////////////////////////////////////////////////////////////////////////
/// @brief current state the query is in (used for profiling and error messages)
////////////////////////////////////////////////////////////////////////////////
ExecutionState _state;
ExecutionState _state;
////////////////////////////////////////////////////////////////////////////////
/// @brief the ExecutionPlan object, if the query is prepared
////////////////////////////////////////////////////////////////////////////////
ExecutionPlan* _plan;
ExecutionPlan* _plan;
////////////////////////////////////////////////////////////////////////////////
/// @brief the Parser object, if the query is prepared
////////////////////////////////////////////////////////////////////////////////
Parser* _parser;
Parser* _parser;
////////////////////////////////////////////////////////////////////////////////
/// @brief the transaction object, in a distributed query every part of
@ -531,13 +554,25 @@ namespace triagens {
/// @brief the ExecutionEngine object, if the query is prepared
////////////////////////////////////////////////////////////////////////////////
ExecutionEngine* _engine;
ExecutionEngine* _engine;
////////////////////////////////////////////////////////////////////////////////
/// @brief the query part
////////////////////////////////////////////////////////////////////////////////
QueryPart const _part;
QueryPart const _part;
////////////////////////////////////////////////////////////////////////////////
/// @brief internal variable we use to determine whether we are in a cluster
////////////////////////////////////////////////////////////////////////////////
short int _clusterStatus;
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not someone else has acquired a V8 context for us
////////////////////////////////////////////////////////////////////////////////
bool const _contextOwnedByExterior;
};
}

View File

@ -127,7 +127,7 @@ void RestAqlHandler::createQueryFromJson () {
std::string const part = JsonHelper::getStringValue(queryJson.json(), "part", "");
auto query = new Query(_applicationV8, _vocbase, plan, options.steal(), (part == "main" ? PART_MAIN : PART_DEPENDENT));
auto query = new Query(_applicationV8, false, _vocbase, plan, options.steal(), (part == "main" ? PART_MAIN : PART_DEPENDENT));
QueryResult res = query->prepare(_queryRegistry);
if (res.code != TRI_ERROR_NO_ERROR) {
generateError(HttpResponse::BAD, TRI_ERROR_QUERY_BAD_JSON_PLAN,
@ -188,7 +188,7 @@ void RestAqlHandler::parseQuery () {
return;
}
auto query = new Query(_applicationV8, _vocbase, queryString.c_str(), queryString.size(),
auto query = new Query(_applicationV8, false, _vocbase, queryString.c_str(), queryString.size(),
nullptr, nullptr, PART_MAIN);
QueryResult res = query->parse();
if (res.code != TRI_ERROR_NO_ERROR) {
@ -244,7 +244,7 @@ void RestAqlHandler::explainQuery () {
Json options;
options = queryJson.get("options").copy(); // cannot throw
auto query = new Query(_applicationV8, _vocbase, queryString.c_str(), queryString.size(),
auto query = new Query(_applicationV8, false, _vocbase, queryString.c_str(), queryString.size(),
parameters.steal(), options.steal(), PART_MAIN);
QueryResult res = query->explain();
if (res.code != TRI_ERROR_NO_ERROR) {
@ -304,7 +304,7 @@ void RestAqlHandler::createQueryFromString () {
Json options;
options = queryJson.get("options").copy(); // cannot throw
auto query = new Query(_applicationV8, _vocbase, queryString.c_str(), queryString.size(),
auto query = new Query(_applicationV8, false, _vocbase, queryString.c_str(), queryString.size(),
parameters.steal(), options.steal(), (part == "main" ? PART_MAIN : PART_DEPENDENT));
QueryResult res = query->prepare(_queryRegistry);
if (res.code != TRI_ERROR_NO_ERROR) {

View File

@ -255,7 +255,6 @@ bool ServerState::isRunningInCluster () {
_role == ServerState::ROLE_COORDINATOR);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the server id
////////////////////////////////////////////////////////////////////////////////

View File

@ -819,10 +819,10 @@ static v8::Handle<v8::Value> JS_ParseAql (v8::Arguments const& argv) {
TRI_V8_TYPE_ERROR(scope, "expecting string for <querystring>");
}
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
string const&& queryString = TRI_ObjectToString(argv[0]);
triagens::aql::Query query(v8g->_applicationV8, vocbase, queryString.c_str(), queryString.size(), nullptr, nullptr, triagens::aql::PART_MAIN);
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
triagens::aql::Query query(v8g->_applicationV8, true, vocbase, queryString.c_str(), queryString.size(), nullptr, nullptr, triagens::aql::PART_MAIN);
auto parseResult = query.parse();
@ -908,7 +908,7 @@ static v8::Handle<v8::Value> JS_ExplainAql (v8::Arguments const& argv) {
// bind parameters will be freed by the query later
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
triagens::aql::Query query(v8g->_applicationV8, vocbase, queryString.c_str(), queryString.size(), parameters, options, triagens::aql::PART_MAIN);
triagens::aql::Query query(v8g->_applicationV8, true, vocbase, queryString.c_str(), queryString.size(), parameters, options, triagens::aql::PART_MAIN);
auto queryResult = query.explain();
@ -1000,8 +1000,8 @@ static v8::Handle<v8::Value> JS_ExecuteAqlJson (v8::Arguments const& argv) {
}
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
triagens::aql::Query query(v8g->_applicationV8, true, vocbase, Json(TRI_UNKNOWN_MEM_ZONE, queryjson), options, triagens::aql::PART_MAIN);
triagens::aql::Query query(v8g->_applicationV8, vocbase, Json(TRI_UNKNOWN_MEM_ZONE, queryjson), options, triagens::aql::PART_MAIN);
auto queryResult = query.execute(static_cast<triagens::aql::QueryRegistry*>(v8g->_queryRegistry));
if (queryResult.code != TRI_ERROR_NO_ERROR) {
@ -1135,10 +1135,10 @@ static v8::Handle<v8::Value> JS_ExecuteAql (v8::Arguments const& argv) {
options = TRI_ObjectToJson(argv[2]);
}
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
// bind parameters will be freed by the query later
triagens::aql::Query query(v8g->_applicationV8, vocbase, queryString.c_str(), queryString.size(), parameters, options, triagens::aql::PART_MAIN);
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
triagens::aql::Query query(v8g->_applicationV8, true, vocbase, queryString.c_str(), queryString.size(), parameters, options, triagens::aql::PART_MAIN);
auto queryResult = query.execute(static_cast<triagens::aql::QueryRegistry*>(v8g->_queryRegistry));
if (queryResult.code != TRI_ERROR_NO_ERROR) {