mirror of https://gitee.com/bigwinds/arangodb
Bug fix/pre release woes (#2988)
* fixed issue #2982 * updated CHANGELOG
This commit is contained in:
parent
e8d6ff21d0
commit
e6c6c5acda
|
@ -1,6 +1,12 @@
|
|||
devel
|
||||
-----
|
||||
|
||||
* fixed issue #2978: log something more obvious when you log a Buffer
|
||||
|
||||
* fixed issue #2982: AQL parse error?
|
||||
|
||||
* fixed docs for issue #2968: Collection _key autoincrement value increases on error
|
||||
|
||||
* fixed issue #3011: Optimizer rule reduce-extraction-to-projection breaks queries
|
||||
|
||||
* Now allowing to restore users in a sharded environment as well
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
|
||||
#include "Aql/Ast.h"
|
||||
#include "Aql/Arithmetic.h"
|
||||
#include "Aql/Executor.h"
|
||||
#include "Aql/Function.h"
|
||||
#include "Aql/Graphs.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/V8Executor.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/StringRef.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
|
@ -1683,30 +1683,35 @@ void Ast::validateAndOptimize() {
|
|||
std::unordered_map<Variable const*, AstNode const*> variableDefinitions;
|
||||
int64_t stopOptimizationRequests = 0;
|
||||
int64_t nestingLevel = 0;
|
||||
bool isInFilter = false;
|
||||
int64_t filterDepth = -1; // -1 = not in filter
|
||||
bool hasSeenAnyWriteNode = false;
|
||||
bool hasSeenWriteNodeInCurrentScope = false;
|
||||
};
|
||||
|
||||
auto preVisitor = [&](AstNode const* node, void* data) -> bool {
|
||||
auto ctx = static_cast<TraversalContext*>(data);
|
||||
if (ctx->filterDepth >= 0) {
|
||||
++ctx->filterDepth;
|
||||
}
|
||||
|
||||
if (node->type == NODE_TYPE_FILTER) {
|
||||
static_cast<TraversalContext*>(data)->isInFilter = true;
|
||||
TRI_ASSERT(ctx->filterDepth == -1);
|
||||
ctx->filterDepth = 0;
|
||||
} else if (node->type == NODE_TYPE_FCALL) {
|
||||
auto func = static_cast<Function*>(node->getData());
|
||||
TRI_ASSERT(func != nullptr);
|
||||
|
||||
if (func->externalName == "NOOPT") {
|
||||
// NOOPT will turn all function optimizations off
|
||||
++(static_cast<TraversalContext*>(data)->stopOptimizationRequests);
|
||||
++(ctx->stopOptimizationRequests);
|
||||
}
|
||||
} else if (node->type == NODE_TYPE_COLLECTION) {
|
||||
// note the level on which we first saw a collection
|
||||
auto c = static_cast<TraversalContext*>(data);
|
||||
c->collectionsFirstSeen.emplace(node->getString(), c->nestingLevel);
|
||||
ctx->collectionsFirstSeen.emplace(node->getString(), ctx->nestingLevel);
|
||||
} else if (node->type == NODE_TYPE_AGGREGATIONS) {
|
||||
++(static_cast<TraversalContext*>(data)->stopOptimizationRequests);
|
||||
++ctx->stopOptimizationRequests;
|
||||
} else if (node->type == NODE_TYPE_SUBQUERY) {
|
||||
++static_cast<TraversalContext*>(data)->nestingLevel;
|
||||
++ctx->nestingLevel;
|
||||
} else if (node->hasFlag(FLAG_BIND_PARAMETER)) {
|
||||
return false;
|
||||
} else if (node->type == NODE_TYPE_REMOVE ||
|
||||
|
@ -1714,42 +1719,44 @@ void Ast::validateAndOptimize() {
|
|||
node->type == NODE_TYPE_UPDATE ||
|
||||
node->type == NODE_TYPE_REPLACE ||
|
||||
node->type == NODE_TYPE_UPSERT) {
|
||||
auto c = static_cast<TraversalContext*>(data);
|
||||
|
||||
if (c->hasSeenWriteNodeInCurrentScope) {
|
||||
if (ctx->hasSeenWriteNodeInCurrentScope) {
|
||||
// no two data-modification nodes are allowed in the same scope
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_MULTI_MODIFY);
|
||||
}
|
||||
c->hasSeenWriteNodeInCurrentScope = true;
|
||||
ctx->hasSeenWriteNodeInCurrentScope = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
auto postVisitor = [&](AstNode const* node, void* data) -> void {
|
||||
auto ctx = static_cast<TraversalContext*>(data);
|
||||
if (ctx->filterDepth >= 0) {
|
||||
--ctx->filterDepth;
|
||||
}
|
||||
|
||||
if (node->type == NODE_TYPE_FILTER) {
|
||||
static_cast<TraversalContext*>(data)->isInFilter = false;
|
||||
ctx->filterDepth = -1;
|
||||
} else if (node->type == NODE_TYPE_SUBQUERY) {
|
||||
--static_cast<TraversalContext*>(data)->nestingLevel;
|
||||
--ctx->nestingLevel;
|
||||
} else if (node->type == NODE_TYPE_REMOVE ||
|
||||
node->type == NODE_TYPE_INSERT ||
|
||||
node->type == NODE_TYPE_UPDATE ||
|
||||
node->type == NODE_TYPE_REPLACE ||
|
||||
node->type == NODE_TYPE_UPSERT) {
|
||||
auto c = static_cast<TraversalContext*>(data);
|
||||
c->hasSeenAnyWriteNode = true;
|
||||
ctx->hasSeenAnyWriteNode = true;
|
||||
|
||||
TRI_ASSERT(c->hasSeenWriteNodeInCurrentScope);
|
||||
c->hasSeenWriteNodeInCurrentScope = false;
|
||||
TRI_ASSERT(ctx->hasSeenWriteNodeInCurrentScope);
|
||||
ctx->hasSeenWriteNodeInCurrentScope = false;
|
||||
|
||||
auto collection = node->getMember(1);
|
||||
std::string name = collection->getString();
|
||||
c->writeCollectionsSeen.emplace(name);
|
||||
ctx->writeCollectionsSeen.emplace(name);
|
||||
|
||||
auto it = c->collectionsFirstSeen.find(name);
|
||||
auto it = ctx->collectionsFirstSeen.find(name);
|
||||
|
||||
if (it != c->collectionsFirstSeen.end()) {
|
||||
if ((*it).second < c->nestingLevel) {
|
||||
if (it != ctx->collectionsFirstSeen.end()) {
|
||||
if ((*it).second < ctx->nestingLevel) {
|
||||
name = "collection '" + name;
|
||||
name.push_back('\'');
|
||||
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_ACCESS_AFTER_MODIFICATION, name.c_str());
|
||||
|
@ -1761,10 +1768,10 @@ void Ast::validateAndOptimize() {
|
|||
|
||||
if (func->externalName == "NOOPT") {
|
||||
// NOOPT will turn all function optimizations off
|
||||
--(static_cast<TraversalContext*>(data)->stopOptimizationRequests);
|
||||
--ctx->stopOptimizationRequests;
|
||||
}
|
||||
} else if (node->type == NODE_TYPE_AGGREGATIONS) {
|
||||
--(static_cast<TraversalContext*>(data)->stopOptimizationRequests);
|
||||
--ctx->stopOptimizationRequests;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1787,7 +1794,7 @@ void Ast::validateAndOptimize() {
|
|||
if (node->type == NODE_TYPE_OPERATOR_BINARY_AND ||
|
||||
node->type == NODE_TYPE_OPERATOR_BINARY_OR) {
|
||||
return this->optimizeBinaryOperatorLogical(
|
||||
node, static_cast<TraversalContext*>(data)->isInFilter);
|
||||
node, static_cast<TraversalContext*>(data)->filterDepth == 1);
|
||||
}
|
||||
|
||||
if (node->type == NODE_TYPE_OPERATOR_BINARY_EQ ||
|
||||
|
@ -2585,7 +2592,7 @@ AstNode* Ast::optimizeBinaryOperatorLogical(AstNode* node,
|
|||
return createNodeValueBool(false);
|
||||
}
|
||||
|
||||
// right-operand was trueish, now return it
|
||||
// right-operand was trueish, now return just left
|
||||
return lhs;
|
||||
} else if (node->type == NODE_TYPE_OPERATOR_BINARY_OR) {
|
||||
if (rhs->isTrue()) {
|
||||
|
|
|
@ -21,13 +21,13 @@
|
|||
/// @author Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Aql/AstNode.h"
|
||||
#include "AstNode.h"
|
||||
#include "Aql/Ast.h"
|
||||
#include "Aql/Executor.h"
|
||||
#include "Aql/Function.h"
|
||||
#include "Aql/Quantifier.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/Scopes.h"
|
||||
#include "Aql/V8Executor.h"
|
||||
#include "Aql/types.h"
|
||||
#include "Basics/StringBuffer.h"
|
||||
#include "Basics/Utf8Helper.h"
|
||||
|
|
|
@ -26,13 +26,13 @@
|
|||
#include "Aql/AqlValue.h"
|
||||
#include "Aql/Ast.h"
|
||||
#include "Aql/AttributeAccessor.h"
|
||||
#include "Aql/Executor.h"
|
||||
#include "Aql/ExpressionContext.h"
|
||||
#include "Aql/BaseExpressionContext.h"
|
||||
#include "Aql/Function.h"
|
||||
#include "Aql/Functions.h"
|
||||
#include "Aql/Quantifier.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/V8Executor.h"
|
||||
#include "Aql/V8Expression.h"
|
||||
#include "Aql/Variable.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
|
|
|
@ -48,8 +48,8 @@ class AqlItemBlock;
|
|||
struct AqlValue;
|
||||
class Ast;
|
||||
class AttributeAccessor;
|
||||
class Executor;
|
||||
class ExpressionContext;
|
||||
class V8Executor;
|
||||
struct V8Expression;
|
||||
|
||||
/// @brief AqlExpression, used in execution plans and execution blocks
|
||||
|
@ -333,7 +333,7 @@ class Expression {
|
|||
Ast* _ast;
|
||||
|
||||
/// @brief the V8 executor
|
||||
Executor* _executor;
|
||||
V8Executor* _executor;
|
||||
|
||||
/// @brief the AST node that contains the expression to execute
|
||||
AstNode* _node;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "Aql/ExecutionBlock.h"
|
||||
#include "Aql/ExecutionEngine.h"
|
||||
#include "Aql/ExecutionPlan.h"
|
||||
#include "Aql/Executor.h"
|
||||
#include "Aql/V8Executor.h"
|
||||
#include "Aql/Optimizer.h"
|
||||
#include "Aql/Parser.h"
|
||||
#include "Aql/PlanCache.h"
|
||||
|
@ -1044,10 +1044,10 @@ void Query::engine(ExecutionEngine* engine) {
|
|||
}
|
||||
|
||||
/// @brief get v8 executor
|
||||
Executor* Query::executor() {
|
||||
V8Executor* Query::executor() {
|
||||
if (_executor == nullptr) {
|
||||
// the executor is a singleton per query
|
||||
_executor.reset(new Executor(_queryOptions.literalSizeThreshold));
|
||||
_executor.reset(new V8Executor(_queryOptions.literalSizeThreshold));
|
||||
}
|
||||
|
||||
TRI_ASSERT(_executor != nullptr);
|
||||
|
|
|
@ -61,10 +61,10 @@ struct AstNode;
|
|||
class Ast;
|
||||
class ExecutionEngine;
|
||||
class ExecutionPlan;
|
||||
class Executor;
|
||||
class Query;
|
||||
struct QueryProfile;
|
||||
class QueryRegistry;
|
||||
class V8Executor;
|
||||
|
||||
/// @brief equery part
|
||||
enum QueryPart { PART_MAIN, PART_DEPENDENT };
|
||||
|
@ -193,7 +193,7 @@ class Query {
|
|||
QueryResult explain();
|
||||
|
||||
/// @brief get v8 executor
|
||||
Executor* executor();
|
||||
V8Executor* executor();
|
||||
|
||||
/// @brief return the engine, if prepared
|
||||
ExecutionEngine* engine() const { return _engine.get(); }
|
||||
|
@ -289,7 +289,7 @@ class Query {
|
|||
TRI_vocbase_t* _vocbase;
|
||||
|
||||
/// @brief V8 code executor
|
||||
std::unique_ptr<Executor> _executor;
|
||||
std::unique_ptr<V8Executor> _executor;
|
||||
|
||||
/// @brief the currently used V8 context
|
||||
V8Context* _context;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
/// @author Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Executor.h"
|
||||
#include "V8Executor.h"
|
||||
#include "Aql/AstNode.h"
|
||||
#include "Aql/AqlFunctionFeature.h"
|
||||
#include "Aql/Functions.h"
|
||||
|
@ -42,10 +42,10 @@ using namespace arangodb::aql;
|
|||
|
||||
/// @brief minimum number of array members / object attributes for considering
|
||||
/// an array / object literal "big" and pulling it out of the expression
|
||||
size_t const Executor::DefaultLiteralSizeThreshold = 32;
|
||||
size_t const V8Executor::DefaultLiteralSizeThreshold = 32;
|
||||
|
||||
/// @brief creates an executor
|
||||
Executor::Executor(int64_t literalSizeThreshold)
|
||||
V8Executor::V8Executor(int64_t literalSizeThreshold)
|
||||
: _buffer(nullptr),
|
||||
_constantRegisters(),
|
||||
_literalSizeThreshold(literalSizeThreshold >= 0
|
||||
|
@ -53,10 +53,10 @@ Executor::Executor(int64_t literalSizeThreshold)
|
|||
: DefaultLiteralSizeThreshold) {}
|
||||
|
||||
/// @brief destroys an executor
|
||||
Executor::~Executor() { delete _buffer; }
|
||||
V8Executor::~V8Executor() { delete _buffer; }
|
||||
|
||||
/// @brief generates an expression execution object
|
||||
V8Expression* Executor::generateExpression(AstNode const* node) {
|
||||
V8Expression* V8Executor::generateExpression(AstNode const* node) {
|
||||
ISOLATE;
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
|
@ -69,7 +69,7 @@ V8Expression* Executor::generateExpression(AstNode const* node) {
|
|||
|
||||
generateCodeExpression(node);
|
||||
|
||||
// std::cout << "Executor::generateExpression: " <<
|
||||
// std::cout << "V8Executor::generateExpression: " <<
|
||||
// std::string(_buffer->c_str(), _buffer->length()) << "\n";
|
||||
v8::Handle<v8::Object> constantValues = v8::Object::New(isolate);
|
||||
for (auto const& it : _constantRegisters) {
|
||||
|
@ -115,14 +115,14 @@ V8Expression* Executor::generateExpression(AstNode const* node) {
|
|||
/// @brief executes an expression directly
|
||||
/// this method is called during AST optimization and will be used to calculate
|
||||
/// values for constant expressions
|
||||
int Executor::executeExpression(Query* query, AstNode const* node,
|
||||
int V8Executor::executeExpression(Query* query, AstNode const* node,
|
||||
VPackBuilder& builder) {
|
||||
ISOLATE;
|
||||
|
||||
_constantRegisters.clear();
|
||||
generateCodeExpression(node);
|
||||
|
||||
// std::cout << "Executor::ExecuteExpression: " <<
|
||||
// std::cout << "V8Executor::ExecuteExpression: " <<
|
||||
// std::string(_buffer->c_str(), _buffer->length()) << "\n";
|
||||
v8::HandleScope scope(isolate);
|
||||
v8::TryCatch tryCatch;
|
||||
|
@ -180,13 +180,13 @@ int Executor::executeExpression(Query* query, AstNode const* node,
|
|||
}
|
||||
|
||||
/// @brief returns a reference to a built-in function
|
||||
Function const* Executor::getFunctionByName(std::string const& name) {
|
||||
Function const* V8Executor::getFunctionByName(std::string const& name) {
|
||||
auto functions = AqlFunctionFeature::AQLFUNCTIONS;
|
||||
return functions->byName(name);
|
||||
}
|
||||
|
||||
/// @brief traverse the expression and note all user-defined functions
|
||||
void Executor::detectUserFunctions(AstNode const* node) {
|
||||
void V8Executor::detectUserFunctions(AstNode const* node) {
|
||||
if (node == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ void Executor::detectUserFunctions(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief traverse the expression and note all (big) array/object literals
|
||||
void Executor::detectConstantValues(AstNode const* node, AstNodeType previous) {
|
||||
void V8Executor::detectConstantValues(AstNode const* node, AstNodeType previous) {
|
||||
if (node == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ void Executor::detectConstantValues(AstNode const* node, AstNodeType previous) {
|
|||
}
|
||||
|
||||
/// @brief convert an AST node to a V8 object
|
||||
v8::Handle<v8::Value> Executor::toV8(v8::Isolate* isolate,
|
||||
v8::Handle<v8::Value> V8Executor::toV8(v8::Isolate* isolate,
|
||||
AstNode const* node) const {
|
||||
if (node->type == NODE_TYPE_ARRAY) {
|
||||
size_t const n = node->numMembers();
|
||||
|
@ -295,7 +295,7 @@ v8::Handle<v8::Value> Executor::toV8(v8::Isolate* isolate,
|
|||
|
||||
/// @brief checks if a V8 exception has occurred and throws an appropriate C++
|
||||
/// exception from it if so
|
||||
void Executor::HandleV8Error(v8::TryCatch& tryCatch,
|
||||
void V8Executor::HandleV8Error(v8::TryCatch& tryCatch,
|
||||
v8::Handle<v8::Value>& result,
|
||||
arangodb::basics::StringBuffer* const buffer,
|
||||
bool duringCompile) {
|
||||
|
@ -391,7 +391,7 @@ void Executor::HandleV8Error(v8::TryCatch& tryCatch,
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for an arbitrary expression
|
||||
void Executor::generateCodeExpression(AstNode const* node) {
|
||||
void V8Executor::generateCodeExpression(AstNode const* node) {
|
||||
// initialize and/or clear the buffer
|
||||
initializeBuffer();
|
||||
TRI_ASSERT(_buffer != nullptr);
|
||||
|
@ -442,19 +442,19 @@ void Executor::generateCodeExpression(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generates code for a string value
|
||||
void Executor::generateCodeString(char const* value, size_t length) {
|
||||
void V8Executor::generateCodeString(char const* value, size_t length) {
|
||||
TRI_ASSERT(value != nullptr);
|
||||
|
||||
_buffer->appendJsonEncoded(value, length);
|
||||
}
|
||||
|
||||
/// @brief generates code for a string value
|
||||
void Executor::generateCodeString(std::string const& value) {
|
||||
void V8Executor::generateCodeString(std::string const& value) {
|
||||
_buffer->appendJsonEncoded(value.c_str(), value.size());
|
||||
}
|
||||
|
||||
/// @brief generate JavaScript code for an array
|
||||
void Executor::generateCodeArray(AstNode const* node) {
|
||||
void V8Executor::generateCodeArray(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
|
||||
size_t const n = node->numMembers();
|
||||
|
@ -484,7 +484,7 @@ void Executor::generateCodeArray(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for an array
|
||||
void Executor::generateCodeForcedArray(AstNode const* node, int64_t levels) {
|
||||
void V8Executor::generateCodeForcedArray(AstNode const* node, int64_t levels) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
|
||||
if (levels > 1) {
|
||||
|
@ -523,7 +523,7 @@ void Executor::generateCodeForcedArray(AstNode const* node, int64_t levels) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for an object
|
||||
void Executor::generateCodeObject(AstNode const* node) {
|
||||
void V8Executor::generateCodeObject(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
|
||||
if (node->containsDynamicAttributeName()) {
|
||||
|
@ -535,7 +535,7 @@ void Executor::generateCodeObject(AstNode const* node) {
|
|||
|
||||
/// @brief generate JavaScript code for an object with dynamically named
|
||||
/// attributes
|
||||
void Executor::generateCodeDynamicObject(AstNode const* node) {
|
||||
void V8Executor::generateCodeDynamicObject(AstNode const* node) {
|
||||
size_t const n = node->numMembers();
|
||||
// very conservative minimum bound
|
||||
_buffer->reserve(64 + n * 10);
|
||||
|
@ -562,7 +562,7 @@ void Executor::generateCodeDynamicObject(AstNode const* node) {
|
|||
|
||||
/// @brief generate JavaScript code for an object without dynamically named
|
||||
/// attributes
|
||||
void Executor::generateCodeRegularObject(AstNode const* node) {
|
||||
void V8Executor::generateCodeRegularObject(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
|
||||
size_t const n = node->numMembers();
|
||||
|
@ -598,7 +598,7 @@ void Executor::generateCodeRegularObject(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a unary operator
|
||||
void Executor::generateCodeUnaryOperator(AstNode const* node) {
|
||||
void V8Executor::generateCodeUnaryOperator(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
auto functions = AqlFunctionFeature::AQLFUNCTIONS;
|
||||
|
@ -613,7 +613,7 @@ void Executor::generateCodeUnaryOperator(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a binary operator
|
||||
void Executor::generateCodeBinaryOperator(AstNode const* node) {
|
||||
void V8Executor::generateCodeBinaryOperator(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 2);
|
||||
auto functions = AqlFunctionFeature::AQLFUNCTIONS;
|
||||
|
@ -642,7 +642,7 @@ void Executor::generateCodeBinaryOperator(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a binary array operator
|
||||
void Executor::generateCodeBinaryArrayOperator(AstNode const* node) {
|
||||
void V8Executor::generateCodeBinaryArrayOperator(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 3);
|
||||
auto functions = AqlFunctionFeature::AQLFUNCTIONS;
|
||||
|
@ -667,7 +667,7 @@ void Executor::generateCodeBinaryArrayOperator(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for the ternary operator
|
||||
void Executor::generateCodeTernaryOperator(AstNode const* node) {
|
||||
void V8Executor::generateCodeTernaryOperator(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 3);
|
||||
auto functions = AqlFunctionFeature::AQLFUNCTIONS;
|
||||
|
@ -686,7 +686,7 @@ void Executor::generateCodeTernaryOperator(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a variable (read) access
|
||||
void Executor::generateCodeReference(AstNode const* node) {
|
||||
void V8Executor::generateCodeReference(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 0);
|
||||
|
||||
|
@ -698,7 +698,7 @@ void Executor::generateCodeReference(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a variable
|
||||
void Executor::generateCodeVariable(AstNode const* node) {
|
||||
void V8Executor::generateCodeVariable(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 0);
|
||||
|
||||
|
@ -710,7 +710,7 @@ void Executor::generateCodeVariable(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a full collection access
|
||||
void Executor::generateCodeCollection(AstNode const* node) {
|
||||
void V8Executor::generateCodeCollection(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 0);
|
||||
|
||||
|
@ -720,7 +720,7 @@ void Executor::generateCodeCollection(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a call to a built-in function
|
||||
void Executor::generateCodeFunctionCall(AstNode const* node) {
|
||||
void V8Executor::generateCodeFunctionCall(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
||||
|
@ -775,7 +775,7 @@ void Executor::generateCodeFunctionCall(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a call to a user-defined function
|
||||
void Executor::generateCodeUserFunctionCall(AstNode const* node) {
|
||||
void V8Executor::generateCodeUserFunctionCall(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
||||
|
@ -798,7 +798,7 @@ void Executor::generateCodeUserFunctionCall(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for an expansion (i.e. [*] operator)
|
||||
void Executor::generateCodeExpansion(AstNode const* node) {
|
||||
void V8Executor::generateCodeExpansion(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
|
||||
TRI_ASSERT(node->numMembers() == 5);
|
||||
|
@ -856,7 +856,7 @@ void Executor::generateCodeExpansion(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for an expansion iterator
|
||||
void Executor::generateCodeExpansionIterator(AstNode const* node) {
|
||||
void V8Executor::generateCodeExpansionIterator(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 2);
|
||||
|
||||
|
@ -865,7 +865,7 @@ void Executor::generateCodeExpansionIterator(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a range (i.e. 1..10)
|
||||
void Executor::generateCodeRange(AstNode const* node) {
|
||||
void V8Executor::generateCodeRange(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 2);
|
||||
|
||||
|
@ -877,7 +877,7 @@ void Executor::generateCodeRange(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a named attribute access
|
||||
void Executor::generateCodeNamedAccess(AstNode const* node) {
|
||||
void V8Executor::generateCodeNamedAccess(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 1);
|
||||
|
||||
|
@ -889,7 +889,7 @@ void Executor::generateCodeNamedAccess(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a bound attribute access
|
||||
void Executor::generateCodeBoundAccess(AstNode const* node) {
|
||||
void V8Executor::generateCodeBoundAccess(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 2);
|
||||
|
||||
|
@ -901,7 +901,7 @@ void Executor::generateCodeBoundAccess(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for an indexed attribute access
|
||||
void Executor::generateCodeIndexedAccess(AstNode const* node) {
|
||||
void V8Executor::generateCodeIndexedAccess(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 2);
|
||||
|
||||
|
@ -914,7 +914,7 @@ void Executor::generateCodeIndexedAccess(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief generate JavaScript code for a node
|
||||
void Executor::generateCodeNode(AstNode const* node) {
|
||||
void V8Executor::generateCodeNode(AstNode const* node) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
|
||||
switch (node->type) {
|
||||
|
@ -1028,7 +1028,7 @@ void Executor::generateCodeNode(AstNode const* node) {
|
|||
}
|
||||
|
||||
/// @brief create the string buffer
|
||||
arangodb::basics::StringBuffer* Executor::initializeBuffer() {
|
||||
arangodb::basics::StringBuffer* V8Executor::initializeBuffer() {
|
||||
if (_buffer == nullptr) {
|
||||
_buffer = new arangodb::basics::StringBuffer(TRI_UNKNOWN_MEM_ZONE, 512, false);
|
||||
|
|
@ -21,8 +21,8 @@
|
|||
/// @author Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_AQL_EXECUTOR_H
|
||||
#define ARANGOD_AQL_EXECUTOR_H 1
|
||||
#ifndef ARANGOD_AQL_V8EXECUTOR_H
|
||||
#define ARANGOD_AQL_V8EXECUTOR_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Aql/AstNode.h"
|
||||
|
@ -44,13 +44,13 @@ struct Function;
|
|||
class Query;
|
||||
struct V8Expression;
|
||||
|
||||
class Executor {
|
||||
class V8Executor {
|
||||
public:
|
||||
/// @brief create the executor
|
||||
explicit Executor(int64_t);
|
||||
explicit V8Executor(int64_t);
|
||||
|
||||
/// @brief destroy the executor
|
||||
~Executor();
|
||||
~V8Executor();
|
||||
|
||||
public:
|
||||
/// @brief generates an expression execution object
|
|
@ -23,9 +23,9 @@
|
|||
|
||||
#include "V8Expression.h"
|
||||
#include "Aql/AqlItemBlock.h"
|
||||
#include "Aql/Executor.h"
|
||||
#include "Aql/ExpressionContext.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/V8Executor.h"
|
||||
#include "Aql/Variable.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "V8/v8-conv.h"
|
||||
|
@ -133,7 +133,7 @@ AqlValue V8Expression::execute(v8::Isolate* isolate, Query* query,
|
|||
|
||||
v8g->_query = old;
|
||||
|
||||
Executor::HandleV8Error(tryCatch, result, nullptr, false);
|
||||
V8Executor::HandleV8Error(tryCatch, result, nullptr, false);
|
||||
} catch (...) {
|
||||
v8g->_query = old;
|
||||
// bubble up exception
|
||||
|
|
|
@ -129,7 +129,6 @@ SET(ARANGOD_SOURCES
|
|||
Aql/ExecutionNode.cpp
|
||||
Aql/ExecutionPlan.cpp
|
||||
Aql/ExecutionStats.cpp
|
||||
Aql/Executor.cpp
|
||||
Aql/Expression.cpp
|
||||
Aql/FixedVarExpressionContext.cpp
|
||||
Aql/Function.cpp
|
||||
|
@ -170,6 +169,7 @@ SET(ARANGOD_SOURCES
|
|||
Aql/TraversalBlock.cpp
|
||||
Aql/TraversalConditionFinder.cpp
|
||||
Aql/TraversalNode.cpp
|
||||
Aql/V8Executor.cpp
|
||||
Aql/V8Expression.cpp
|
||||
Aql/Variable.cpp
|
||||
Aql/VariableGenerator.cpp
|
||||
|
|
|
@ -17,6 +17,10 @@ global.DEFINE_MODULE('buffer', (function () {
|
|||
const exports = {};
|
||||
|
||||
var SlowBuffer = require('internal').SlowBuffer;
|
||||
|
||||
SlowBuffer.prototype._PRINT = function(context) {
|
||||
context.output += '[Buffer, length: ' + this.length + ']';
|
||||
};
|
||||
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
|
@ -230,6 +234,10 @@ global.DEFINE_MODULE('buffer', (function () {
|
|||
this.offset = 0;
|
||||
}
|
||||
|
||||
this._PRINT = function(context) {
|
||||
context.output += '[Buffer, length: ' + this.length + ']';
|
||||
};
|
||||
|
||||
// optimize by branching logic for new allocations
|
||||
if (typeof subject !== 'number') {
|
||||
if (type === 'string') {
|
||||
|
|
|
@ -867,3 +867,8 @@ int TRI_AppendCsvDoubleStringBuffer(TRI_string_buffer_t* self, double d) {
|
|||
AppendChar(self, ';');
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, arangodb::basics::StringBuffer const& buffer) {
|
||||
stream.write(buffer.begin(), buffer.length());
|
||||
return stream;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "Zip/zip.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iosfwd>
|
||||
|
||||
/// @brief string buffer with formatting routines
|
||||
struct TRI_string_buffer_t {
|
||||
|
@ -467,6 +468,7 @@ class StringBuffer {
|
|||
|
||||
/// @brief returns length of the character buffer
|
||||
size_t length() const { return TRI_LengthStringBuffer(&_buffer); }
|
||||
size_t size() const { return TRI_LengthStringBuffer(&_buffer); }
|
||||
|
||||
/// @brief returns capacity of the character buffer
|
||||
size_t capacity() const { return TRI_CapacityStringBuffer(&_buffer); }
|
||||
|
@ -767,4 +769,6 @@ class StringBuffer {
|
|||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream&, arangodb::basics::StringBuffer const&);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue