mirror of https://gitee.com/bigwinds/arangodb
refactoring
This commit is contained in:
parent
6ebfbfef49
commit
2aad264e77
|
@ -58,8 +58,8 @@ Ast::Ast (Query* query,
|
|||
Parser* parser)
|
||||
: _query(query),
|
||||
_parser(parser),
|
||||
_variableId(0),
|
||||
_nodes(),
|
||||
_strings(),
|
||||
_scopes(),
|
||||
_bindParameters(),
|
||||
_collectionNames(),
|
||||
|
@ -72,7 +72,6 @@ Ast::Ast (Query* query,
|
|||
TRI_ASSERT(_parser != nullptr);
|
||||
|
||||
_nodes.reserve(32);
|
||||
_strings.reserve(32);
|
||||
|
||||
startSubQuery();
|
||||
|
||||
|
@ -84,11 +83,6 @@ Ast::Ast (Query* query,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ast::~Ast () {
|
||||
// free strings
|
||||
for (auto it = _strings.begin(); it != _strings.end(); ++it) {
|
||||
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, const_cast<char*>(*it));
|
||||
}
|
||||
|
||||
// free nodes
|
||||
for (auto it = _nodes.begin(); it != _nodes.end(); ++it) {
|
||||
delete (*it);
|
||||
|
@ -99,8 +93,20 @@ Ast::~Ast () {
|
|||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate a new unique variable name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char const* Ast::generateName () {
|
||||
std::string const variableName(std::to_string(nextVariableId())); // to_string: c++11
|
||||
|
||||
// register the string and return a copy of it
|
||||
return _query->registerString(variableName.c_str(), variableName.size(), false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief convert the AST into JSON
|
||||
/// the caller is responsible for freeing the JSON later
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_json_t* Ast::toJson (TRI_memory_zone_t* zone) {
|
||||
|
@ -127,47 +133,6 @@ void Ast::addOperation (AstNode* node) {
|
|||
_root->addMember(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief register a string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* Ast::registerString (char const* p,
|
||||
size_t length,
|
||||
bool mustUnescape) {
|
||||
|
||||
if (p == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
static char const* empty = "";
|
||||
// optimisation for the empty string
|
||||
return const_cast<char*>(empty);
|
||||
}
|
||||
|
||||
char* copy = nullptr;
|
||||
if (mustUnescape) {
|
||||
size_t outLength;
|
||||
copy = TRI_UnescapeUtf8StringZ(TRI_UNKNOWN_MEM_ZONE, p, length, &outLength);
|
||||
}
|
||||
else {
|
||||
copy = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, p, length);
|
||||
}
|
||||
|
||||
if (copy == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
try {
|
||||
_strings.push_back(copy);
|
||||
}
|
||||
catch (...) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST for node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -187,27 +152,6 @@ AstNode* Ast::createNodeFor (char const* variableName,
|
|||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST for node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode* Ast::createNodeFor (char const* variable1Name,
|
||||
char const* variable2Name) {
|
||||
if (variable1Name == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
AstNode* node = createNode(NODE_TYPE_FOR);
|
||||
|
||||
AstNode* variable = createNodeVariable(variable1Name, true);
|
||||
node->addMember(variable);
|
||||
|
||||
auto reference = createNodeReference(variable2Name);
|
||||
node->addMember(reference);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST let node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -241,24 +185,6 @@ AstNode* Ast::createNodeFilter (AstNode const* expression) {
|
|||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST filter node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode* Ast::createNodeFilter (char const* variableName) {
|
||||
if (variableName == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
AstNode* node = createNode(NODE_TYPE_FILTER);
|
||||
node->setIntValue(static_cast<int64_t>(FILTER_UNKNOWN));
|
||||
|
||||
auto reference = createNodeReference(variableName);
|
||||
node->addMember(reference);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST return node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -427,7 +353,7 @@ AstNode* Ast::createNodeVariable (char const* name,
|
|||
AstNode* node = createNode(NODE_TYPE_VARIABLE);
|
||||
node->setStringValue(name);
|
||||
|
||||
auto variable = _scopes.addVariable(name, isUserDefined);
|
||||
auto variable = _scopes.addVariable(nextVariableId(), name, isUserDefined);
|
||||
node->setData(static_cast<void*>(variable));
|
||||
|
||||
return node;
|
||||
|
@ -742,7 +668,7 @@ AstNode* Ast::createNodeFunctionCall (char const* functionName,
|
|||
}
|
||||
|
||||
std::string const normalizedName = normalizeFunctionName(functionName);
|
||||
char* fname = registerString(normalizedName.c_str(), normalizedName.size(), false);
|
||||
char* fname = _query->registerString(normalizedName.c_str(), normalizedName.size(), false);
|
||||
|
||||
AstNode* node;
|
||||
|
||||
|
@ -824,7 +750,7 @@ void Ast::injectBindParameters (BindParameters& parameters) {
|
|||
}
|
||||
|
||||
// turn node into a collection node
|
||||
char const* name = registerString(value->_value._string.data, value->_value._string.length - 1, false);
|
||||
char const* name = _query->registerString(value->_value._string.data, value->_value._string.length - 1, false);
|
||||
|
||||
node = createNodeCollection(name);
|
||||
|
||||
|
@ -1300,6 +1226,7 @@ AstNode* Ast::optimizeTernaryOperator (AstNode* node) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief optimizes a reference to a variable
|
||||
/// references are replaced with constants if possible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode* Ast::optimizeReference (AstNode* node) {
|
||||
|
@ -1312,6 +1239,7 @@ AstNode* Ast::optimizeReference (AstNode* node) {
|
|||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
// constant propagation
|
||||
if (variable->constValue() == nullptr) {
|
||||
// note which variables we are reading
|
||||
variable->increaseReferenceCount();
|
||||
|
@ -1319,8 +1247,6 @@ AstNode* Ast::optimizeReference (AstNode* node) {
|
|||
return node;
|
||||
}
|
||||
|
||||
// TODO: re-activate constant propagation??
|
||||
return node;
|
||||
return static_cast<AstNode*>(variable->constValue());
|
||||
}
|
||||
|
||||
|
@ -1387,8 +1313,6 @@ AstNode* Ast::optimizeLet (AstNode* node,
|
|||
}
|
||||
}
|
||||
else if (pass == 1) {
|
||||
/* TODO: re-add reference counting
|
||||
|
||||
if (! v->isReferenceCounted()) {
|
||||
// this optimizes away the assignment of variables which are never read
|
||||
// (i.e. assigned-only variables). this is currently not free of side-effects:
|
||||
|
@ -1403,7 +1327,6 @@ AstNode* Ast::optimizeLet (AstNode* node,
|
|||
// variables
|
||||
return createNodeNop();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return node;
|
||||
|
@ -1452,7 +1375,7 @@ AstNode* Ast::nodeFromJson (TRI_json_t const* json) {
|
|||
}
|
||||
|
||||
if (json->_type == TRI_JSON_STRING) {
|
||||
char const* value = registerString(json->_value._string.data, json->_value._string.length - 1, false);
|
||||
char const* value = _query->registerString(json->_value._string.data, json->_value._string.length - 1, false);
|
||||
return createNodeValueString(value);
|
||||
}
|
||||
|
||||
|
@ -1479,7 +1402,7 @@ AstNode* Ast::nodeFromJson (TRI_json_t const* json) {
|
|||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
char const* attributeName = registerString(key->_value._string.data, key->_value._string.length - 1, false);
|
||||
char const* attributeName = _query->registerString(key->_value._string.data, key->_value._string.length - 1, false);
|
||||
|
||||
node->addMember(createNodeArrayElement(attributeName, nodeFromJson(value)));
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ast (Query*,
|
||||
Parser*);
|
||||
Parser*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroy the AST
|
||||
|
@ -190,8 +190,23 @@ namespace triagens {
|
|||
_writeOptions = node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the next variable id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline VariableId nextVariableId () {
|
||||
return ++_variableId;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate a new unique variable name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char const* generateName ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief convert the AST into JSON
|
||||
/// the caller is responsible for freeing the JSON later
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_json_s* toJson (TRI_memory_zone_t*);
|
||||
|
@ -202,14 +217,6 @@ namespace triagens {
|
|||
|
||||
void addOperation (AstNode*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief register a string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* registerString (char const*,
|
||||
size_t,
|
||||
bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST for node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -217,13 +224,6 @@ namespace triagens {
|
|||
AstNode* createNodeFor (char const*,
|
||||
AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST for node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode* createNodeFor (char const*,
|
||||
char const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST let node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -238,12 +238,6 @@ namespace triagens {
|
|||
|
||||
AstNode* createNodeFilter (AstNode const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST filter node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AstNode* createNodeFilter (char const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an AST return node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -614,7 +608,7 @@ namespace triagens {
|
|||
/// @brief the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Query* _query;
|
||||
Query* _query;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the query parser
|
||||
|
@ -622,18 +616,18 @@ namespace triagens {
|
|||
|
||||
Parser* _parser;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the next assigned variable id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _variableId;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief all nodes created in the AST - will be used for freeing them later
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<AstNode*> _nodes;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief all strings created in the AST - will be used for freeing them later
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<char const*> _strings;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief all scopes used in the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
#include "Aql/Parser.h"
|
||||
#include "Aql/AstNode.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
|
||||
using namespace triagens::aql;
|
||||
|
||||
|
@ -49,12 +48,8 @@ Parser::Parser (Query* query)
|
|||
_remainingLength(query->queryLength()),
|
||||
_offset(0),
|
||||
_marker(nullptr),
|
||||
_uniqueId(0),
|
||||
_stack() {
|
||||
|
||||
Aqllex_init(&_scanner);
|
||||
Aqlset_extra(this, _scanner);
|
||||
|
||||
_ast = new Ast(query, this);
|
||||
|
||||
_stack.reserve(16);
|
||||
|
@ -65,8 +60,6 @@ Parser::Parser (Query* query)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Parser::~Parser () {
|
||||
Aqllex_destroy(_scanner);
|
||||
|
||||
if (_ast != nullptr) {
|
||||
delete _ast;
|
||||
}
|
||||
|
@ -118,16 +111,29 @@ ParseResult Parser::parse () {
|
|||
// start main scope
|
||||
auto scopes = _ast->scopes();
|
||||
scopes->start(AQL_SCOPE_MAIN);
|
||||
|
||||
Aqllex_init(&_scanner);
|
||||
Aqlset_extra(this, _scanner);
|
||||
|
||||
// parse the query string
|
||||
if (Aqlparse(this)) {
|
||||
// lexing/parsing failed
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_PARSE);
|
||||
try {
|
||||
// parse the query string
|
||||
if (Aqlparse(this)) {
|
||||
// lexing/parsing failed
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_PARSE);
|
||||
}
|
||||
|
||||
Aqllex_destroy(_scanner);
|
||||
}
|
||||
catch (...) {
|
||||
Aqllex_destroy(_scanner);
|
||||
throw;
|
||||
}
|
||||
|
||||
// end main scope
|
||||
scopes->endCurrent();
|
||||
|
||||
TRI_ASSERT(scopes->numActive() == 0);
|
||||
|
||||
ParseResult result;
|
||||
result.collectionNames = _ast->collectionNames();
|
||||
result.bindParameters = _ast->bindParameters();
|
||||
|
@ -136,17 +142,6 @@ ParseResult Parser::parse () {
|
|||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate a new unique name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* Parser::generateName () {
|
||||
std::string const variableName(std::to_string(++_uniqueId)); // c++11
|
||||
|
||||
// register the string and return a copy of it
|
||||
return _ast->registerString(variableName.c_str(), variableName.size(), false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief register a parse error, position is specified as line / column
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -117,6 +117,14 @@ namespace triagens {
|
|||
return _ast;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the query during parsing
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline Query* query () {
|
||||
return _query;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the scanner
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -198,12 +206,6 @@ namespace triagens {
|
|||
|
||||
ParseResult parse ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate a new unique name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* generateName ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief register a parse error, position is specified as line / column
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -265,19 +267,53 @@ namespace triagens {
|
|||
|
||||
private:
|
||||
|
||||
Query* _query; // the query object
|
||||
Ast* _ast; // abstract syntax tree
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* _scanner; // the lexer generated by flex
|
||||
char const* _buffer; // the currently processed part of the query string
|
||||
size_t _remainingLength; // remaining length of the query string, modified during parsing
|
||||
size_t _offset; // current parse position
|
||||
char const* _marker; // a position used temporarily during parsing
|
||||
Query* _query;
|
||||
|
||||
size_t _uniqueId; // a counter to generate unique (temporary) variable names
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief abstract syntax tree for the query, build during parsing
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ast* _ast;
|
||||
|
||||
std::vector<void*> _stack;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lexer / scanner used when parsing the query (Aql/tokens.ll)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* _scanner;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief currently processed part of the query string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char const* _buffer;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remaining length of the query string, used during parsing
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t _remainingLength;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief current offset into query string, used during parsing
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t _offset;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief pointer into query string, used temporarily during parsing
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char const* _marker;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief a stack of things, used temporarily during parsing
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<void*> _stack;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -31,11 +31,10 @@
|
|||
#include "Aql/Parser.h"
|
||||
#include "Aql/V8Executor.h"
|
||||
#include "BasicsC/json.h"
|
||||
#include "BasicsC/tri-strings.h"
|
||||
#include "Utils/Exception.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
#include "Basics/JsonHelper.h"
|
||||
|
||||
using namespace triagens::aql;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -55,9 +54,12 @@ Query::Query (TRI_vocbase_t* vocbase,
|
|||
_queryString(queryString),
|
||||
_queryLength(queryLength),
|
||||
_type(AQL_QUERY_READ),
|
||||
_bindParameters(bindParameters) {
|
||||
_bindParameters(bindParameters),
|
||||
_strings() {
|
||||
|
||||
TRI_ASSERT(_vocbase != nullptr);
|
||||
|
||||
_strings.reserve(32);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -69,6 +71,11 @@ Query::~Query () {
|
|||
delete _executor;
|
||||
_executor = nullptr;
|
||||
}
|
||||
|
||||
// free strings
|
||||
for (auto it = _strings.begin(); it != _strings.end(); ++it) {
|
||||
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, const_cast<char*>(*it));
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -206,6 +213,7 @@ void Query::explain () {
|
|||
|
||||
V8Executor* Query::getExecutor () {
|
||||
if (_executor == nullptr) {
|
||||
// the executor is a singleton per query
|
||||
_executor = new V8Executor;
|
||||
}
|
||||
|
||||
|
@ -213,6 +221,48 @@ V8Executor* Query::getExecutor () {
|
|||
return _executor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief register a string
|
||||
/// the string is freed when the query is destroyed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* Query::registerString (char const* p,
|
||||
size_t length,
|
||||
bool mustUnescape) {
|
||||
|
||||
if (p == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
static char const* empty = "";
|
||||
// optimisation for the empty string
|
||||
return const_cast<char*>(empty);
|
||||
}
|
||||
|
||||
char* copy = nullptr;
|
||||
if (mustUnescape) {
|
||||
size_t outLength;
|
||||
copy = TRI_UnescapeUtf8StringZ(TRI_UNKNOWN_MEM_ZONE, p, length, &outLength);
|
||||
}
|
||||
else {
|
||||
copy = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, p, length);
|
||||
}
|
||||
|
||||
if (copy == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
try {
|
||||
_strings.push_back(copy);
|
||||
}
|
||||
catch (...) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -165,6 +165,15 @@ namespace triagens {
|
|||
|
||||
V8Executor* getExecutor ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief register a string
|
||||
/// the string is freed when the query is destroyed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* registerString (char const*,
|
||||
size_t,
|
||||
bool);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -177,15 +186,47 @@ namespace triagens {
|
|||
|
||||
private:
|
||||
|
||||
struct TRI_vocbase_s* _vocbase;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief pointer to vocbase the query runs in
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_vocbase_s* _vocbase;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief V8 code executor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
V8Executor* _executor;
|
||||
V8Executor* _executor;
|
||||
|
||||
char const* _queryString;
|
||||
size_t const _queryLength;
|
||||
QueryType _type;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual query string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BindParameters _bindParameters;
|
||||
char const* _queryString;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief length of the query string in bytes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t const _queryLength;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief type of the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QueryType _type;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief bind parameters for the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BindParameters _bindParameters;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief all strings created in the AST - will be used for freeing them later
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<char const*> _strings;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -79,9 +79,8 @@ std::string Scope::typeName () const {
|
|||
/// @brief adds a variable to the scope
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Scope::addVariable (std::string const& name,
|
||||
Variable* variable) {
|
||||
_variables.insert(std::make_pair(name, variable));
|
||||
void Scope::addVariable (Variable* variable) {
|
||||
_variables.insert(std::make_pair(variable->name, variable));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -118,9 +117,7 @@ Variable* Scope::getVariable (char const* name) const {
|
|||
|
||||
Scopes::Scopes ()
|
||||
: _variables(),
|
||||
_activeScopes(),
|
||||
_nextId(0) {
|
||||
|
||||
_activeScopes() {
|
||||
_activeScopes.reserve(4);
|
||||
}
|
||||
|
||||
|
@ -203,7 +200,8 @@ void Scopes::endNested () {
|
|||
/// @brief adds a variable to the current scope
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Variable* Scopes::addVariable (char const* name,
|
||||
Variable* Scopes::addVariable (VariableId id,
|
||||
char const* name,
|
||||
bool isUserDefined) {
|
||||
TRI_ASSERT(! _activeScopes.empty());
|
||||
TRI_ASSERT(name != nullptr);
|
||||
|
@ -217,8 +215,6 @@ Variable* Scopes::addVariable (char const* name,
|
|||
}
|
||||
}
|
||||
|
||||
VariableId id = ++_nextId;
|
||||
|
||||
// if this fails, the exception will propagate and be caught somewhere else
|
||||
auto variable = new Variable(name, id, isUserDefined);
|
||||
|
||||
|
@ -233,7 +229,7 @@ Variable* Scopes::addVariable (char const* name,
|
|||
}
|
||||
|
||||
// if this fails, there won't be a memleak
|
||||
_activeScopes.back()->addVariable(std::string(name), variable);
|
||||
_activeScopes.back()->addVariable(variable);
|
||||
|
||||
return variable;
|
||||
}
|
||||
|
|
|
@ -95,8 +95,7 @@ namespace triagens {
|
|||
/// @brief adds a variable to the scope
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void addVariable (std::string const&,
|
||||
Variable*);
|
||||
void addVariable (Variable*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if a variable exists in the scope
|
||||
|
@ -163,6 +162,14 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief number of currently active scopes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline size_t numActive () const {
|
||||
return _activeScopes.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief start a new scope
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -185,7 +192,8 @@ namespace triagens {
|
|||
/// @brief adds a variable to the current scope
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Variable* addVariable (char const*,
|
||||
Variable* addVariable (VariableId,
|
||||
char const*,
|
||||
bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -222,19 +230,7 @@ namespace triagens {
|
|||
/// @brief currently active scopes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<Scope*> _activeScopes;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief all scopes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<Scope*> _allScopes;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief next variable id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableId _nextId;
|
||||
std::vector<Scope*> _activeScopes;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -230,39 +230,16 @@ for_statement:
|
|||
T_FOR variable_name T_IN expression {
|
||||
parser->ast()->scopes()->start(triagens::aql::AQL_SCOPE_FOR);
|
||||
|
||||
if ($4->type == NODE_TYPE_COLLECTION || $4->type == NODE_TYPE_REFERENCE) {
|
||||
// right operand of FOR is a collection or a reference. can use it directly
|
||||
auto node = parser->ast()->createNodeFor($2, $4);
|
||||
parser->ast()->addOperation(node);
|
||||
}
|
||||
else {
|
||||
char const* variableName = parser->generateName();
|
||||
// right operand of FOR is an expression. use a temporary variable
|
||||
auto letNode = parser->ast()->createNodeLet(variableName, $4, false);
|
||||
parser->ast()->addOperation(letNode);
|
||||
|
||||
auto forNode = parser->ast()->createNodeFor($2, variableName);
|
||||
parser->ast()->addOperation(forNode);
|
||||
}
|
||||
auto node = parser->ast()->createNodeFor($2, $4);
|
||||
parser->ast()->addOperation(node);
|
||||
}
|
||||
;
|
||||
|
||||
filter_statement:
|
||||
T_FILTER expression {
|
||||
if ($2->type == NODE_TYPE_REFERENCE) {
|
||||
// operand is a reference. can use it directly
|
||||
auto node = parser->ast()->createNodeFilter($2);
|
||||
parser->ast()->addOperation(node);
|
||||
}
|
||||
else {
|
||||
// operand is not a reference. use a temporary variable
|
||||
char const* variableName = parser->generateName();
|
||||
auto letNode = parser->ast()->createNodeLet(variableName, $2, false);
|
||||
parser->ast()->addOperation(letNode);
|
||||
|
||||
auto filterNode = parser->ast()->createNodeFilter(variableName);
|
||||
parser->ast()->addOperation(filterNode);
|
||||
}
|
||||
// operand is a reference. can use it directly
|
||||
auto node = parser->ast()->createNodeFilter($2);
|
||||
parser->ast()->addOperation(node);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -1284,7 +1284,7 @@ case 47:
|
|||
YY_RULE_SETUP
|
||||
{
|
||||
/* unquoted string */
|
||||
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
|
||||
yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
|
||||
return T_STRING;
|
||||
}
|
||||
YY_BREAK
|
||||
|
@ -1301,7 +1301,7 @@ YY_RULE_SETUP
|
|||
{
|
||||
/* end of backtick-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
yylval->strval = yyextra->query()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
return T_STRING;
|
||||
}
|
||||
YY_BREAK
|
||||
|
@ -1339,7 +1339,7 @@ YY_RULE_SETUP
|
|||
{
|
||||
/* end of quote-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
yylval->strval = yyextra->query()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
return T_QUOTED_STRING;
|
||||
}
|
||||
YY_BREAK
|
||||
|
@ -1377,7 +1377,7 @@ YY_RULE_SETUP
|
|||
{
|
||||
/* end of quote-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
yylval->strval = yyextra->query()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
return T_QUOTED_STRING;
|
||||
}
|
||||
YY_BREAK
|
||||
|
@ -1407,7 +1407,7 @@ case 63:
|
|||
YY_RULE_SETUP
|
||||
{
|
||||
/* a numeric integer value */
|
||||
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
|
||||
yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
|
||||
return T_INTEGER;
|
||||
}
|
||||
YY_BREAK
|
||||
|
@ -1415,7 +1415,7 @@ case 64:
|
|||
YY_RULE_SETUP
|
||||
{
|
||||
/* a numeric double value */
|
||||
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
|
||||
yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
|
||||
return T_DOUBLE;
|
||||
}
|
||||
YY_BREAK
|
||||
|
@ -1427,7 +1427,7 @@ YY_RULE_SETUP
|
|||
{
|
||||
/* bind parameters must start with a @
|
||||
if followed by another @, this is a collection name parameter */
|
||||
yylval->strval = yyextra->ast()->registerString(yytext + 1, yyleng - 1, false);
|
||||
yylval->strval = yyextra->query()->registerString(yytext + 1, yyleng - 1, false);
|
||||
return T_PARAMETER;
|
||||
}
|
||||
YY_BREAK
|
||||
|
|
|
@ -259,7 +259,7 @@ namespace triagens {
|
|||
|
||||
([a-zA-Z][_a-zA-Z0-9]*|_+[a-zA-Z]+[_a-zA-Z0-9]*) {
|
||||
/* unquoted string */
|
||||
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
|
||||
yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
|
||||
return T_STRING;
|
||||
}
|
||||
|
||||
|
@ -272,7 +272,7 @@ namespace triagens {
|
|||
<BACKTICK>` {
|
||||
/* end of backtick-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
yylval->strval = yyextra->query()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
return T_STRING;
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ namespace triagens {
|
|||
<DOUBLE_QUOTE>\" {
|
||||
/* end of quote-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
yylval->strval = yyextra->query()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
return T_QUOTED_STRING;
|
||||
}
|
||||
|
||||
|
@ -326,7 +326,7 @@ namespace triagens {
|
|||
<SINGLE_QUOTE>' {
|
||||
/* end of quote-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
yylval->strval = yyextra->query()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
|
||||
return T_QUOTED_STRING;
|
||||
}
|
||||
|
||||
|
@ -347,13 +347,13 @@ namespace triagens {
|
|||
|
||||
(0|[1-9][0-9]*) {
|
||||
/* a numeric integer value */
|
||||
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
|
||||
yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
|
||||
return T_INTEGER;
|
||||
}
|
||||
|
||||
(0|[1-9][0-9]*)(\.[0-9]+([eE]([\-\+])?[0-9]+)?) {
|
||||
/* a numeric double value */
|
||||
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
|
||||
yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
|
||||
return T_DOUBLE;
|
||||
}
|
||||
|
||||
|
@ -364,7 +364,7 @@ namespace triagens {
|
|||
@@?[a-zA-Z0-9][a-zA-Z0-9_]* {
|
||||
/* bind parameters must start with a @
|
||||
if followed by another @, this is a collection name parameter */
|
||||
yylval->strval = yyextra->ast()->registerString(yytext + 1, yyleng - 1, false);
|
||||
yylval->strval = yyextra->query()->registerString(yytext + 1, yyleng - 1, false);
|
||||
return T_PARAMETER;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue