1
0
Fork 0
arangodb/arangod/Ahuacatl/ahuacatl-ast-node.cpp

1323 lines
44 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// @brief Ahuacatl, parser nodes
///
/// @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
////////////////////////////////////////////////////////////////////////////////
#include "Ahuacatl/ahuacatl-ast-node.h"
#include "Ahuacatl/ahuacatl-collections.h"
#include "Ahuacatl/ahuacatl-functions.h"
#include "Ahuacatl/ahuacatl-parser-functions.h"
#include "Ahuacatl/ahuacatl-scope.h"
#include "Ahuacatl/ahuacatl-variable.h"
#include "VocBase/collection.h"
// -----------------------------------------------------------------------------
// --SECTION-- private macros
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief shortcut macro to create a new node or fail in case of OOM
////////////////////////////////////////////////////////////////////////////////
inline TRI_aql_node_t* CREATE_NODE_FUNC(TRI_aql_node_type_e type,
TRI_aql_context_t* context) {
TRI_aql_node_t* node;
try {
node = new TRI_aql_node_t();
}
catch (std::exception&) {
node = nullptr;
}
if (node == nullptr) {
TRI_SetErrorContextAql(
__FILE__,
__LINE__,
context,
TRI_ERROR_OUT_OF_MEMORY,
nullptr);
return nullptr;
}
node->_type = type;
TRI_InitVectorPointer(&node->_members, TRI_UNKNOWN_MEM_ZONE);
TRI_RegisterNodeContextAql(context, node);
return node;
}
#define CREATE_NODE(type) TRI_aql_node_t* node = CREATE_NODE_FUNC(type, context);
////////////////////////////////////////////////////////////////////////////////
/// @brief add a sub node to a node
////////////////////////////////////////////////////////////////////////////////
#define ADD_MEMBER(member) \
if (member == NULL) { \
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL); \
return NULL; \
} \
\
if (TRI_ERROR_NO_ERROR != TRI_PushBackVectorPointer(&node->_members, (void*) member)) { \
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL); \
return NULL; \
}
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a write opertion for a query
////////////////////////////////////////////////////////////////////////////////
static void SetWriteOperation (TRI_aql_context_t* context,
TRI_aql_node_t const* collection,
TRI_aql_query_type_e type,
TRI_aql_node_t* options) {
if (context->_writeCollection != nullptr ||
context->_type != TRI_AQL_QUERY_READ) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_QUERY_MULTI_MODIFY, nullptr);
return;
}
if (context->_subQueries > 0) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_QUERY_MODIFY_IN_SUBQUERY, nullptr);
return;
}
if (collection->_type == TRI_AQL_NODE_COLLECTION) {
// collection specified by name
TRI_aql_node_t* nameNode = TRI_AQL_NODE_MEMBER(collection, 0);
if (nameNode == nullptr) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, nullptr);
return;
}
context->_writeCollection = TRI_AQL_NODE_STRING(nameNode);
}
else if (collection->_type == TRI_AQL_NODE_PARAMETER) {
// collection specified via bind parameter
context->_writeCollection = TRI_AQL_NODE_STRING(collection);
}
else {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_INTERNAL, nullptr);
TRI_ASSERT(false);
return;
}
if (options != nullptr) {
if (! TRI_IsConstantValueNodeAql(options)) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_QUERY_COMPILE_TIME_OPTIONS, nullptr);
return;
}
}
context->_type = type;
context->_writeOptions = options;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST function call node
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* CreateNodeInternalFcall (TRI_aql_context_t* const context,
const char* const name,
const char* const internalName,
const TRI_aql_node_t* const parameters) {
CREATE_NODE(TRI_AQL_NODE_FCALL)
TRI_AQL_NODE_DATA(node) = 0;
{
TRI_aql_function_t* function;
TRI_associative_pointer_t* functions;
TRI_ASSERT(context->_vocbase);
functions = context->_vocbase->_functions;
TRI_ASSERT(functions);
function = TRI_GetByExternalNameFunctionAql(functions, internalName);
if (function == NULL) {
// function name is unknown
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_QUERY_FUNCTION_NAME_UNKNOWN, name);
return NULL;
}
// validate function call arguments
if (! TRI_ValidateArgsFunctionAql(context, function, parameters)) {
return NULL;
}
// initialise
ADD_MEMBER(parameters)
TRI_AQL_NODE_DATA(node) = function;
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST function call node
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* CreateNodeUserFcall (TRI_aql_context_t* const context,
const char* const name,
char* const internalName,
const TRI_aql_node_t* const parameters) {
CREATE_NODE(TRI_AQL_NODE_FCALL_USER)
{
char* copy = TRI_RegisterStringAql(context, internalName, strlen(internalName), false);
if (copy == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
TRI_AQL_NODE_STRING(node) = copy;
ADD_MEMBER(parameters)
}
return node;
}
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST nop node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeNopAql (void) {
TRI_aql_node_t* node;
try {
node = new TRI_aql_node_t;
}
catch (std::exception&) {
return nullptr;
}
node->_type = TRI_AQL_NODE_NOP;
TRI_InitVectorPointer(&node->_members, TRI_UNKNOWN_MEM_ZONE);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST return empty node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeReturnEmptyAql (void) {
TRI_aql_node_t* node;
TRI_aql_node_t* list;
int res;
try {
node = new TRI_aql_node_t();
}
catch (std::exception&) {
node = nullptr;
}
if (node == nullptr) {
return nullptr;
}
node->_type = TRI_AQL_NODE_RETURN_EMPTY;
try {
list = new TRI_aql_node_t();
}
catch (std::exception&) {
list = nullptr;
}
if (list == nullptr) {
delete node;
return nullptr;
}
list->_type = TRI_AQL_NODE_LIST;
TRI_InitVectorPointer(&list->_members, TRI_UNKNOWN_MEM_ZONE);
res = TRI_InitVectorPointer2(&node->_members, TRI_UNKNOWN_MEM_ZONE, 1);
if (res != TRI_ERROR_NO_ERROR) {
TRI_DestroyVectorPointer(&list->_members);
delete list;
delete node;
return NULL;
}
res = TRI_PushBackVectorPointer(&node->_members, (void*) list);
if (res != TRI_ERROR_NO_ERROR) {
TRI_DestroyVectorPointer(&node->_members);
TRI_DestroyVectorPointer(&list->_members);
delete list;
delete node;
return NULL;
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST scope start node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeScopeStartAql (TRI_aql_context_t* const context,
void* data) {
CREATE_NODE(TRI_AQL_NODE_SCOPE_START)
node->_value._value._data = data;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST scope end node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeScopeEndAql (TRI_aql_context_t* const context,
void* data) {
CREATE_NODE(TRI_AQL_NODE_SCOPE_END)
node->_value._value._data = data;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST for node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeForAql (TRI_aql_context_t* const context,
const char* const name,
const TRI_aql_node_t* const expression) {
CREATE_NODE(TRI_AQL_NODE_FOR)
// initialise
TRI_AQL_NODE_DATA(node) = NULL;
if (name == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
if (! TRI_IsValidVariableNameAql(name)) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_QUERY_VARIABLE_NAME_INVALID, name);
return NULL;
}
{
TRI_aql_node_t* variable = TRI_CreateNodeVariableAql(context, name, node, false);
ADD_MEMBER(variable)
ADD_MEMBER(expression)
}
{
TRI_aql_for_hint_t* hint;
// init for hint
hint = TRI_CreateForHintScopeAql(context);
// attach the hint to the loop
TRI_AQL_NODE_DATA(node) = hint;
if (hint == NULL) {
return NULL;
}
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST let node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeLetAql (TRI_aql_context_t* const context,
const char* const name,
const TRI_aql_node_t* const expression) {
CREATE_NODE(TRI_AQL_NODE_LET)
if (name == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
if (! TRI_IsValidVariableNameAql(name)) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_QUERY_VARIABLE_NAME_INVALID, name);
return NULL;
}
{
TRI_aql_node_t* variable = TRI_CreateNodeVariableAql(context, name, node, true);
ADD_MEMBER(variable)
ADD_MEMBER(expression)
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST filter node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeFilterAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const expression) {
CREATE_NODE(TRI_AQL_NODE_FILTER)
ADD_MEMBER(expression)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST return node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeReturnAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const expression) {
CREATE_NODE(TRI_AQL_NODE_RETURN)
ADD_MEMBER(expression)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST remove node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeRemoveAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const expression,
const TRI_aql_node_t* const collection,
TRI_aql_node_t* options) {
CREATE_NODE(TRI_AQL_NODE_REMOVE)
ADD_MEMBER(expression)
SetWriteOperation(context, collection, TRI_AQL_QUERY_REMOVE, options);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST save node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeInsertAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const expression,
const TRI_aql_node_t* const collection,
TRI_aql_node_t* options) {
CREATE_NODE(TRI_AQL_NODE_INSERT)
ADD_MEMBER(expression)
SetWriteOperation(context, collection, TRI_AQL_QUERY_INSERT, options);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST update node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeUpdateAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const keyExpression,
const TRI_aql_node_t* const docExpression,
const TRI_aql_node_t* const collection,
TRI_aql_node_t* options) {
CREATE_NODE(TRI_AQL_NODE_UPDATE)
ADD_MEMBER(docExpression)
if (keyExpression != nullptr) {
// key explicitly specified
ADD_MEMBER(keyExpression)
}
SetWriteOperation(context, collection, TRI_AQL_QUERY_UPDATE, options);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST replace node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeReplaceAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const keyExpression,
const TRI_aql_node_t* const docExpression,
const TRI_aql_node_t* const collection,
TRI_aql_node_t* options) {
CREATE_NODE(TRI_AQL_NODE_REPLACE)
ADD_MEMBER(docExpression)
if (keyExpression != nullptr) {
// key explicitly specified
ADD_MEMBER(keyExpression)
}
SetWriteOperation(context, collection, TRI_AQL_QUERY_REPLACE, options);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST collect node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeCollectAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const list,
const char* const name) {
CREATE_NODE(TRI_AQL_NODE_COLLECT)
ADD_MEMBER(list)
if (name != NULL) {
TRI_aql_node_t* variable = TRI_CreateNodeVariableAql(context, name, node, false);
ADD_MEMBER(variable)
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST sort node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeSortAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const list) {
CREATE_NODE(TRI_AQL_NODE_SORT)
ADD_MEMBER(list)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST sort element node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeSortElementAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const expression,
const bool ascending) {
CREATE_NODE(TRI_AQL_NODE_SORT_ELEMENT)
ADD_MEMBER(expression)
TRI_AQL_NODE_BOOL(node) = ascending;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST limit node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeLimitAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const offset,
const TRI_aql_node_t* const count) {
CREATE_NODE(TRI_AQL_NODE_LIMIT)
ADD_MEMBER(offset)
ADD_MEMBER(count)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST assign node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeAssignAql (TRI_aql_context_t* const context,
const char* const name,
const TRI_aql_node_t* const expression) {
CREATE_NODE(TRI_AQL_NODE_ASSIGN)
{
TRI_aql_node_t* variable = TRI_CreateNodeVariableAql(context, name, node, false);
ADD_MEMBER(variable)
ADD_MEMBER(expression)
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST variable node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeVariableAql (TRI_aql_context_t* const context,
const char* const name,
TRI_aql_node_t* const definingNode,
bool allowDuplicateName) {
CREATE_NODE(TRI_AQL_NODE_VARIABLE)
if (name == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
// if not a temporary variable
if (*name != '_') {
if (! TRI_AddVariableScopeAql(context, name, definingNode, allowDuplicateName)) {
// duplicate variable name
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_QUERY_VARIABLE_REDECLARED, name);
return NULL;
}
}
TRI_AQL_NODE_STRING(node) = (char*) name;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST collection node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeCollectionAql (TRI_aql_context_t* const context,
const char* const name) {
CREATE_NODE(TRI_AQL_NODE_COLLECTION)
node->_value._value._data = NULL;
if (name == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
if (strlen(name) == 0) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, name);
return NULL;
}
else {
if (! TRI_IsAllowedNameCollection(true, name)) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_ARANGO_ILLEGAL_NAME, name);
return NULL;
}
}
{
TRI_aql_collection_hint_t* hint;
TRI_aql_node_t* nameNode;
// init collection hint
hint = TRI_CreateCollectionHintAql();
// attach the hint to the collection
node->_value._value._data = hint;
if (hint == NULL) {
return NULL;
}
nameNode = TRI_CreateNodeValueStringAql(context, name);
ADD_MEMBER(nameNode)
}
if (! TRI_AddCollectionAql(context, name)) {
return NULL;
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST reference node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeReferenceAql (TRI_aql_context_t* const context,
const char* const name) {
CREATE_NODE(TRI_AQL_NODE_REFERENCE)
if (name == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
TRI_AQL_NODE_STRING(node) = (char*) name;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST parameter node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeParameterAql (TRI_aql_context_t* const context,
const char* const name) {
CREATE_NODE(TRI_AQL_NODE_PARAMETER)
if (name == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
// save name of bind parameter for later
TRI_InsertKeyAssociativePointer(&context->_parameters._names, name, (void*) name, true);
TRI_AQL_NODE_STRING(node) = (char*) name;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST unary plus node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorUnaryPlusAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const operand) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_UNARY_PLUS)
ADD_MEMBER(operand)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST unary minus node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorUnaryMinusAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const operand) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_UNARY_MINUS)
ADD_MEMBER(operand)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST unary not node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorUnaryNotAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const operand) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_UNARY_NOT)
ADD_MEMBER(operand)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary and node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryAndAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_AND)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary or node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryOrAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_OR)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary eq node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryEqAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_EQ)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary ne node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryNeAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_NE)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary lt node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryLtAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_LT)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary le node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryLeAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_LE)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary gt node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryGtAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_GT)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary ge node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryGeAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_GE)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary in node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryInAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_IN)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary plus node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryPlusAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_PLUS)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary minus node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryMinusAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_MINUS)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary times node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryTimesAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_TIMES)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary div node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryDivAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_DIV)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST binary mod node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryModAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const lhs,
const TRI_aql_node_t* const rhs) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_BINARY_MOD)
ADD_MEMBER(lhs)
ADD_MEMBER(rhs)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST ternary operator node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeOperatorTernaryAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const condition,
const TRI_aql_node_t* const truePart,
const TRI_aql_node_t* const falsePart) {
CREATE_NODE(TRI_AQL_NODE_OPERATOR_TERNARY)
ADD_MEMBER(condition)
ADD_MEMBER(truePart)
ADD_MEMBER(falsePart)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST subquery node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeSubqueryAql (TRI_aql_context_t* const context) {
CREATE_NODE(TRI_AQL_NODE_SUBQUERY)
{
// add the temporary variable
TRI_aql_node_t* variable = TRI_CreateNodeVariableAql(context, TRI_GetNameParseAql(context), node, false);
ADD_MEMBER(variable)
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST attribute access node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeAttributeAccessAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const accessed,
const char* const name) {
CREATE_NODE(TRI_AQL_NODE_ATTRIBUTE_ACCESS)
if (name == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
ADD_MEMBER(accessed)
TRI_AQL_NODE_STRING(node) = (char*) name;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST attribute access node w/ bind parameter
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeBoundAttributeAccessAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const accessed,
const TRI_aql_node_t* const parameter) {
CREATE_NODE(TRI_AQL_NODE_BOUND_ATTRIBUTE_ACCESS)
ADD_MEMBER(accessed)
ADD_MEMBER(parameter)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST index access node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeIndexedAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const accessed,
const TRI_aql_node_t* const indexValue) {
CREATE_NODE(TRI_AQL_NODE_INDEXED)
ADD_MEMBER(accessed)
ADD_MEMBER(indexValue)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST expand node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeExpandAql (TRI_aql_context_t* const context,
const char* const varname,
const TRI_aql_node_t* const expanded,
const TRI_aql_node_t* const expansion) {
CREATE_NODE(TRI_AQL_NODE_EXPAND)
if (varname == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
{
// TODO: check if 3rd parameters' values are correct for these
TRI_aql_node_t* variable1 = TRI_CreateNodeVariableAql(context, varname, node, false);
TRI_aql_node_t* variable2 = TRI_CreateNodeVariableAql(context, TRI_GetNameParseAql(context), node, false);
ADD_MEMBER(variable1)
ADD_MEMBER(variable2)
ADD_MEMBER(expanded)
ADD_MEMBER(expansion)
}
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST null value node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeValueNullAql (TRI_aql_context_t* const context) {
CREATE_NODE(TRI_AQL_NODE_VALUE)
TRI_AQL_NODE_TYPE(node) = TRI_AQL_TYPE_NULL;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST int value node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeValueIntAql (TRI_aql_context_t* const context,
const int64_t value) {
CREATE_NODE(TRI_AQL_NODE_VALUE)
TRI_AQL_NODE_TYPE(node) = TRI_AQL_TYPE_INT;
TRI_AQL_NODE_INT(node) = value;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST double value node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeValueDoubleAql (TRI_aql_context_t* const context,
const double value) {
CREATE_NODE(TRI_AQL_NODE_VALUE)
TRI_AQL_NODE_TYPE(node) = TRI_AQL_TYPE_DOUBLE;
TRI_AQL_NODE_DOUBLE(node) = value;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST bool value node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeValueBoolAql (TRI_aql_context_t* const context,
const bool value) {
CREATE_NODE(TRI_AQL_NODE_VALUE)
TRI_AQL_NODE_TYPE(node) = TRI_AQL_TYPE_BOOL;
TRI_AQL_NODE_BOOL(node) = value;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST string value node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeValueStringAql (TRI_aql_context_t* const context,
const char* const value) {
CREATE_NODE(TRI_AQL_NODE_VALUE)
if (value == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
TRI_AQL_NODE_TYPE(node) = TRI_AQL_TYPE_STRING;
TRI_AQL_NODE_STRING(node) = (char*) value;
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST list node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeListAql (TRI_aql_context_t* const context) {
CREATE_NODE(TRI_AQL_NODE_LIST)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST array node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeArrayAql (TRI_aql_context_t* const context) {
CREATE_NODE(TRI_AQL_NODE_ARRAY)
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST array element node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeArrayElementAql (TRI_aql_context_t* const context,
const char* const name,
const TRI_aql_node_t* const value) {
CREATE_NODE(TRI_AQL_NODE_ARRAY_ELEMENT)
if (name == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
TRI_AQL_NODE_STRING(node) = (char*) name;
ADD_MEMBER(value);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST function call node
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_t* TRI_CreateNodeFcallAql (TRI_aql_context_t* const context,
const char* const name,
const TRI_aql_node_t* const parameters) {
TRI_aql_node_t* node;
char* upperName;
if (name == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
if (strchr(name, TRI_AQL_NAMESPACE_SEPARATOR_CHAR) != NULL) {
upperName = TRI_UpperAsciiStringZ(TRI_CORE_MEM_ZONE, name);
}
else {
char* tempName = TRI_UpperAsciiStringZ(TRI_CORE_MEM_ZONE, name);
upperName = TRI_Concatenate2String(TRI_AQL_DEFAULT_PREFIX, tempName);
TRI_Free(TRI_CORE_MEM_ZONE, tempName);
}
if (upperName == NULL) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return NULL;
}
if (*upperName == '_') {
// default internal namespace
node = CreateNodeInternalFcall(context, name, upperName, parameters);
}
else {
// user namespace
node = CreateNodeUserFcall(context, name, upperName, parameters);
}
TRI_Free(TRI_CORE_MEM_ZONE, upperName);
return node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a value to the end of a list
////////////////////////////////////////////////////////////////////////////////
bool TRI_PushListAql (TRI_aql_context_t* const context,
const TRI_aql_node_t* const value) {
TRI_aql_node_t* node = static_cast<TRI_aql_node_t*>(TRI_PeekStackParseAql(context));
TRI_ASSERT(node);
if (value == NULL ||
TRI_ERROR_NO_ERROR != TRI_PushBackVectorPointer(&node->_members, (void*) value)) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a value to the end of an array
////////////////////////////////////////////////////////////////////////////////
bool TRI_PushArrayAql (TRI_aql_context_t* const context,
const char* const name,
const TRI_aql_node_t* const value) {
TRI_aql_node_t* node = static_cast<TRI_aql_node_t*>(TRI_PeekStackParseAql(context));
TRI_aql_node_t* element;
TRI_ASSERT(node);
element = TRI_CreateNodeArrayElementAql(context, name, value);
if (element == NULL ||
TRI_ERROR_NO_ERROR != TRI_PushBackVectorPointer(&node->_members, element)) {
TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the boolean value of a node
////////////////////////////////////////////////////////////////////////////////
bool TRI_GetBooleanNodeValueAql (const TRI_aql_node_t* const node) {
TRI_ASSERT(node);
TRI_ASSERT(node->_type == TRI_AQL_NODE_VALUE);
return TRI_AQL_NODE_BOOL(node);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the numeric value of a node
////////////////////////////////////////////////////////////////////////////////
double TRI_GetNumericNodeValueAql (const TRI_aql_node_t* const node) {
TRI_ASSERT(node);
TRI_ASSERT(node->_type == TRI_AQL_NODE_VALUE);
if (node->_value._type == TRI_AQL_TYPE_INT) {
return (double) TRI_AQL_NODE_INT(node);
}
if (node->_value._type == TRI_AQL_TYPE_DOUBLE) {
return TRI_AQL_NODE_DOUBLE(node);
}
if (node->_value._type == TRI_AQL_TYPE_BOOL) {
return TRI_AQL_NODE_BOOL(node) ? 1.0 : 0.0;
}
return 0.0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief reverse a relational operator
////////////////////////////////////////////////////////////////////////////////
TRI_aql_node_type_e TRI_ReverseOperatorRelationalAql (const TRI_aql_node_type_e source) {
switch (source) {
case TRI_AQL_NODE_OPERATOR_BINARY_LT:
return TRI_AQL_NODE_OPERATOR_BINARY_GT;
case TRI_AQL_NODE_OPERATOR_BINARY_LE:
return TRI_AQL_NODE_OPERATOR_BINARY_GE;
case TRI_AQL_NODE_OPERATOR_BINARY_GT:
return TRI_AQL_NODE_OPERATOR_BINARY_LT;
case TRI_AQL_NODE_OPERATOR_BINARY_GE:
return TRI_AQL_NODE_OPERATOR_BINARY_LE;
case TRI_AQL_NODE_OPERATOR_BINARY_NE:
case TRI_AQL_NODE_OPERATOR_BINARY_EQ:
return source;
case TRI_AQL_NODE_OPERATOR_BINARY_IN:
default: {
TRI_ASSERT(false);
return TRI_AQL_NODE_NOP;
}
}
}
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End: