1
0
Fork 0

refactoring

This commit is contained in:
Jan Steemann 2014-07-31 10:38:49 +02:00
parent 6ebfbfef49
commit 2aad264e77
11 changed files with 248 additions and 240 deletions

View File

@ -58,8 +58,8 @@ Ast::Ast (Query* query,
Parser* parser) Parser* parser)
: _query(query), : _query(query),
_parser(parser), _parser(parser),
_variableId(0),
_nodes(), _nodes(),
_strings(),
_scopes(), _scopes(),
_bindParameters(), _bindParameters(),
_collectionNames(), _collectionNames(),
@ -72,7 +72,6 @@ Ast::Ast (Query* query,
TRI_ASSERT(_parser != nullptr); TRI_ASSERT(_parser != nullptr);
_nodes.reserve(32); _nodes.reserve(32);
_strings.reserve(32);
startSubQuery(); startSubQuery();
@ -84,11 +83,6 @@ Ast::Ast (Query* query,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Ast::~Ast () { 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 // free nodes
for (auto it = _nodes.begin(); it != _nodes.end(); ++it) { for (auto it = _nodes.begin(); it != _nodes.end(); ++it) {
delete (*it); delete (*it);
@ -99,8 +93,20 @@ Ast::~Ast () {
// --SECTION-- public functions // --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 /// @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) { TRI_json_t* Ast::toJson (TRI_memory_zone_t* zone) {
@ -127,47 +133,6 @@ void Ast::addOperation (AstNode* node) {
_root->addMember(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 /// @brief create an AST for node
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -187,27 +152,6 @@ AstNode* Ast::createNodeFor (char const* variableName,
return node; 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 /// @brief create an AST let node
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -241,24 +185,6 @@ AstNode* Ast::createNodeFilter (AstNode const* expression) {
return node; 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 /// @brief create an AST return node
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -427,7 +353,7 @@ AstNode* Ast::createNodeVariable (char const* name,
AstNode* node = createNode(NODE_TYPE_VARIABLE); AstNode* node = createNode(NODE_TYPE_VARIABLE);
node->setStringValue(name); node->setStringValue(name);
auto variable = _scopes.addVariable(name, isUserDefined); auto variable = _scopes.addVariable(nextVariableId(), name, isUserDefined);
node->setData(static_cast<void*>(variable)); node->setData(static_cast<void*>(variable));
return node; return node;
@ -742,7 +668,7 @@ AstNode* Ast::createNodeFunctionCall (char const* functionName,
} }
std::string const normalizedName = normalizeFunctionName(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; AstNode* node;
@ -824,7 +750,7 @@ void Ast::injectBindParameters (BindParameters& parameters) {
} }
// turn node into a collection node // 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); node = createNodeCollection(name);
@ -1300,6 +1226,7 @@ AstNode* Ast::optimizeTernaryOperator (AstNode* node) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief optimizes a reference to a variable /// @brief optimizes a reference to a variable
/// references are replaced with constants if possible
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
AstNode* Ast::optimizeReference (AstNode* node) { AstNode* Ast::optimizeReference (AstNode* node) {
@ -1312,6 +1239,7 @@ AstNode* Ast::optimizeReference (AstNode* node) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
} }
// constant propagation
if (variable->constValue() == nullptr) { if (variable->constValue() == nullptr) {
// note which variables we are reading // note which variables we are reading
variable->increaseReferenceCount(); variable->increaseReferenceCount();
@ -1319,8 +1247,6 @@ AstNode* Ast::optimizeReference (AstNode* node) {
return node; return node;
} }
// TODO: re-activate constant propagation??
return node;
return static_cast<AstNode*>(variable->constValue()); return static_cast<AstNode*>(variable->constValue());
} }
@ -1387,8 +1313,6 @@ AstNode* Ast::optimizeLet (AstNode* node,
} }
} }
else if (pass == 1) { else if (pass == 1) {
/* TODO: re-add reference counting
if (! v->isReferenceCounted()) { if (! v->isReferenceCounted()) {
// this optimizes away the assignment of variables which are never read // this optimizes away the assignment of variables which are never read
// (i.e. assigned-only variables). this is currently not free of side-effects: // (i.e. assigned-only variables). this is currently not free of side-effects:
@ -1403,7 +1327,6 @@ AstNode* Ast::optimizeLet (AstNode* node,
// variables // variables
return createNodeNop(); return createNodeNop();
} }
*/
} }
return node; return node;
@ -1452,7 +1375,7 @@ AstNode* Ast::nodeFromJson (TRI_json_t const* json) {
} }
if (json->_type == TRI_JSON_STRING) { 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); return createNodeValueString(value);
} }
@ -1479,7 +1402,7 @@ AstNode* Ast::nodeFromJson (TRI_json_t const* json) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); 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))); node->addMember(createNodeArrayElement(attributeName, nodeFromJson(value)));
} }

