mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel
This commit is contained in:
commit
429ad349d4
|
@ -1079,6 +1079,9 @@ AstNode* Ast::createArithmeticResultNode (double value) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
AstNode* Ast::executeConstExpression (AstNode const* node) {
|
AstNode* Ast::executeConstExpression (AstNode const* node) {
|
||||||
|
// must enter v8 before we can execute any expression
|
||||||
|
v8::HandleScope scope; // do not delete this!
|
||||||
|
_query->enterContext();
|
||||||
TRI_json_t* result = _query->executor()->executeExpression(node);
|
TRI_json_t* result = _query->executor()->executeExpression(node);
|
||||||
|
|
||||||
if (result == nullptr) {
|
if (result == nullptr) {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "Aql/ExecutionBlock.h"
|
#include "Aql/ExecutionBlock.h"
|
||||||
#include "Aql/ExecutionEngine.h"
|
#include "Aql/ExecutionEngine.h"
|
||||||
|
#include "Basics/ScopeGuard.h"
|
||||||
#include "Basics/StringUtils.h"
|
#include "Basics/StringUtils.h"
|
||||||
#include "Basics/StringBuffer.h"
|
#include "Basics/StringBuffer.h"
|
||||||
#include "Basics/json-utilities.h"
|
#include "Basics/json-utilities.h"
|
||||||
|
@ -920,6 +921,16 @@ bool IndexRangeBlock::readIndex () {
|
||||||
|
|
||||||
newCondition = std::unique_ptr<IndexOrCondition>(new IndexOrCondition());
|
newCondition = std::unique_ptr<IndexOrCondition>(new IndexOrCondition());
|
||||||
newCondition.get()->push_back(std::vector<RangeInfo>());
|
newCondition.get()->push_back(std::vector<RangeInfo>());
|
||||||
|
|
||||||
|
// must have a V8 context here to protect Expression::execute()
|
||||||
|
auto engine = _engine;
|
||||||
|
triagens::basics::ScopeGuard guard{
|
||||||
|
[&engine]() -> void { engine->getQuery()->enterContext(); },
|
||||||
|
[&engine]() -> void { engine->getQuery()->exitContext(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
v8::HandleScope scope; // do not delete this!
|
||||||
|
|
||||||
size_t posInExpressions = 0;
|
size_t posInExpressions = 0;
|
||||||
for (auto r : en->_ranges.at(0)) {
|
for (auto r : en->_ranges.at(0)) {
|
||||||
// First create a new RangeInfo containing only the constant
|
// First create a new RangeInfo containing only the constant
|
||||||
|
@ -1843,6 +1854,16 @@ void CalculationBlock::doEvaluation (AqlItemBlock* result) {
|
||||||
|
|
||||||
RegisterId nrRegs = result->getNrRegs();
|
RegisterId nrRegs = result->getNrRegs();
|
||||||
result->setDocumentCollection(_outReg, nullptr);
|
result->setDocumentCollection(_outReg, nullptr);
|
||||||
|
|
||||||
|
// must have a V8 context here to protect Expression::execute()
|
||||||
|
auto engine = _engine;
|
||||||
|
triagens::basics::ScopeGuard guard{
|
||||||
|
[&engine]() -> void { engine->getQuery()->enterContext(); },
|
||||||
|
[&engine]() -> void { engine->getQuery()->exitContext(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
v8::HandleScope scope; // do not delete this!
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
// need to execute the expression
|
// need to execute the expression
|
||||||
AqlValue a = _expression->execute(_trx, docColls, data, nrRegs * i, _inVars, _inRegs);
|
AqlValue a = _expression->execute(_trx, docColls, data, nrRegs * i, _inVars, _inRegs);
|
||||||
|
|
|
@ -473,7 +473,7 @@ struct CoordinatorInstanciator : public WalkerWorker<ExecutionNode> {
|
||||||
jsonNodesList.set("variables", query->ast()->variables()->toJson(TRI_UNKNOWN_MEM_ZONE));
|
jsonNodesList.set("variables", query->ast()->variables()->toJson(TRI_UNKNOWN_MEM_ZONE));
|
||||||
|
|
||||||
result.set("plan", jsonNodesList);
|
result.set("plan", jsonNodesList);
|
||||||
result.set("part", Json("main")); // TODO: set correct query type
|
result.set("part", Json("dependent")); // TODO: set correct query type
|
||||||
|
|
||||||
Json optimizerOptionsRules(Json::List);
|
Json optimizerOptionsRules(Json::List);
|
||||||
Json optimizerOptions(Json::Array);
|
Json optimizerOptions(Json::Array);
|
||||||
|
@ -527,12 +527,12 @@ struct CoordinatorInstanciator : public WalkerWorker<ExecutionNode> {
|
||||||
triagens::basics::Json response(TRI_UNKNOWN_MEM_ZONE, triagens::basics::JsonHelper::fromString(res->answer->body()));
|
triagens::basics::Json response(TRI_UNKNOWN_MEM_ZONE, triagens::basics::JsonHelper::fromString(res->answer->body()));
|
||||||
std::string queryId = triagens::basics::JsonHelper::getStringValue(response.json(), "queryId", "");
|
std::string queryId = triagens::basics::JsonHelper::getStringValue(response.json(), "queryId", "");
|
||||||
|
|
||||||
// std::cout << "DB SERVER ANSWERED WITHOUT ERROR: " << res->answer->body() << ", SHARDID:" << res->shardID << ", QUERYID: " << queryId << "\n";
|
std::cout << "DB SERVER ANSWERED WITHOUT ERROR: " << res->answer->body() << ", SHARDID:" << res->shardID << ", QUERYID: " << queryId << "\n";
|
||||||
queryIds.emplace(std::make_pair(res->shardID, queryId));
|
queryIds.emplace(std::make_pair(res->shardID, queryId));
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// std::cout << "DB SERVER ANSWERED WITH ERROR: " << res->answer->body() << "\n";
|
std::cout << "DB SERVER ANSWERED WITH ERROR: " << res->answer->body() << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete res;
|
delete res;
|
||||||
|
|
|
@ -406,7 +406,7 @@ void Executor::generateCodeExpression (AstNode const* node) {
|
||||||
generateCodeNode(node);
|
generateCodeNode(node);
|
||||||
|
|
||||||
// write epilogue
|
// write epilogue
|
||||||
_buffer->appendText("; })");
|
_buffer->appendText(";})", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -440,15 +440,15 @@ void Executor::generateCodeList (AstNode const* node) {
|
||||||
|
|
||||||
size_t const n = node->numMembers();
|
size_t const n = node->numMembers();
|
||||||
|
|
||||||
_buffer->appendText("[ ");
|
_buffer->appendChar('[');
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
_buffer->appendText(", ");
|
_buffer->appendChar(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
generateCodeNode(node->getMember(i));
|
generateCodeNode(node->getMember(i));
|
||||||
}
|
}
|
||||||
_buffer->appendText(" ]");
|
_buffer->appendChar(']');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -460,21 +460,21 @@ void Executor::generateCodeArray (AstNode const* node) {
|
||||||
|
|
||||||
size_t const n = node->numMembers();
|
size_t const n = node->numMembers();
|
||||||
|
|
||||||
_buffer->appendText("{ ");
|
_buffer->appendChar('{');
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
_buffer->appendText(", ");
|
_buffer->appendChar(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
auto member = node->getMember(i);
|
auto member = node->getMember(i);
|
||||||
|
|
||||||
if (member != nullptr) {
|
if (member != nullptr) {
|
||||||
generateCodeString(member->getStringValue());
|
generateCodeString(member->getStringValue());
|
||||||
_buffer->appendText(" : ");
|
_buffer->appendChar(':');
|
||||||
generateCodeNode(member->getMember(0));
|
generateCodeNode(member->getMember(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_buffer->appendText(" }");
|
_buffer->appendChar('}');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -492,12 +492,12 @@ void Executor::generateCodeUnaryOperator (AstNode const* node) {
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer->appendText("aql.");
|
_buffer->appendText("aql.", 4);
|
||||||
_buffer->appendText((*it).second);
|
_buffer->appendText((*it).second);
|
||||||
_buffer->appendText("(");
|
_buffer->appendChar('(');
|
||||||
|
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendText(")");
|
_buffer->appendChar(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -518,24 +518,24 @@ void Executor::generateCodeBinaryOperator (AstNode const* node) {
|
||||||
bool wrap = (node->type == NODE_TYPE_OPERATOR_BINARY_AND ||
|
bool wrap = (node->type == NODE_TYPE_OPERATOR_BINARY_AND ||
|
||||||
node->type == NODE_TYPE_OPERATOR_BINARY_OR);
|
node->type == NODE_TYPE_OPERATOR_BINARY_OR);
|
||||||
|
|
||||||
_buffer->appendText("aql.");
|
_buffer->appendText("aql.", 4);
|
||||||
_buffer->appendText((*it).second);
|
_buffer->appendText((*it).second);
|
||||||
_buffer->appendText("(");
|
_buffer->appendChar('(');
|
||||||
|
|
||||||
if (wrap) {
|
if (wrap) {
|
||||||
_buffer->appendText("function () { return ");
|
_buffer->appendText("function () { return ");
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendText("}, function () { return ");
|
_buffer->appendText("}, function () { return ");
|
||||||
generateCodeNode(node->getMember(1));
|
generateCodeNode(node->getMember(1));
|
||||||
_buffer->appendText("}");
|
_buffer->appendChar(')');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendText(", ");
|
_buffer->appendChar(',');
|
||||||
generateCodeNode(node->getMember(1));
|
generateCodeNode(node->getMember(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer->appendText(")");
|
_buffer->appendChar(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -553,9 +553,9 @@ void Executor::generateCodeTernaryOperator (AstNode const* node) {
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer->appendText("aql.");
|
_buffer->appendText("aql.", 4);
|
||||||
_buffer->appendText((*it).second);
|
_buffer->appendText((*it).second);
|
||||||
_buffer->appendText("(");
|
_buffer->appendChar('(');
|
||||||
|
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendText(", function () { return ");
|
_buffer->appendText(", function () { return ");
|
||||||
|
@ -575,9 +575,9 @@ void Executor::generateCodeReference (AstNode const* node) {
|
||||||
|
|
||||||
auto variable = static_cast<Variable*>(node->getData());
|
auto variable = static_cast<Variable*>(node->getData());
|
||||||
|
|
||||||
_buffer->appendText("vars[");
|
_buffer->appendText("vars[", 5);
|
||||||
generateCodeString(variable->name.c_str());
|
generateCodeString(variable->name.c_str());
|
||||||
_buffer->appendText("]");
|
_buffer->appendChar(']');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -590,9 +590,9 @@ void Executor::generateCodeVariable (AstNode const* node) {
|
||||||
|
|
||||||
auto variable = static_cast<Variable*>(node->getData());
|
auto variable = static_cast<Variable*>(node->getData());
|
||||||
|
|
||||||
_buffer->appendText("vars[");
|
_buffer->appendText("vars[", 5);
|
||||||
generateCodeString(variable->name.c_str());
|
generateCodeString(variable->name.c_str());
|
||||||
_buffer->appendText("]");
|
_buffer->appendChar(']');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -607,7 +607,7 @@ void Executor::generateCodeCollection (AstNode const* node) {
|
||||||
|
|
||||||
_buffer->appendText("aql.GET_DOCUMENTS(");
|
_buffer->appendText("aql.GET_DOCUMENTS(");
|
||||||
generateCodeString(name);
|
generateCodeString(name);
|
||||||
_buffer->appendText(")");
|
_buffer->appendChar(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -624,14 +624,14 @@ void Executor::generateCodeFunctionCall (AstNode const* node) {
|
||||||
TRI_ASSERT(args != nullptr);
|
TRI_ASSERT(args != nullptr);
|
||||||
TRI_ASSERT(args->type == NODE_TYPE_LIST);
|
TRI_ASSERT(args->type == NODE_TYPE_LIST);
|
||||||
|
|
||||||
_buffer->appendText("aql.");
|
_buffer->appendText("aql.", 4);
|
||||||
_buffer->appendText(func->internalName);
|
_buffer->appendText(func->internalName);
|
||||||
_buffer->appendText("(");
|
_buffer->appendChar('(');
|
||||||
|
|
||||||
size_t const n = args->numMembers();
|
size_t const n = args->numMembers();
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
_buffer->appendText(", ");
|
_buffer->appendChar(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
auto member = args->getMember(i);
|
auto member = args->getMember(i);
|
||||||
|
@ -658,7 +658,7 @@ void Executor::generateCodeFunctionCall (AstNode const* node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer->appendText(")");
|
_buffer->appendChar(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -678,17 +678,17 @@ void Executor::generateCodeUserFunctionCall (AstNode const* node) {
|
||||||
|
|
||||||
_buffer->appendText("aql.FCALL_USER(");
|
_buffer->appendText("aql.FCALL_USER(");
|
||||||
generateCodeString(name);
|
generateCodeString(name);
|
||||||
_buffer->appendText(", [");
|
_buffer->appendText(",[", 2);
|
||||||
|
|
||||||
size_t const n = args->numMembers();
|
size_t const n = args->numMembers();
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
_buffer->appendText(", ");
|
_buffer->appendChar(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
generateCodeNode(args->getMember(i));
|
generateCodeNode(args->getMember(i));
|
||||||
}
|
}
|
||||||
_buffer->appendText("])");
|
_buffer->appendText("])", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -735,9 +735,9 @@ void Executor::generateCodeRange (AstNode const* node) {
|
||||||
|
|
||||||
_buffer->appendText("aql.RANGE(");
|
_buffer->appendText("aql.RANGE(");
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendText(", ");
|
_buffer->appendChar(',');
|
||||||
generateCodeNode(node->getMember(1));
|
generateCodeNode(node->getMember(1));
|
||||||
_buffer->appendText(")");
|
_buffer->appendChar(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -750,9 +750,9 @@ void Executor::generateCodeNamedAccess (AstNode const* node) {
|
||||||
|
|
||||||
_buffer->appendText("aql.DOCUMENT_MEMBER(");
|
_buffer->appendText("aql.DOCUMENT_MEMBER(");
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendText(", ");
|
_buffer->appendChar(',');
|
||||||
generateCodeString(node->getStringValue());
|
generateCodeString(node->getStringValue());
|
||||||
_buffer->appendText(")");
|
_buffer->appendChar(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -765,9 +765,9 @@ void Executor::generateCodeBoundAccess (AstNode const* node) {
|
||||||
|
|
||||||
_buffer->appendText("aql.DOCUMENT_MEMBER(");
|
_buffer->appendText("aql.DOCUMENT_MEMBER(");
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendText(", ");
|
_buffer->appendChar(',');
|
||||||
generateCodeNode(node->getMember(1));
|
generateCodeNode(node->getMember(1));
|
||||||
_buffer->appendText(")");
|
_buffer->appendChar(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -780,9 +780,9 @@ void Executor::generateCodeIndexedAccess (AstNode const* node) {
|
||||||
|
|
||||||
_buffer->appendText("aql.GET_INDEX(");
|
_buffer->appendText("aql.GET_INDEX(");
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendText(", ");
|
_buffer->appendChar(',');
|
||||||
generateCodeNode(node->getMember(1));
|
generateCodeNode(node->getMember(1));
|
||||||
_buffer->appendText(")");
|
_buffer->appendChar(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -86,6 +86,7 @@ Expression::~Expression () {
|
||||||
else if (_type == JSON) {
|
else if (_type == JSON) {
|
||||||
TRI_ASSERT(_data != nullptr);
|
TRI_ASSERT(_data != nullptr);
|
||||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _data);
|
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, _data);
|
||||||
|
_data = nullptr;
|
||||||
// _json is freed automatically by AqlItemBlock
|
// _json is freed automatically by AqlItemBlock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,6 +162,17 @@ void Expression::replaceVariables (std::unordered_map<VariableId, Variable const
|
||||||
|
|
||||||
_ast->replaceVariables(const_cast<AstNode*>(_node), replacements);
|
_ast->replaceVariables(const_cast<AstNode*>(_node), replacements);
|
||||||
|
|
||||||
|
invalidateExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief invalidates an expression
|
||||||
|
/// this only has an effect for V8-based functions, which need to be created,
|
||||||
|
/// used and destroyed in the same context. when a V8 function is used across
|
||||||
|
/// multiple V8 contexts, it must be invalidated in between
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Expression::invalidateExpression () {
|
||||||
if (_type == V8) {
|
if (_type == V8) {
|
||||||
delete _func;
|
delete _func;
|
||||||
_type = UNPROCESSED;
|
_type = UNPROCESSED;
|
||||||
|
|
|
@ -201,6 +201,15 @@ namespace triagens {
|
||||||
|
|
||||||
void replaceVariables (std::unordered_map<VariableId, Variable const*> const&);
|
void replaceVariables (std::unordered_map<VariableId, Variable const*> const&);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief invalidates an expression
|
||||||
|
/// this only has an effect for V8-based functions, which need to be created,
|
||||||
|
/// used and destroyed in the same context. when a V8 function is used across
|
||||||
|
/// multiple V8 contexts, it must be invalidated in between
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void invalidateExpression ();
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- private functions
|
// --SECTION-- private functions
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -39,7 +39,9 @@
|
||||||
#include "Basics/tri-strings.h"
|
#include "Basics/tri-strings.h"
|
||||||
#include "Cluster/ServerState.h"
|
#include "Cluster/ServerState.h"
|
||||||
#include "Utils/AqlTransaction.h"
|
#include "Utils/AqlTransaction.h"
|
||||||
|
#include "Utils/CollectionNameResolver.h"
|
||||||
#include "Utils/Exception.h"
|
#include "Utils/Exception.h"
|
||||||
|
#include "Utils/StandaloneTransactionContext.h"
|
||||||
#include "Utils/V8TransactionContext.h"
|
#include "Utils/V8TransactionContext.h"
|
||||||
#include "V8Server/ApplicationV8.h"
|
#include "V8Server/ApplicationV8.h"
|
||||||
#include "VocBase/vocbase.h"
|
#include "VocBase/vocbase.h"
|
||||||
|
@ -229,6 +231,14 @@ Query::~Query () {
|
||||||
|
|
||||||
if (_context != nullptr) {
|
if (_context != nullptr) {
|
||||||
TRI_ASSERT(! _contextOwnedByExterior);
|
TRI_ASSERT(! _contextOwnedByExterior);
|
||||||
|
|
||||||
|
// unregister transaction and resolver in context
|
||||||
|
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
||||||
|
auto ctx = static_cast<triagens::arango::V8TransactionContext*>(v8g->_transactionContext);
|
||||||
|
if (ctx != nullptr) {
|
||||||
|
ctx->unregisterTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
_applicationV8->exitContext(_context);
|
_applicationV8->exitContext(_context);
|
||||||
_context = nullptr;
|
_context = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +418,7 @@ QueryResult Query::prepare (QueryRegistry* registry) {
|
||||||
// std::cout << "AST: " << triagens::basics::JsonHelper::toString(parser->ast()->toJson(TRI_UNKNOWN_MEM_ZONE, false)) << "\n";
|
// std::cout << "AST: " << triagens::basics::JsonHelper::toString(parser->ast()->toJson(TRI_UNKNOWN_MEM_ZONE, false)) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto trx = new triagens::arango::AqlTransaction(new triagens::arango::V8TransactionContext(true), _vocbase, _collections.collections(), _part == PART_MAIN);
|
auto trx = new triagens::arango::AqlTransaction(new triagens::arango::StandaloneTransactionContext(), _vocbase, _collections.collections(), _part == PART_MAIN);
|
||||||
_trx = trx; // Save the transaction in our object
|
_trx = trx; // Save the transaction in our object
|
||||||
|
|
||||||
bool planRegisters;
|
bool planRegisters;
|
||||||
|
@ -482,6 +492,9 @@ QueryResult Query::prepare (QueryRegistry* registry) {
|
||||||
// varsUsedLater and varsValid are unordered_sets and so their orders
|
// varsUsedLater and varsValid are unordered_sets and so their orders
|
||||||
// are not the same in the serialised and deserialised plans
|
// are not the same in the serialised and deserialised plans
|
||||||
|
|
||||||
|
// return the V8 context
|
||||||
|
exitContext();
|
||||||
|
|
||||||
enterState(EXECUTION);
|
enterState(EXECUTION);
|
||||||
ExecutionEngine* engine(ExecutionEngine::instanciateFromPlan(registry, this, plan.get(), planRegisters));
|
ExecutionEngine* engine(ExecutionEngine::instanciateFromPlan(registry, this, plan.get(), planRegisters));
|
||||||
|
|
||||||
|
@ -617,7 +630,7 @@ QueryResult Query::explain () {
|
||||||
// std::cout << "AST: " << triagens::basics::JsonHelper::toString(parser.ast()->toJson(TRI_UNKNOWN_MEM_ZONE)) << "\n";
|
// std::cout << "AST: " << triagens::basics::JsonHelper::toString(parser.ast()->toJson(TRI_UNKNOWN_MEM_ZONE)) << "\n";
|
||||||
|
|
||||||
// create the transaction object, but do not start it yet
|
// create the transaction object, but do not start it yet
|
||||||
auto trx = new triagens::arango::AqlTransaction(new triagens::arango::V8TransactionContext(true), _vocbase, _collections.collections(), true);
|
auto trx = new triagens::arango::AqlTransaction(new triagens::arango::StandaloneTransactionContext(), _vocbase, _collections.collections(), true);
|
||||||
_trx = trx; // save the pointer in this
|
_trx = trx; // save the pointer in this
|
||||||
|
|
||||||
// we have an AST
|
// we have an AST
|
||||||
|
@ -805,9 +818,17 @@ void Query::enterContext () {
|
||||||
if (! _contextOwnedByExterior) {
|
if (! _contextOwnedByExterior) {
|
||||||
if (_context == nullptr) {
|
if (_context == nullptr) {
|
||||||
_context = _applicationV8->enterContext("STANDARD", _vocbase, false, false);
|
_context = _applicationV8->enterContext("STANDARD", _vocbase, false, false);
|
||||||
|
|
||||||
if (_context == nullptr) {
|
if (_context == nullptr) {
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "cannot enter V8 context");
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "cannot enter V8 context");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// register transaction and resolver in context
|
||||||
|
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
||||||
|
auto ctx = static_cast<triagens::arango::V8TransactionContext*>(v8g->_transactionContext);
|
||||||
|
if (ctx != nullptr) {
|
||||||
|
ctx->registerTransaction(_trx->getInternals());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRI_ASSERT(_context != nullptr);
|
TRI_ASSERT(_context != nullptr);
|
||||||
|
@ -822,6 +843,13 @@ void Query::exitContext () {
|
||||||
if (! _contextOwnedByExterior) {
|
if (! _contextOwnedByExterior) {
|
||||||
if (_context != nullptr) {
|
if (_context != nullptr) {
|
||||||
if (isRunningInCluster()) {
|
if (isRunningInCluster()) {
|
||||||
|
// unregister transaction and resolver in context
|
||||||
|
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
||||||
|
auto ctx = static_cast<triagens::arango::V8TransactionContext*>(v8g->_transactionContext);
|
||||||
|
if (ctx != nullptr) {
|
||||||
|
ctx->unregisterTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
_applicationV8->exitContext(_context);
|
_applicationV8->exitContext(_context);
|
||||||
_context = nullptr;
|
_context = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,13 +98,8 @@ void QueryRegistry::insert (TRI_vocbase_t* vocbase,
|
||||||
|
|
||||||
TRI_ASSERT_EXPENSIVE(_queries.find(vocbase->_name)->second.find(id) != _queries.find(vocbase->_name)->second.end());
|
TRI_ASSERT_EXPENSIVE(_queries.find(vocbase->_name)->second.find(id) != _queries.find(vocbase->_name)->second.end());
|
||||||
|
|
||||||
if (query->part() == PART_MAIN) {
|
// Also, we need to count down the debugging counters for transactions:
|
||||||
// A query that is being shelved must unregister its transaction
|
triagens::arango::TransactionBase::increaseNumbers(-1, -1);
|
||||||
// with the current context:
|
|
||||||
query->trx()->unregisterTransactionWithContext();
|
|
||||||
// Also, we need to count down the debugging counters for transactions:
|
|
||||||
triagens::arango::TransactionBase::increaseNumbers(-1, -1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
|
@ -136,14 +131,8 @@ Query* QueryRegistry::open (TRI_vocbase_t* vocbase,
|
||||||
}
|
}
|
||||||
qi->_isOpen = true;
|
qi->_isOpen = true;
|
||||||
|
|
||||||
// A query that is being opened must register its transaction
|
// We need to count up the debugging counters for transactions:
|
||||||
// with the current context:
|
triagens::arango::TransactionBase::increaseNumbers(1, 1);
|
||||||
|
|
||||||
if (qi->_query->part() == PART_MAIN) {
|
|
||||||
qi->_query->trx()->registerTransactionWithContext();
|
|
||||||
// Also, we need to count up the debugging counters for transactions:
|
|
||||||
triagens::arango::TransactionBase::increaseNumbers(1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return qi->_query;
|
return qi->_query;
|
||||||
}
|
}
|
||||||
|
@ -171,13 +160,8 @@ void QueryRegistry::close (TRI_vocbase_t* vocbase, QueryId id, double ttl) {
|
||||||
"query with given vocbase and id is not open");
|
"query with given vocbase and id is not open");
|
||||||
}
|
}
|
||||||
|
|
||||||
// A query that is being closed must unregister its transaction
|
// We need to count down the debugging counters for transactions:
|
||||||
// with the current context:
|
triagens::arango::TransactionBase::increaseNumbers(-1, -1);
|
||||||
if (qi->_query->part() == PART_MAIN) {
|
|
||||||
qi->_query->trx()->unregisterTransactionWithContext();
|
|
||||||
// Also, we need to count down the debugging counters for transactions:
|
|
||||||
triagens::arango::TransactionBase::increaseNumbers(1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
qi->_isOpen = false;
|
qi->_isOpen = false;
|
||||||
qi->_expires = TRI_microtime() + qi->_timeToLive;
|
qi->_expires = TRI_microtime() + qi->_timeToLive;
|
||||||
|
@ -205,11 +189,8 @@ void QueryRegistry::destroy (std::string const& vocbase, QueryId id) {
|
||||||
// to register the transaction with the current context and adjust
|
// to register the transaction with the current context and adjust
|
||||||
// the debugging counters for transactions:
|
// the debugging counters for transactions:
|
||||||
if (! qi->_isOpen) {
|
if (! qi->_isOpen) {
|
||||||
if (qi->_query->part() == PART_MAIN) {
|
// We need to count up the debugging counters for transactions:
|
||||||
qi->_query->trx()->registerTransactionWithContext();
|
triagens::arango::TransactionBase::increaseNumbers(1, 1);
|
||||||
// Also, we need to count down the debugging counters for transactions:
|
|
||||||
triagens::arango::TransactionBase::increaseNumbers(1, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we can delete it:
|
// Now we can delete it:
|
||||||
|
|
|
@ -114,6 +114,8 @@ void RestAqlHandler::createQueryFromJson () {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "createQueryFromJson" << queryJson.toString() << std::endl;
|
||||||
|
|
||||||
Json plan;
|
Json plan;
|
||||||
Json options;
|
Json options;
|
||||||
|
|
||||||
|
@ -163,7 +165,7 @@ void RestAqlHandler::createQueryFromJson () {
|
||||||
answerBody("queryId", Json(StringUtils::itoa(_qId)))
|
answerBody("queryId", Json(StringUtils::itoa(_qId)))
|
||||||
("ttl", Json(ttl));
|
("ttl", Json(ttl));
|
||||||
|
|
||||||
//std::cout << "RESPONSE BODY IS: " << answerBody.toString() << "\n";
|
std::cout << "RESPONSE BODY IS: " << answerBody.toString() << "\n";
|
||||||
_response->body().appendText(answerBody.toString());
|
_response->body().appendText(answerBody.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,6 +436,11 @@ void RestAqlHandler::useQuery (std::string const& operation,
|
||||||
_queryRegistry->close(_vocbase, _qId);
|
_queryRegistry->close(_vocbase, _qId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
std::cout << "useQuery op:" << operation << "," << idString << std::endl
|
||||||
|
<< queryJson.toString() << std::endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << "useQuery shutdown" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -467,6 +474,8 @@ void RestAqlHandler::useQuery (std::string const& operation,
|
||||||
TRI_ERROR_HTTP_SERVER_ERROR,
|
TRI_ERROR_HTTP_SERVER_ERROR,
|
||||||
"an unknown exception occurred");
|
"an unknown exception occurred");
|
||||||
}
|
}
|
||||||
|
std::cout << "Response of useQuery:" << _response->body().c_str() <<
|
||||||
|
std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -810,7 +819,7 @@ void RestAqlHandler::handleUseQuery (std::string const& operation,
|
||||||
"initializeCursor lead to an exception");
|
"initializeCursor lead to an exception");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
answerBody("error", Json(res == TRI_ERROR_NO_ERROR))
|
answerBody("error", Json(res != TRI_ERROR_NO_ERROR))
|
||||||
("code", Json(static_cast<double>(res)));
|
("code", Json(static_cast<double>(res)));
|
||||||
}
|
}
|
||||||
else if (operation == "shutdown") {
|
else if (operation == "shutdown") {
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "Cluster/ServerState.h"
|
#include "Cluster/ServerState.h"
|
||||||
#include "Utils/CollectionNameResolver.h"
|
#include "Utils/CollectionNameResolver.h"
|
||||||
#include "Utils/Transaction.h"
|
#include "Utils/Transaction.h"
|
||||||
#include "Utils/V8TransactionContext.h"
|
#include "Utils/StandaloneTransactionContext.h"
|
||||||
#include "VocBase/transaction.h"
|
#include "VocBase/transaction.h"
|
||||||
#include "VocBase/vocbase.h"
|
#include "VocBase/vocbase.h"
|
||||||
#include <v8.h>
|
#include <v8.h>
|
||||||
|
@ -63,9 +63,10 @@ namespace triagens {
|
||||||
|
|
||||||
AqlTransaction (TransactionContext* transactionContext,
|
AqlTransaction (TransactionContext* transactionContext,
|
||||||
TRI_vocbase_t* vocbase,
|
TRI_vocbase_t* vocbase,
|
||||||
std::map<std::string, triagens::aql::Collection*>* collections,
|
std::map<std::string, triagens::aql::Collection*> const* collections,
|
||||||
bool isMainTransaction)
|
bool isMainTransaction)
|
||||||
: Transaction(transactionContext, vocbase, 0) {
|
: Transaction(transactionContext, vocbase, 0),
|
||||||
|
_collections(*collections) {
|
||||||
|
|
||||||
this->addHint(TRI_TRANSACTION_HINT_LOCK_ENTIRELY, false);
|
this->addHint(TRI_TRANSACTION_HINT_LOCK_ENTIRELY, false);
|
||||||
if (! isMainTransaction) {
|
if (! isMainTransaction) {
|
||||||
|
@ -164,44 +165,26 @@ namespace triagens {
|
||||||
return trxColl->_collection->_collection;
|
return trxColl->_collection->_collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief registerTransaction
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int registerTransactionWithContext () {
|
|
||||||
// This calls the method in the V8TransactionContext
|
|
||||||
return this->_transactionContext->registerTransaction(this->_trx);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief unregisterTransaction
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int unregisterTransactionWithContext () {
|
|
||||||
// This calls the method in the V8TransactionContext
|
|
||||||
return this->_transactionContext->unregisterTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief clone, used to make daughter transactions for parts of a distributed
|
/// @brief clone, used to make daughter transactions for parts of a distributed
|
||||||
/// AQL query running on the coordinator
|
/// AQL query running on the coordinator
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
triagens::arango::AqlTransaction* clone () const {
|
triagens::arango::AqlTransaction* clone () const {
|
||||||
auto colls = new std::map<std::string, triagens::aql::Collection*>();
|
return new triagens::arango::AqlTransaction(
|
||||||
try {
|
new triagens::arango::StandaloneTransactionContext(),
|
||||||
auto res = new triagens::arango::AqlTransaction(
|
this->_vocbase,
|
||||||
new triagens::arango::V8TransactionContext(true),
|
&_collections, false);
|
||||||
this->_vocbase,
|
|
||||||
colls, false);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
delete colls;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief keep a copy of the collections, this is needed for the clone
|
||||||
|
/// operation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::map<std::string, triagens::aql::Collection*> _collections;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,8 +73,9 @@ TRI_transaction_t* StandaloneTransactionContext::getParentTransaction () const {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int StandaloneTransactionContext::registerTransaction (TRI_transaction_t* trx) {
|
int StandaloneTransactionContext::registerTransaction (TRI_transaction_t* trx) {
|
||||||
TRI_ASSERT(_resolver == nullptr);
|
if (_resolver == nullptr) {
|
||||||
_resolver = new CollectionNameResolver(trx->_vocbase);
|
_resolver = new CollectionNameResolver(trx->_vocbase);
|
||||||
|
}
|
||||||
|
|
||||||
return TRI_ERROR_NO_ERROR;
|
return TRI_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,14 @@ namespace triagens {
|
||||||
return _vocbase;
|
return _vocbase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief return internals of transaction
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline TRI_transaction_t* getInternals () const {
|
||||||
|
return _trx;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief add a transaction hint
|
/// @brief add a transaction hint
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -136,6 +136,7 @@ void V8TransactionContext::deleteResolver () {
|
||||||
TRI_ASSERT(hasResolver());
|
TRI_ASSERT(hasResolver());
|
||||||
delete _resolver;
|
delete _resolver;
|
||||||
_resolver = nullptr;
|
_resolver = nullptr;
|
||||||
|
_ownResolver = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Scope guard class
|
||||||
|
///
|
||||||
|
/// @file
|
||||||
|
///
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
||||||
|
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
/// you may not use this file except in compliance with the License.
|
||||||
|
/// You may obtain a copy of the License at
|
||||||
|
///
|
||||||
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
///
|
||||||
|
/// Unless required by applicable law or agreed to in writing, software
|
||||||
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
/// See the License for the specific language governing permissions and
|
||||||
|
/// limitations under the License.
|
||||||
|
///
|
||||||
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
///
|
||||||
|
/// @author Jan Steemann
|
||||||
|
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
||||||
|
/// @author Copyright 2009-2013, triAGENS GmbH, Cologne, Germany
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef ARANGODB_BASICS_SCOPE_GUARD_H
|
||||||
|
#define ARANGODB_BASICS_SCOPE_GUARD_H 1
|
||||||
|
|
||||||
|
#include "Basics/Common.h"
|
||||||
|
|
||||||
|
namespace triagens {
|
||||||
|
namespace basics {
|
||||||
|
class ScopeGuard {
|
||||||
|
public:
|
||||||
|
ScopeGuard (std::function<void()> onEnter,
|
||||||
|
std::function<void()> onExit)
|
||||||
|
: _onExit(onExit) {
|
||||||
|
onEnter();
|
||||||
|
}
|
||||||
|
|
||||||
|
~ScopeGuard () {
|
||||||
|
_onExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::function<void()> _onExit;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// --SECTION-- END-OF-FILE
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Local Variables:
|
||||||
|
// mode: outline-minor
|
||||||
|
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||||
|
// End:
|
Loading…
Reference in New Issue