1
0
Fork 0

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

This commit is contained in:
Max Neunhoeffer 2014-07-25 15:15:18 +02:00
commit 450a27a15d
8 changed files with 1416 additions and 591 deletions

291
arangod/Aql/AstNode.h Normal file
View File

@ -0,0 +1,291 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Aql, AST node
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_AQL_ASTNODE_H
#define ARANGODB_AQL_ASTNODE_H 1
#include "Basics/Common.h"
#include "BasicsC/vector.h"
#include "Utils/Exception.h"
namespace triagens {
namespace aql {
////////////////////////////////////////////////////////////////////////////////
/// @brief enumeration of AST node value types
////////////////////////////////////////////////////////////////////////////////
enum AstNodeValueType {
VALUE_TYPE_FAIL = 0,
VALUE_TYPE_NULL,
VALUE_TYPE_INT,
VALUE_TYPE_DOUBLE,
VALUE_TYPE_BOOL,
VALUE_TYPE_STRING
};
////////////////////////////////////////////////////////////////////////////////
/// @brief AST node value
////////////////////////////////////////////////////////////////////////////////
struct AstNodeValue {
union {
int64_t _int;
double _double;
bool _bool;
char const* _string;
} value;
AstNodeValueType type;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief enumeration of AST node types
////////////////////////////////////////////////////////////////////////////////
enum AstNodeType {
NODE_TYPE_ROOT,
NODE_TYPE_SCOPE_START,
NODE_TYPE_SCOPE_END,
NODE_TYPE_FOR,
NODE_TYPE_LET,
NODE_TYPE_FILTER,
NODE_TYPE_RETURN,
NODE_TYPE_REMOVE,
NODE_TYPE_INSERT,
NODE_TYPE_UPDATE,
NODE_TYPE_REPLACE,
NODE_TYPE_COLLECT,
NODE_TYPE_SORT,
NODE_TYPE_SORT_ELEMENT,
NODE_TYPE_LIMIT,
NODE_TYPE_VARIABLE,
NODE_TYPE_ASSIGN,
NODE_TYPE_OPERATOR_UNARY_PLUS,
NODE_TYPE_OPERATOR_UNARY_MINUS,
NODE_TYPE_OPERATOR_UNARY_NOT,
NODE_TYPE_OPERATOR_BINARY_AND,
NODE_TYPE_OPERATOR_BINARY_OR,
NODE_TYPE_OPERATOR_BINARY_PLUS,
NODE_TYPE_OPERATOR_BINARY_MINUS,
NODE_TYPE_OPERATOR_BINARY_TIMES,
NODE_TYPE_OPERATOR_BINARY_DIV,
NODE_TYPE_OPERATOR_BINARY_MOD,
NODE_TYPE_OPERATOR_BINARY_EQ,
NODE_TYPE_OPERATOR_BINARY_NE,
NODE_TYPE_OPERATOR_BINARY_LT,
NODE_TYPE_OPERATOR_BINARY_LE,
NODE_TYPE_OPERATOR_BINARY_GT,
NODE_TYPE_OPERATOR_BINARY_GE,
NODE_TYPE_OPERATOR_BINARY_IN,
NODE_TYPE_OPERATOR_TERNARY,
NODE_TYPE_SUBQUERY,
NODE_TYPE_ATTRIBUTE_ACCESS,
NODE_TYPE_BOUND_ATTRIBUTE_ACCESS,
NODE_TYPE_INDEXED_ACCESS,
NODE_TYPE_EXPAND,
NODE_TYPE_VALUE,
NODE_TYPE_LIST,
NODE_TYPE_ARRAY,
NODE_TYPE_ARRAY_ELEMENT,
NODE_TYPE_COLLECTION,
NODE_TYPE_REFERENCE,
NODE_TYPE_ATTRIBUTE,
NODE_TYPE_PARAMETER,
NODE_TYPE_FCALL,
NODE_TYPE_FCALL_USER
};
// -----------------------------------------------------------------------------
// --SECTION-- struct AstNode
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief the node
////////////////////////////////////////////////////////////////////////////////
struct AstNode {
// -----------------------------------------------------------------------------
// --SECTION-- constructors / destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief create a node
////////////////////////////////////////////////////////////////////////////////
AstNode (AstNodeType type)
: type(type) {
TRI_InitVectorPointer(&members, TRI_UNKNOWN_MEM_ZONE);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the node
////////////////////////////////////////////////////////////////////////////////
~AstNode () {
TRI_DestroyVectorPointer(&members);
}
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief add a member to the node
////////////////////////////////////////////////////////////////////////////////
void addMember (AstNode* node) {
TRI_ASSERT(node != nullptr);
int res = TRI_PushBackVectorPointer(&members, static_cast<void*>(node));
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a member to the node
////////////////////////////////////////////////////////////////////////////////
void addMember (AstNode const* node) {
addMember(const_cast<AstNode*>(node));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return a member of the node
////////////////////////////////////////////////////////////////////////////////
AstNode* getMember (size_t i) {
if (i >= members._length) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
}
return static_cast<AstNode*>(members._buffer[i]);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set the node's value type
////////////////////////////////////////////////////////////////////////////////
void setValueType (AstNodeValueType type) {
value.type = type;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the bool value of a node
////////////////////////////////////////////////////////////////////////////////
int64_t getBoolValue () const {
return value.value._bool;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set the bool value of a node
////////////////////////////////////////////////////////////////////////////////
void setBoolValue (bool v) {
value.value._bool = v;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the int value of a node
////////////////////////////////////////////////////////////////////////////////
int64_t getIntValue () const {
return value.value._int;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set the int value of a node
////////////////////////////////////////////////////////////////////////////////
void setIntValue (int64_t v) {
value.value._int = v;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the double value of a node
////////////////////////////////////////////////////////////////////////////////
double getDoubleValue () const {
return value.value._double;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set the string value of a node
////////////////////////////////////////////////////////////////////////////////
void setDoubleValue (double v) {
value.value._double = v;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the string value of a node
////////////////////////////////////////////////////////////////////////////////
char const* getStringValue () const {
return value.value._string;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set the string value of a node
////////////////////////////////////////////////////////////////////////////////
void setStringValue (char const* v) {
value.value._string = v;
}
// -----------------------------------------------------------------------------
// --SECTION-- public variables
// -----------------------------------------------------------------------------
public:
TRI_vector_pointer_t members;
AstNodeType const type;
AstNodeValue value;
};
}
}
#endif
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:

View File

@ -28,6 +28,7 @@
////////////////////////////////////////////////////////////////////////////////
#include "Aql/Parser.h"
#include "Aql/AstNode.h"
using namespace triagens::aql;
@ -46,6 +47,7 @@ Parser::Parser (Query* query)
_remainingLength(query->queryLength()),
_offset(0),
_marker(nullptr),
_subQueryCount(0),
_uniqueId(0),
_stack() {
@ -67,6 +69,41 @@ Parser::~Parser () {
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief set data for write queries
////////////////////////////////////////////////////////////////////////////////
bool Parser::configureWriteQuery (QueryType type,
AstNode const* collectionNode,
AstNode* optionNode) {
TRI_ASSERT(type != AQL_QUERY_READ);
// check if we currently are in a subquery
if (isInSubQuery()) {
// data modification not allowed in sub-queries
registerError(TRI_ERROR_QUERY_MODIFY_IN_SUBQUERY);
return false;
}
// check current query type
auto oldType = _query->type();
if (oldType != AQL_QUERY_READ) {
// already a data-modification query, cannot have two data-modification operations in one query
registerError(TRI_ERROR_QUERY_MULTI_MODIFY);
return false;
}
// now track which collection is going to be modified
ast()->setWriteCollection(collectionNode);
ast()->setWriteOptions(optionNode);
// register type
_query->type(type);
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief parse the query
////////////////////////////////////////////////////////////////////////////////
@ -94,7 +131,7 @@ char* Parser::generateName () {
int n = snprintf(buffer, sizeof(buffer) - 1, "_%d", (int) ++_uniqueId);
// register the string and return a copy of it
return registerString(buffer, static_cast<size_t>(n), false);
return ast()->registerString(buffer, static_cast<size_t>(n), false);
}
////////////////////////////////////////////////////////////////////////////////
@ -137,6 +174,28 @@ void Parser::registerError (int code,
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief push an AstNode into the list element on top of the stack
////////////////////////////////////////////////////////////////////////////////
void Parser::pushList (AstNode* node) {
auto list = static_cast<AstNode*>(peekStack());
TRI_ASSERT(list->type == NODE_TYPE_LIST);
list->addMember(node);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief push an AstNode into the array element on top of the stack
////////////////////////////////////////////////////////////////////////////////
void Parser::pushArray (char const* attributeName,
AstNode* node) {
auto array = static_cast<AstNode*>(peekStack());
TRI_ASSERT(array->type == NODE_TYPE_ARRAY);
auto element = ast()->createNodeArrayElement(attributeName, node);
array->addMember(element);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief push a temporary value on the parser's stack
////////////////////////////////////////////////////////////////////////////////

View File

@ -41,6 +41,7 @@
namespace triagens {
namespace aql {
struct AstNode;
class Query;
class Parser;
}
@ -116,6 +117,31 @@ namespace triagens {
return _query->ast();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief start a subquery
////////////////////////////////////////////////////////////////////////////////
inline void startSubQuery () {
++_subQueryCount;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief end a subquery
////////////////////////////////////////////////////////////////////////////////
inline void endSubQuery () {
TRI_ASSERT(_subQueryCount > 0);
--_subQueryCount;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not we are in a subquery
////////////////////////////////////////////////////////////////////////////////
inline bool isInSubQuery () const {
return (_subQueryCount > 0);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the scanner
////////////////////////////////////////////////////////////////////////////////
@ -184,23 +210,12 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
/// @brief set data for write queries
////////////////////////////////////////////////////////////////////////////////
char* registerString (char const* p,
size_t length,
bool mustEscape) {
// TODO
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set the query type
////////////////////////////////////////////////////////////////////////////////
void type (QueryType type) {
_query->type(type);
}
bool configureWriteQuery (QueryType,
AstNode const*,
AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief parse the query
@ -229,6 +244,19 @@ namespace triagens {
void registerError (int,
char const* = nullptr);
////////////////////////////////////////////////////////////////////////////////
/// @brief push an AstNode into the list element on top of the stack
////////////////////////////////////////////////////////////////////////////////
void pushList (AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief push an AstNode into the array element on top of the stack
////////////////////////////////////////////////////////////////////////////////
void pushArray (char const*,
AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief push a temporary value on the parser's stack
////////////////////////////////////////////////////////////////////////////////
@ -261,6 +289,7 @@ namespace triagens {
size_t _offset; // current parse position
char const* _marker; // a position used temporarily during parsing
size_t _subQueryCount; // number of active subqueries
size_t _uniqueId; // a counter to generate unique (temporary) variable names

View File

@ -28,7 +28,7 @@
////////////////////////////////////////////////////////////////////////////////
#include "Aql/QueryAst.h"
#include "Ahuacatl/ahuacatl-ast-node.h"
#include "BasicsC/tri-strings.h"
#include "Utils/Exception.h"
using namespace triagens::aql;
@ -42,19 +42,15 @@ using namespace triagens::aql;
////////////////////////////////////////////////////////////////////////////////
QueryAst::QueryAst ()
: _root(nullptr),
_scopes() {
: _nodes(),
_strings(),
_scopes(),
_root(nullptr),
_writeCollection(nullptr),
_writeOptions(nullptr) {
TRI_aql_node_t* root = new TRI_aql_node_t;
root->_type = TRI_AQL_NODE_ROOT;
int res = TRI_InitVectorPointer2(&root->_members, TRI_UNKNOWN_MEM_ZONE, 16);
if (res != TRI_ERROR_NO_ERROR) {
delete root;
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
_root = root;
_nodes.reserve(32);
_root = createNode(NODE_TYPE_ROOT);
}
////////////////////////////////////////////////////////////////////////////////
@ -62,6 +58,15 @@ QueryAst::QueryAst ()
////////////////////////////////////////////////////////////////////////////////
QueryAst::~QueryAst () {
// 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);
}
}
// -----------------------------------------------------------------------------
@ -72,10 +77,563 @@ QueryAst::~QueryAst () {
/// @brief destroy the AST
////////////////////////////////////////////////////////////////////////////////
void QueryAst::addOperation (TRI_aql_node_t* node) {
void QueryAst::addOperation (AstNode* node) {
TRI_ASSERT(_root != nullptr);
TRI_PushBackVectorPointer(&_root->_members, (void*) node);
TRI_PushBackVectorPointer(&_root->members, (void*) node);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
////////////////////////////////////////////////////////////////////////////////
char* QueryAst::registerString (char const* p,
size_t length,
bool mustUnescape) {
if (p == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
char* copy = nullptr;
if (mustUnescape && length > 0) {
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 scope start node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeScopeStart () {
// TODO: re-add hint??
return createNode(NODE_TYPE_SCOPE_START);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST scope end node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeScopeEnd () {
// TODO: re-add hint??
return createNode(NODE_TYPE_SCOPE_END);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST for node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeFor (char const* variableName,
AstNode const* expression) {
// TODO:
/*
if (! TRI_IsValidVariableNameAql(variableName)) {
// TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_QUERY_VARIABLE_NAME_INVALID, name);
}
*/
AstNode* node = createNode(NODE_TYPE_FOR);
AstNode* variable = createNodeVariable(variableName);
node->addMember(variable);
node->addMember(expression);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST let node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeLet (char const* variableName,
AstNode const* expression) {
// TODO:
/*
if (! TRI_IsValidVariableNameAql(variableName)) {
// TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_QUERY_VARIABLE_NAME_INVALID, name);
}
*/
AstNode* node = createNode(NODE_TYPE_LET);
AstNode* variable = createNodeVariable(variableName);
node->addMember(variable);
node->addMember(expression);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST filter node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeFilter (AstNode const* expression) {
AstNode* node = createNode(NODE_TYPE_FILTER);
node->addMember(expression);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST return node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeReturn (AstNode const* expression) {
AstNode* node = createNode(NODE_TYPE_RETURN);
node->addMember(expression);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST remove node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeRemove (AstNode const* expression,
AstNode const* collection,
AstNode* options) {
AstNode* node = createNode(NODE_TYPE_REMOVE);
node->addMember(expression);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST insert node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeInsert (AstNode const* expression,
AstNode const* collection,
AstNode* options) {
AstNode* node = createNode(NODE_TYPE_INSERT);
node->addMember(expression);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST update node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeUpdate (AstNode const* keyExpression,
AstNode const* docExpression,
AstNode const* collection,
AstNode* options) {
AstNode* node = createNode(NODE_TYPE_UPDATE);
node->addMember(docExpression);
if (keyExpression != nullptr) {
node->addMember(keyExpression);
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST replace node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeReplace (AstNode const* keyExpression,
AstNode const* docExpression,
AstNode const* collection,
AstNode* options) {
AstNode* node = createNode(NODE_TYPE_REPLACE);
node->addMember(docExpression);
if (keyExpression != nullptr) {
node->addMember(keyExpression);
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST collect node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeCollect (AstNode const* list,
char const* name) {
AstNode* node = createNode(NODE_TYPE_COLLECT);
node->addMember(list);
if (name != nullptr) {
AstNode* variable = createNodeVariable(name);
node->addMember(variable);
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST sort node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeSort (AstNode const* list) {
AstNode* node = createNode(NODE_TYPE_SORT);
node->addMember(list);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST sort element node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeSortElement (AstNode const* expression,
bool ascending) {
AstNode* node = createNode(NODE_TYPE_SORT_ELEMENT);
node->addMember(expression);
node->setBoolValue(ascending);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST limit node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeLimit (AstNode const* offset,
AstNode const* count) {
AstNode* node = createNode(NODE_TYPE_LIMIT);
node->addMember(offset);
node->addMember(count);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST assign node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeAssign (char const* name,
AstNode const* expression) {
// TODO: look up what an assign node is!!!!!!!!!
AstNode* node = createNode(NODE_TYPE_ASSIGN);
AstNode* variable = createNodeVariable(name);
node->addMember(variable);
node->addMember(expression);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST variable node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeVariable (char const* name) {
// TODO: check for duplicate names here!!
// TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_QUERY_VARIABLE_REDECLARED, name);
AstNode* node = createNode(NODE_TYPE_VARIABLE);
node->setStringValue(name);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST collection node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeCollection (char const* name) {
if (name == nullptr || *name == '\0') {
// TODO
// TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, name);
return nullptr;
}
/*
if (! TRI_IsAllowedNameCollection(true, name)) {
// TODO
// TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_ARANGO_ILLEGAL_NAME, name);
return nullptr;
}
*/
AstNode* node = createNode(NODE_TYPE_COLLECTION);
AstNode* nameNode = createNodeValueString(name);
// TODO: check if we can store the name inline
// TODO: add the collection to the query
node->addMember(nameNode);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST reference node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeReference (char const* name) {
AstNode* node = createNode(NODE_TYPE_REFERENCE);
node->setStringValue(name);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST parameter node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeParameter (char const* name) {
AstNode* node = createNode(NODE_TYPE_PARAMETER);
// TODO: insert bind parameter name into list of found parameters
// (so we can check which ones are missing)
node->setStringValue(name);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST unary operator node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeUnaryOperator (AstNodeType type,
AstNode const* operand) {
AstNode* node = createNode(type);
node->addMember(operand);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary operator node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeBinaryOperator (AstNodeType type,
AstNode const* lhs,
AstNode const* rhs) {
AstNode* node = createNode(type);
node->addMember(lhs);
node->addMember(rhs);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST ternary operator node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeTernaryOperator (AstNode const* condition,
AstNode const* truePart,
AstNode const* falsePart) {
AstNode* node = createNode(NODE_TYPE_OPERATOR_TERNARY);
node->addMember(condition);
node->addMember(truePart);
node->addMember(falsePart);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST subquery node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeSubquery () {
AstNode* node = createNode(NODE_TYPE_SUBQUERY);
// TODO: let the parser create a dynamic name here
AstNode* variable = createNodeVariable("tempName");
node->addMember(variable);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST attribute access node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeAttributeAccess (AstNode const* accessed,
char const* attributeName) {
AstNode* node = createNode(NODE_TYPE_ATTRIBUTE_ACCESS);
node->addMember(accessed);
node->setStringValue(attributeName);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST attribute access node w/ bind parameter
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeBoundAttributeAccess (AstNode const* accessed,
AstNode const* parameter) {
AstNode* node = createNode(NODE_TYPE_BOUND_ATTRIBUTE_ACCESS);
node->addMember(accessed);
node->addMember(parameter);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST indexed access node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeIndexedAccess (AstNode const* accessed,
AstNode const* indexValue) {
AstNode* node = createNode(NODE_TYPE_INDEXED_ACCESS);
node->addMember(accessed);
node->addMember(indexValue);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST expand node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeExpand (char const* variableName,
AstNode const* expanded,
AstNode const* expansion) {
AstNode* node = createNode(NODE_TYPE_EXPAND);
AstNode* variable = createNodeVariable(variableName);
// TODO: let the parser create a temporary variable name
AstNode* temp = createNodeVariable("temp");
node->addMember(variable);
node->addMember(temp);
node->addMember(expanded);
node->addMember(expansion);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST null value node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeValueNull () {
AstNode* node = createNode(NODE_TYPE_VALUE);
node->setValueType(VALUE_TYPE_NULL);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST bool value node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeValueBool (bool value) {
AstNode* node = createNode(NODE_TYPE_VALUE);
node->setValueType(VALUE_TYPE_BOOL);
node->setBoolValue(value);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST int value node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeValueInt (int64_t value) {
AstNode* node = createNode(NODE_TYPE_VALUE);
node->setValueType(VALUE_TYPE_INT);
node->setIntValue(value);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST double value node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeValueDouble (double value) {
AstNode* node = createNode(NODE_TYPE_VALUE);
node->setValueType(VALUE_TYPE_DOUBLE);
node->setDoubleValue(value);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST string value node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeValueString (char const* value) {
AstNode* node = createNode(NODE_TYPE_VALUE);
node->setValueType(VALUE_TYPE_STRING);
node->setStringValue(value);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST list node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeList () {
AstNode* node = createNode(NODE_TYPE_LIST);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST array node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeArray () {
AstNode* node = createNode(NODE_TYPE_ARRAY);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST array element node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeArrayElement (char const* attributeName,
AstNode const* expression) {
AstNode* node = createNode(NODE_TYPE_ARRAY_ELEMENT);
node->setStringValue(attributeName);
node->addMember(expression);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST function call node
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNodeFunctionCall (char const* functionName,
AstNode const* parameters) {
// TODO: support function calls!
TRI_ASSERT(false);
return nullptr;
}
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief create a node of the specified type
////////////////////////////////////////////////////////////////////////////////
AstNode* QueryAst::createNode (AstNodeType type) {
auto node = new AstNode(type);
try {
_nodes.push_back(node);
}
catch (...) {
delete node;
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
return node;
}
// -----------------------------------------------------------------------------

View File

@ -31,8 +31,8 @@
#define ARANGODB_AQL_QUERY_AST_H 1
#include "Basics/Common.h"
#include "Aql/AstNode.h"
#include "Aql/Scopes.h"
#include "Ahuacatl/ahuacatl-ast-node.h"
namespace triagens {
namespace aql {
@ -79,11 +79,293 @@ namespace triagens {
return &_scopes;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief track the write collection
////////////////////////////////////////////////////////////////////////////////
inline void setWriteCollection (AstNode const* node) {
TRI_ASSERT(node->type == NODE_TYPE_COLLECTION ||
node->type == NODE_TYPE_PARAMETER);
_writeCollection = node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief track the write query options
////////////////////////////////////////////////////////////////////////////////
inline void setWriteOptions (AstNode const* node) {
_writeOptions = node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add an operation to the root node
////////////////////////////////////////////////////////////////////////////////
void addOperation (TRI_aql_node_t*);
void addOperation (AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
////////////////////////////////////////////////////////////////////////////////
char* registerString (char const*,
size_t,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST scope start node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeScopeStart ();
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST scope end node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeScopeEnd ();
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST for node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeFor (char const*,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST let node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeLet (char const*,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST filter node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeFilter (AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST return node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeReturn (AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST remove node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeRemove (AstNode const*,
AstNode const*,
AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST insert node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeInsert (AstNode const*,
AstNode const*,
AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST update node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeUpdate (AstNode const*,
AstNode const*,
AstNode const*,
AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST replace node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeReplace (AstNode const*,
AstNode const*,
AstNode const*,
AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST collect node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeCollect (AstNode const*,
char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST sort node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeSort (AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST sort element node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeSortElement (AstNode const*,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST limit node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeLimit (AstNode const*,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST assign node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeAssign (char const*,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST variable node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeVariable (char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST collection node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeCollection (char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST reference node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeReference (char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST parameter node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeParameter (char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST unary operator
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeUnaryOperator (AstNodeType type,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary operator
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeBinaryOperator (AstNodeType type,
AstNode const*,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST ternary operator
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeTernaryOperator (AstNode const*,
AstNode const*,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST subquery node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeSubquery ();
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST attribute access node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeAttributeAccess (AstNode const*,
char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST attribute access node w/ bind parameter
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeBoundAttributeAccess (AstNode const*,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST index access node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeIndexedAccess (AstNode const*,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST expand node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeExpand (char const*,
AstNode const*,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST null value node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeValueNull ();
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST bool value node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeValueBool (bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST int value node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeValueInt (int64_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST double value node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeValueDouble (double);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST string value node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeValueString (char const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST list node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeList ();
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST array node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeArray ();
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST array element node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeArrayElement (char const*,
AstNode const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST function call node
////////////////////////////////////////////////////////////////////////////////
AstNode* createNodeFunctionCall (char const*,
AstNode const*);
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief create a node of the specified type
////////////////////////////////////////////////////////////////////////////////
AstNode* createNode (AstNodeType);
// -----------------------------------------------------------------------------
// --SECTION-- private variables
@ -92,16 +374,40 @@ namespace triagens {
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief root node of the AST
/// @brief all nodes created in the AST - will be used for freeing them later
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* _root;
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
////////////////////////////////////////////////////////////////////////////////
Scopes _scopes;
Scopes _scopes;
////////////////////////////////////////////////////////////////////////////////
/// @brief root node of the AST
////////////////////////////////////////////////////////////////////////////////
AstNode* _root;
////////////////////////////////////////////////////////////////////////////////
/// @brief which collection is going to be modified in the query
////////////////////////////////////////////////////////////////////////////////
AstNode const* _writeCollection;
////////////////////////////////////////////////////////////////////////////////
/// @brief which options are used for write queries
////////////////////////////////////////////////////////////////////////////////
AstNode const* _writeOptions;
};

File diff suppressed because it is too large Load Diff

View File

@ -625,6 +625,7 @@ namespace triagens {
}
}
#include "Aql/AstNode.h"
#include "Aql/grammar.h"
#include "Aql/Parser.h"
@ -1283,7 +1284,7 @@ case 47:
YY_RULE_SETUP
{
/* unquoted string */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_STRING;
}
YY_BREAK
@ -1300,7 +1301,7 @@ YY_RULE_SETUP
{
/* end of backtick-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_STRING;
}
YY_BREAK
@ -1338,7 +1339,7 @@ YY_RULE_SETUP
{
/* end of quote-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_QUOTED_STRING;
}
YY_BREAK
@ -1376,7 +1377,7 @@ YY_RULE_SETUP
{
/* end of quote-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_QUOTED_STRING;
}
YY_BREAK
@ -1406,7 +1407,7 @@ case 63:
YY_RULE_SETUP
{
/* a numeric integer value */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_INTEGER;
}
YY_BREAK
@ -1414,7 +1415,7 @@ case 64:
YY_RULE_SETUP
{
/* a numeric double value */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_DOUBLE;
}
YY_BREAK
@ -1426,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->registerString(yytext + 1, yyleng - 1, false);
yylval->strval = yyextra->ast()->registerString(yytext + 1, yyleng - 1, false);
return T_PARAMETER;
}
YY_BREAK

View File

@ -26,6 +26,7 @@ namespace triagens {
}
#include "Aql/AstNode.h"
#include "Aql/grammar.h"
#include "Aql/Parser.h"
@ -258,7 +259,7 @@ namespace triagens {
([a-zA-Z][_a-zA-Z0-9]*|_+[a-zA-Z]+[_a-zA-Z0-9]*) {
/* unquoted string */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_STRING;
}
@ -271,7 +272,7 @@ namespace triagens {
<BACKTICK>` {
/* end of backtick-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_STRING;
}
@ -298,7 +299,7 @@ namespace triagens {
<DOUBLE_QUOTE>\" {
/* end of quote-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_QUOTED_STRING;
}
@ -325,7 +326,7 @@ namespace triagens {
<SINGLE_QUOTE>' {
/* end of quote-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_QUOTED_STRING;
}
@ -346,13 +347,13 @@ namespace triagens {
(0|[1-9][0-9]*) {
/* a numeric integer value */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_INTEGER;
}
(0|[1-9][0-9]*)(\.[0-9]+([eE]([\-\+])?[0-9]+)?) {
/* a numeric double value */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_DOUBLE;
}
@ -363,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->registerString(yytext + 1, yyleng - 1, false);
yylval->strval = yyextra->ast()->registerString(yytext + 1, yyleng - 1, false);
return T_PARAMETER;
}