View File

@ -74,7 +74,7 @@ namespace triagens {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Ast (Query*, Ast (Query*,
Parser*); Parser*);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the AST /// @brief destroy the AST
@ -190,8 +190,23 @@ namespace triagens {
_writeOptions = node; _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 /// @brief convert the AST into JSON
/// the caller is responsible for freeing the JSON later
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
struct TRI_json_s* toJson (TRI_memory_zone_t*); struct TRI_json_s* toJson (TRI_memory_zone_t*);
@ -202,14 +217,6 @@ namespace triagens {
void addOperation (AstNode*); void addOperation (AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
////////////////////////////////////////////////////////////////////////////////
char* registerString (char const*,
size_t,
bool);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST for node /// @brief create an AST for node
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -217,13 +224,6 @@ namespace triagens {
AstNode* createNodeFor (char const*, AstNode* createNodeFor (char const*,
AstNode const*); AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST for node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeFor (char const*,
char const*);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST let node /// @brief create an AST let node
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -238,12 +238,6 @@ namespace triagens {
AstNode* createNodeFilter (AstNode const*); AstNode* createNodeFilter (AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST filter node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeFilter (char const*);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST return node /// @brief create an AST return node
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -614,7 +608,7 @@ namespace triagens {
/// @brief the query /// @brief the query
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Query* _query; Query* _query;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief the query parser /// @brief the query parser
@ -622,18 +616,18 @@ namespace triagens {
Parser* _parser; Parser* _parser;
////////////////////////////////////////////////////////////////////////////////
/// @brief the next assigned variable id
////////////////////////////////////////////////////////////////////////////////
VariableId _variableId;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief all nodes created in the AST - will be used for freeing them later /// @brief all nodes created in the AST - will be used for freeing them later
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::vector<AstNode*> _nodes; 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 /// @brief all scopes used in the query
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -29,7 +29,6 @@
#include "Aql/Parser.h" #include "Aql/Parser.h"
#include "Aql/AstNode.h" #include "Aql/AstNode.h"
#include "Basics/StringUtils.h"
using namespace triagens::aql; using namespace triagens::aql;
@ -49,12 +48,8 @@ Parser::Parser (Query* query)
_remainingLength(query->queryLength()), _remainingLength(query->queryLength()),
_offset(0), _offset(0),
_marker(nullptr), _marker(nullptr),
_uniqueId(0),
_stack() { _stack() {
Aqllex_init(&_scanner);
Aqlset_extra(this, _scanner);
_ast = new Ast(query, this); _ast = new Ast(query, this);
_stack.reserve(16); _stack.reserve(16);
@ -65,8 +60,6 @@ Parser::Parser (Query* query)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Parser::~Parser () { Parser::~Parser () {
Aqllex_destroy(_scanner);
if (_ast != nullptr) { if (_ast != nullptr) {
delete _ast; delete _ast;
} }
@ -118,16 +111,29 @@ ParseResult Parser::parse () {
// start main scope // start main scope
auto scopes = _ast->scopes(); auto scopes = _ast->scopes();
scopes->start(AQL_SCOPE_MAIN); scopes->start(AQL_SCOPE_MAIN);
Aqllex_init(&_scanner);
Aqlset_extra(this, _scanner);
// parse the query string try {
if (Aqlparse(this)) { // parse the query string
// lexing/parsing failed if (Aqlparse(this)) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_PARSE); // lexing/parsing failed
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_PARSE);
}
Aqllex_destroy(_scanner);
}
catch (...) {
Aqllex_destroy(_scanner);
throw;
} }
// end main scope // end main scope
scopes->endCurrent(); scopes->endCurrent();
TRI_ASSERT(scopes->numActive() == 0);
ParseResult result; ParseResult result;
result.collectionNames = _ast->collectionNames(); result.collectionNames = _ast->collectionNames();
result.bindParameters = _ast->bindParameters(); result.bindParameters = _ast->bindParameters();
@ -136,17 +142,6 @@ ParseResult Parser::parse () {
return result; 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 /// @brief register a parse error, position is specified as line / column
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -117,6 +117,14 @@ namespace triagens {
return _ast; return _ast;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief return the query during parsing
////////////////////////////////////////////////////////////////////////////////
inline Query* query () {
return _query;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief return the scanner /// @brief return the scanner
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -198,12 +206,6 @@ namespace triagens {
ParseResult parse (); ParseResult parse ();
////////////////////////////////////////////////////////////////////////////////
/// @brief generate a new unique name
////////////////////////////////////////////////////////////////////////////////
char* generateName ();
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief register a parse error, position is specified as line / column /// @brief register a parse error, position is specified as line / column
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -265,19 +267,53 @@ namespace triagens {
private: private:
Query* _query; // the query object ////////////////////////////////////////////////////////////////////////////////
Ast* _ast; // abstract syntax tree /// @brief the query
////////////////////////////////////////////////////////////////////////////////
void* _scanner; // the lexer generated by flex Query* _query;
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
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;
}; };
} }

View File

@ -31,11 +31,10 @@
#include "Aql/Parser.h" #include "Aql/Parser.h"
#include "Aql/V8Executor.h" #include "Aql/V8Executor.h"
#include "BasicsC/json.h" #include "BasicsC/json.h"
#include "BasicsC/tri-strings.h"
#include "Utils/Exception.h" #include "Utils/Exception.h"
#include "VocBase/vocbase.h" #include "VocBase/vocbase.h"
#include "Basics/JsonHelper.h"
using namespace triagens::aql; using namespace triagens::aql;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -55,9 +54,12 @@ Query::Query (TRI_vocbase_t* vocbase,
_queryString(queryString), _queryString(queryString),
_queryLength(queryLength), _queryLength(queryLength),
_type(AQL_QUERY_READ), _type(AQL_QUERY_READ),
_bindParameters(bindParameters) { _bindParameters(bindParameters),
_strings() {
TRI_ASSERT(_vocbase != nullptr); TRI_ASSERT(_vocbase != nullptr);
_strings.reserve(32);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -69,6 +71,11 @@ Query::~Query () {
delete _executor; delete _executor;
_executor = nullptr; _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 () { V8Executor* Query::getExecutor () {
if (_executor == nullptr) { if (_executor == nullptr) {
// the executor is a singleton per query
_executor = new V8Executor; _executor = new V8Executor;
} }
@ -213,6 +221,48 @@ V8Executor* Query::getExecutor () {
return _executor; 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 // --SECTION-- END-OF-FILE
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -165,6 +165,15 @@ namespace triagens {
V8Executor* getExecutor (); 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 // --SECTION-- private methods
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -177,15 +186,47 @@ namespace triagens {
private: 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; /// @brief the actual query string
QueryType _type; ////////////////////////////////////////////////////////////////////////////////
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;
}; };

View File

@ -79,9 +79,8 @@ std::string Scope::typeName () const {
/// @brief adds a variable to the scope /// @brief adds a variable to the scope
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void Scope::addVariable (std::string const& name, void Scope::addVariable (Variable* variable) {
Variable* variable) { _variables.insert(std::make_pair(variable->name, variable));
_variables.insert(std::make_pair(name, variable));
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -118,9 +117,7 @@ Variable* Scope::getVariable (char const* name) const {
Scopes::Scopes () Scopes::Scopes ()
: _variables(), : _variables(),
_activeScopes(), _activeScopes() {
_nextId(0) {
_activeScopes.reserve(4); _activeScopes.reserve(4);
} }
@ -203,7 +200,8 @@ void Scopes::endNested () {
/// @brief adds a variable to the current scope /// @brief adds a variable to the current scope
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Variable* Scopes::addVariable (char const* name, Variable* Scopes::addVariable (VariableId id,
char const* name,
bool isUserDefined) { bool isUserDefined) {
TRI_ASSERT(! _activeScopes.empty()); TRI_ASSERT(! _activeScopes.empty());
TRI_ASSERT(name != nullptr); 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 // if this fails, the exception will propagate and be caught somewhere else
auto variable = new Variable(name, id, isUserDefined); 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 // if this fails, there won't be a memleak
_activeScopes.back()->addVariable(std::string(name), variable); _activeScopes.back()->addVariable(variable);
return variable; return variable;
} }

View File

@ -95,8 +95,7 @@ namespace triagens {
/// @brief adds a variable to the scope /// @brief adds a variable to the scope
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void addVariable (std::string const&, void addVariable (Variable*);
Variable*);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a variable exists in the scope /// @brief checks if a variable exists in the scope
@ -163,6 +162,14 @@ namespace triagens {
public: public:
////////////////////////////////////////////////////////////////////////////////
/// @brief number of currently active scopes
////////////////////////////////////////////////////////////////////////////////
inline size_t numActive () const {
return _activeScopes.size();
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief start a new scope /// @brief start a new scope
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -185,7 +192,8 @@ namespace triagens {
/// @brief adds a variable to the current scope /// @brief adds a variable to the current scope
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Variable* addVariable (char const*, Variable* addVariable (VariableId,
char const*,
bool); bool);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -222,19 +230,7 @@ namespace triagens {
/// @brief currently active scopes /// @brief currently active scopes
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::vector<Scope*> _activeScopes; std::vector<Scope*> _activeScopes;
////////////////////////////////////////////////////////////////////////////////
/// @brief all scopes
////////////////////////////////////////////////////////////////////////////////
std::vector<Scope*> _allScopes;
////////////////////////////////////////////////////////////////////////////////
/// @brief next variable id
////////////////////////////////////////////////////////////////////////////////
VariableId _nextId;
}; };

View File

@ -230,39 +230,16 @@ for_statement:
T_FOR variable_name T_IN expression { T_FOR variable_name T_IN expression {
parser->ast()->scopes()->start(triagens::aql::AQL_SCOPE_FOR); parser->ast()->scopes()->start(triagens::aql::AQL_SCOPE_FOR);
if ($4->type == NODE_TYPE_COLLECTION || $4->type == NODE_TYPE_REFERENCE) { auto node = parser->ast()->createNodeFor($2, $4);
// right operand of FOR is a collection or a reference. can use it directly parser->ast()->addOperation(node);
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);
}
} }
; ;
filter_statement: filter_statement:
T_FILTER expression { T_FILTER expression {
if ($2->type == NODE_TYPE_REFERENCE) { // operand is a reference. can use it directly
// operand is a reference. can use it directly auto node = parser->ast()->createNodeFilter($2);
auto node = parser->ast()->createNodeFilter($2); parser->ast()->addOperation(node);
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);
}
} }
; ;

View File

@ -1284,7 +1284,7 @@ case 47:
YY_RULE_SETUP YY_RULE_SETUP
{ {
/* unquoted string */ /* unquoted string */
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false); yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
return T_STRING; return T_STRING;
} }
YY_BREAK YY_BREAK
@ -1301,7 +1301,7 @@ YY_RULE_SETUP
{ {
/* end of backtick-enclosed string */ /* end of backtick-enclosed string */
BEGIN(INITIAL); 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; return T_STRING;
} }
YY_BREAK YY_BREAK
@ -1339,7 +1339,7 @@ YY_RULE_SETUP
{ {
/* end of quote-enclosed string */ /* end of quote-enclosed string */
BEGIN(INITIAL); 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; return T_QUOTED_STRING;
} }
YY_BREAK YY_BREAK
@ -1377,7 +1377,7 @@ YY_RULE_SETUP
{ {
/* end of quote-enclosed string */ /* end of quote-enclosed string */
BEGIN(INITIAL); 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; return T_QUOTED_STRING;
} }
YY_BREAK YY_BREAK
@ -1407,7 +1407,7 @@ case 63:
YY_RULE_SETUP YY_RULE_SETUP
{ {
/* a numeric integer value */ /* a numeric integer value */
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false); yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
return T_INTEGER; return T_INTEGER;
} }
YY_BREAK YY_BREAK
@ -1415,7 +1415,7 @@ case 64:
YY_RULE_SETUP YY_RULE_SETUP
{ {
/* a numeric double value */ /* a numeric double value */
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false); yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
return T_DOUBLE; return T_DOUBLE;
} }
YY_BREAK YY_BREAK
@ -1427,7 +1427,7 @@ YY_RULE_SETUP
{ {
/* bind parameters must start with a @ /* bind parameters must start with a @
if followed by another @, this is a collection name parameter */ 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; return T_PARAMETER;
} }
YY_BREAK YY_BREAK

View File

@ -259,7 +259,7 @@ namespace triagens {
([a-zA-Z][_a-zA-Z0-9]*|_+[a-zA-Z]+[_a-zA-Z0-9]*) { ([a-zA-Z][_a-zA-Z0-9]*|_+[a-zA-Z]+[_a-zA-Z0-9]*) {
/* unquoted string */ /* unquoted string */
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false); yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
return T_STRING; return T_STRING;
} }
@ -272,7 +272,7 @@ namespace triagens {
<BACKTICK>` { <BACKTICK>` {
/* end of backtick-enclosed string */ /* end of backtick-enclosed string */
BEGIN(INITIAL); 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; return T_STRING;
} }
@ -299,7 +299,7 @@ namespace triagens {
<DOUBLE_QUOTE>\" { <DOUBLE_QUOTE>\" {
/* end of quote-enclosed string */ /* end of quote-enclosed string */
BEGIN(INITIAL); 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; return T_QUOTED_STRING;
} }
@ -326,7 +326,7 @@ namespace triagens {
<SINGLE_QUOTE>' { <SINGLE_QUOTE>' {
/* end of quote-enclosed string */ /* end of quote-enclosed string */
BEGIN(INITIAL); 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; return T_QUOTED_STRING;
} }
@ -347,13 +347,13 @@ namespace triagens {
(0|[1-9][0-9]*) { (0|[1-9][0-9]*) {
/* a numeric integer value */ /* a numeric integer value */
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false); yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
return T_INTEGER; return T_INTEGER;
} }
(0|[1-9][0-9]*)(\.[0-9]+([eE]([\-\+])?[0-9]+)?) { (0|[1-9][0-9]*)(\.[0-9]+([eE]([\-\+])?[0-9]+)?) {
/* a numeric double value */ /* a numeric double value */
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false); yylval->strval = yyextra->query()->registerString(yytext, yyleng, false);
return T_DOUBLE; return T_DOUBLE;
} }
@ -364,7 +364,7 @@ namespace triagens {
@@?[a-zA-Z0-9][a-zA-Z0-9_]* { @@?[a-zA-Z0-9][a-zA-Z0-9_]* {
/* bind parameters must start with a @ /* bind parameters must start with a @
if followed by another @, this is a collection name parameter */ 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; return T_PARAMETER;
} }