mirror of https://gitee.com/bigwinds/arangodb
1467 lines
43 KiB
C
1467 lines
43 KiB
C
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief Ahuacatl, parser nodes
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2010-2012 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 triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// @author Jan Steemann
|
|
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "Ahuacatl/ast-node.h"
|
|
#include "Ahuacatl/ahuacatl-functions.h"
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private macros
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Ahuacatl
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief shortcut macro for signalling out of memory
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define ABORT_OOM \
|
|
TRI_SetErrorAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); \
|
|
return NULL;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Ahuacatl
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static inline void InitNode (TRI_aql_parse_context_t* const context,
|
|
TRI_aql_node_t* const node,
|
|
const TRI_aql_node_type_e type) {
|
|
node->_type = type;
|
|
node->_next = NULL;
|
|
node->free = NULL;
|
|
|
|
TRI_RegisterNodeParseContextAql(context, node);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief free a list node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeNodeList (TRI_aql_node_t* const node) {
|
|
TRI_aql_node_list_t* _node = (TRI_aql_node_list_t*) node;
|
|
|
|
TRI_DestroyVectorPointer(&_node->_values);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief free an array node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void FreeNodeArray (TRI_aql_node_t* const node) {
|
|
TRI_aql_node_array_t* _node = (TRI_aql_node_array_t*) node;
|
|
|
|
TRI_DestroyAssociativePointer(&_node->_values);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief hash array element
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static uint64_t HashArrayElement (TRI_associative_pointer_t* array,
|
|
void const* element) {
|
|
TRI_aql_node_array_element_t* e = (TRI_aql_node_array_element_t*) element;
|
|
|
|
return TRI_FnvHashString(e->_name);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief comparison function used to determine array element equality
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool EqualArrayElement (TRI_associative_pointer_t* array,
|
|
void const* key,
|
|
void const* element) {
|
|
TRI_aql_node_array_element_t* e = (TRI_aql_node_array_element_t*) element;
|
|
|
|
return TRI_EqualString(key, e->_name);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- public functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Ahuacatl
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST for node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeForAql (TRI_aql_parse_context_t* const context,
|
|
const char* const name,
|
|
const TRI_aql_node_t* const expression) {
|
|
TRI_aql_node_for_t* node;
|
|
TRI_aql_node_t* variableNode;
|
|
|
|
assert(context);
|
|
|
|
if (!name || !expression) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_for_t*) TRI_Allocate(sizeof(TRI_aql_node_for_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_FOR);
|
|
|
|
variableNode = TRI_CreateNodeVariableAql(context, name);
|
|
if (!variableNode) {
|
|
return NULL;
|
|
}
|
|
|
|
node->_variable = variableNode;
|
|
node->_expression = (TRI_aql_node_t*) expression;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
/*
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST let node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeLetAql (TRI_aql_parse_context_t* const context,
|
|
const char* const name,
|
|
const TRI_aql_node_t* const expression) {
|
|
TRI_aql_node_let_t* node;
|
|
TRI_aql_node_t* variableNode;
|
|
|
|
assert(context);
|
|
|
|
if (!name || !expression) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_let_t*) TRI_Allocate(sizeof(TRI_aql_node_let_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_LET);
|
|
|
|
variableNode = TRI_CreateNodeVariableAql(context, name);
|
|
if (!variableNode) {
|
|
return NULL;
|
|
}
|
|
|
|
node->_variable = variableNode;
|
|
node->_expression = (TRI_aql_node_t*) expression;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
*/
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST filter node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeFilterAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const expression) {
|
|
TRI_aql_node_filter_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!expression) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_filter_t*) TRI_Allocate(sizeof(TRI_aql_node_filter_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_FILTER);
|
|
|
|
node->_expression = (TRI_aql_node_t*) expression;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST return node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeReturnAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const expression) {
|
|
TRI_aql_node_return_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!expression) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_return_t*) TRI_Allocate(sizeof(TRI_aql_node_return_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_RETURN);
|
|
|
|
node->_expression = (TRI_aql_node_t*) expression;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST collect node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeCollectAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const list,
|
|
const char* const name) {
|
|
TRI_aql_node_collect_t* node;
|
|
TRI_aql_node_t* variableNode;
|
|
|
|
assert(context);
|
|
|
|
if (!list) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_collect_t*) TRI_Allocate(sizeof(TRI_aql_node_collect_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_COLLECT);
|
|
|
|
node->_list = (TRI_aql_node_t*) list;
|
|
|
|
node->_into = NULL;
|
|
if (name) {
|
|
variableNode = TRI_CreateNodeVariableAql(context, name);
|
|
if (!variableNode) {
|
|
return NULL;
|
|
}
|
|
node->_into = variableNode;
|
|
}
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST sort node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeSortAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const list) {
|
|
TRI_aql_node_sort_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!list) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_sort_t*) TRI_Allocate(sizeof(TRI_aql_node_sort_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_SORT);
|
|
|
|
node->_list = (TRI_aql_node_t*) list;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST sort element node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeSortElementAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const expression,
|
|
const bool ascending) {
|
|
TRI_aql_node_sort_element_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!expression) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_sort_element_t*) TRI_Allocate(sizeof(TRI_aql_node_sort_element_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_SORT_ELEMENT);
|
|
|
|
node->_expression = (TRI_aql_node_t*) expression;
|
|
node->_ascending = ascending;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST limit node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeLimitAql (TRI_aql_parse_context_t* const context,
|
|
const int64_t offset,
|
|
const int64_t count) {
|
|
TRI_aql_node_limit_t* node;
|
|
|
|
assert(context);
|
|
|
|
node = (TRI_aql_node_limit_t*) TRI_Allocate(sizeof(TRI_aql_node_limit_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_LIMIT);
|
|
|
|
node->_offset = offset;
|
|
node->_count = count;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST assign node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeAssignAql (TRI_aql_parse_context_t* const context,
|
|
const char* const name,
|
|
const TRI_aql_node_t* const expression) {
|
|
TRI_aql_node_assign_t* node;
|
|
TRI_aql_node_t* variableNode;
|
|
|
|
assert(context);
|
|
|
|
if (!name || !expression) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_assign_t*) TRI_Allocate(sizeof(TRI_aql_node_assign_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_ASSIGN);
|
|
|
|
variableNode = TRI_CreateNodeVariableAql(context, name);
|
|
if (!variableNode) {
|
|
return NULL;
|
|
}
|
|
|
|
node->_variable = variableNode;
|
|
node->_expression = (TRI_aql_node_t*) expression;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST variable node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeVariableAql (TRI_aql_parse_context_t* const context,
|
|
const char* const name) {
|
|
TRI_aql_node_variable_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!name) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (!TRI_AddVariableParseContextAql(context, name)) {
|
|
// duplicate variable name
|
|
TRI_SetErrorAql(context, TRI_ERROR_QUERY_VARIABLE_REDECLARED, name);
|
|
return NULL;
|
|
}
|
|
|
|
node = (TRI_aql_node_variable_t*) TRI_Allocate(sizeof(TRI_aql_node_variable_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_VARIABLE);
|
|
|
|
node->_name = (char*) name;
|
|
|
|
if (!node->_name) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST reference node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeReferenceAql (TRI_aql_parse_context_t* const context,
|
|
const char* const name,
|
|
const bool isCollection) {
|
|
TRI_aql_node_reference_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!name) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_reference_t*) TRI_Allocate(sizeof(TRI_aql_node_reference_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_REFERENCE);
|
|
|
|
node->_name = (char*) name;
|
|
node->_isCollection = isCollection;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST attribute node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeAttributeAql (TRI_aql_parse_context_t* const context,
|
|
const char* const name) {
|
|
TRI_aql_node_attribute_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!name) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_attribute_t*) TRI_Allocate(sizeof(TRI_aql_node_attribute_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_ATTRIBUTE);
|
|
|
|
node->_name = (char*) name;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST parameter node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeParameterAql (TRI_aql_parse_context_t* const context,
|
|
const char* const name) {
|
|
TRI_aql_node_parameter_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!name) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_parameter_t*) TRI_Allocate(sizeof(TRI_aql_node_parameter_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_PARAMETER);
|
|
|
|
node->_name = (char*) name;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST unary plus node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorUnaryPlusAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const operand) {
|
|
TRI_aql_node_operator_unary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!operand) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_unary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_unary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_UNARY_PLUS);
|
|
|
|
node->_operand = (TRI_aql_node_t*) operand;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST unary minus node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorUnaryMinusAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const operand) {
|
|
TRI_aql_node_operator_unary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!operand) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_unary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_unary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_UNARY_MINUS);
|
|
|
|
node->_operand = (TRI_aql_node_t*) operand;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST unary not node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorUnaryNotAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const operand) {
|
|
TRI_aql_node_operator_unary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!operand) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_unary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_unary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_UNARY_NOT);
|
|
|
|
node->_operand = (TRI_aql_node_t*) operand;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary and node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryAndAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_AND);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary or node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryOrAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_OR);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary eq node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryEqAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_EQ);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary ne node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryNeAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_NE);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary lt node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryLtAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_LT);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary le node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryLeAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_LE);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary gt node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryGtAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_GT);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary ge node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryGeAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_GE);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary in node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryInAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_IN);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary plus node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryPlusAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_PLUS);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary minus node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryMinusAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_MINUS);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary times node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryTimesAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_TIMES);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary div node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryDivAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_DIV);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST binary mod node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorBinaryModAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const lhs,
|
|
const TRI_aql_node_t* const rhs) {
|
|
TRI_aql_node_operator_binary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!lhs || !rhs) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_binary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_binary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_BINARY_MOD);
|
|
|
|
node->_lhs = (TRI_aql_node_t*) lhs;
|
|
node->_rhs = (TRI_aql_node_t*) rhs;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST ternary operator node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeOperatorTernaryAql (TRI_aql_parse_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) {
|
|
TRI_aql_node_operator_ternary_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!condition || !truePart || !falsePart) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_operator_ternary_t*) TRI_Allocate(sizeof(TRI_aql_node_operator_ternary_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_OPERATOR_TERNARY);
|
|
|
|
node->_condition = (TRI_aql_node_t*) condition;
|
|
node->_truePart = (TRI_aql_node_t*) truePart;
|
|
node->_falsePart = (TRI_aql_node_t*) falsePart;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST subquery node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeSubqueryAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const query) {
|
|
TRI_aql_node_subquery_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!query) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_subquery_t*) TRI_Allocate(sizeof(TRI_aql_node_subquery_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_SUBQUERY);
|
|
|
|
node->_query = (TRI_aql_node_t*) query;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST attribute access node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeAttributeAccessAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const accessed,
|
|
const char* const name) {
|
|
TRI_aql_node_attribute_access_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!accessed || !name) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_attribute_access_t*) TRI_Allocate(sizeof(TRI_aql_node_attribute_access_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_ATTRIBUTE_ACCESS);
|
|
|
|
node->_accessed = (TRI_aql_node_t*) accessed;
|
|
node->_name = (char*) name;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST index access node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeIndexedAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const accessed,
|
|
const TRI_aql_node_t* const indexValue) {
|
|
TRI_aql_node_indexed_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!accessed || !indexValue) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_indexed_t*) TRI_Allocate(sizeof(TRI_aql_node_indexed_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_INDEXED);
|
|
|
|
node->_accessed = (TRI_aql_node_t*) accessed;
|
|
node->_index = (TRI_aql_node_t*) indexValue;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST expand node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeExpandAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const expanded,
|
|
const TRI_aql_node_t* const expansion) {
|
|
TRI_aql_node_expand_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!expanded || !expansion) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_expand_t*) TRI_Allocate(sizeof(TRI_aql_node_expand_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_EXPAND);
|
|
|
|
node->_expanded = (TRI_aql_node_t*) expanded;
|
|
node->_expansion = (TRI_aql_node_t*) expansion;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST null value node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeValueNullAql (TRI_aql_parse_context_t* const context) {
|
|
TRI_aql_node_value_t* node;
|
|
|
|
assert(context);
|
|
|
|
node = (TRI_aql_node_value_t*) TRI_Allocate(sizeof(TRI_aql_node_value_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_VALUE);
|
|
|
|
node->_value._type = AQL_TYPE_NULL;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST int value node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeValueIntAql (TRI_aql_parse_context_t* const context,
|
|
const int64_t value) {
|
|
TRI_aql_node_value_t* node;
|
|
|
|
assert(context);
|
|
|
|
node = (TRI_aql_node_value_t*) TRI_Allocate(sizeof(TRI_aql_node_value_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_VALUE);
|
|
|
|
node->_value._type = AQL_TYPE_INT;
|
|
node->_value._value._int = value;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST double value node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeValueDoubleAql (TRI_aql_parse_context_t* const context,
|
|
const double value) {
|
|
TRI_aql_node_value_t* node;
|
|
|
|
assert(context);
|
|
|
|
node = (TRI_aql_node_value_t*) TRI_Allocate(sizeof(TRI_aql_node_value_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_VALUE);
|
|
|
|
node->_value._type = AQL_TYPE_DOUBLE;
|
|
node->_value._value._double = value;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST bool value node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeValueBoolAql (TRI_aql_parse_context_t* const context,
|
|
const bool value) {
|
|
TRI_aql_node_value_t* node;
|
|
|
|
assert(context);
|
|
|
|
node = (TRI_aql_node_value_t*) TRI_Allocate(sizeof(TRI_aql_node_value_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_VALUE);
|
|
|
|
node->_value._type = AQL_TYPE_BOOL;
|
|
node->_value._value._bool = value;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST string value node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeValueStringAql (TRI_aql_parse_context_t* const context,
|
|
const char* const value) {
|
|
TRI_aql_node_value_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!value) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_value_t*) TRI_Allocate(sizeof(TRI_aql_node_value_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_VALUE);
|
|
|
|
node->_value._type = AQL_TYPE_STRING;
|
|
node->_value._value._string = (char*) value;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST list node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeListAql (TRI_aql_parse_context_t* const context) {
|
|
TRI_aql_node_list_t* node;
|
|
|
|
assert(context);
|
|
|
|
node = (TRI_aql_node_list_t*) TRI_Allocate(sizeof(TRI_aql_node_list_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_LIST);
|
|
|
|
TRI_InitVectorPointer(&node->_values);
|
|
node->_base.free = &FreeNodeList;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST array node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeArrayAql (TRI_aql_parse_context_t* const context) {
|
|
TRI_aql_node_array_t* node;
|
|
|
|
assert(context);
|
|
|
|
node = (TRI_aql_node_array_t*) TRI_Allocate(sizeof(TRI_aql_node_array_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_ARRAY);
|
|
|
|
TRI_InitAssociativePointer(&node->_values,
|
|
TRI_HashStringKeyAssociativePointer,
|
|
HashArrayElement,
|
|
EqualArrayElement,
|
|
0);
|
|
|
|
node->_base.free = &FreeNodeArray;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST array element node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeArrayElementAql (TRI_aql_parse_context_t* const context,
|
|
const char* const name,
|
|
const TRI_aql_node_t* const value) {
|
|
TRI_aql_node_array_element_t* node;
|
|
|
|
assert(context);
|
|
|
|
if (!value) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = (TRI_aql_node_array_element_t*) TRI_Allocate(sizeof(TRI_aql_node_array_element_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_ARRAY_ELEMENT);
|
|
|
|
node->_name = (char*) name;
|
|
node->_value = (TRI_aql_node_t*) value;
|
|
|
|
if (!node->_name) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create an AST function call node
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_aql_node_t* TRI_CreateNodeFcallAql (TRI_aql_parse_context_t* const context,
|
|
const char* const name,
|
|
const TRI_aql_node_t* const parameters) {
|
|
TRI_aql_node_fcall_t* node;
|
|
TRI_aql_function_t* function;
|
|
TRI_associative_pointer_t* functions;
|
|
|
|
assert(context);
|
|
assert(context->_vocbase);
|
|
|
|
|
|
if (!name || !parameters) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
functions = context->_vocbase->_functionsAql;
|
|
assert(functions);
|
|
|
|
// TODO: normalize function name
|
|
function = (TRI_aql_function_t*) TRI_LookupByKeyAssociativePointer(functions, (void*) name);
|
|
if (!function) {
|
|
// function name is unknown
|
|
TRI_SetErrorAql(context, TRI_ERROR_QUERY_FUNCTION_NAME_UNKNOWN, name);
|
|
return NULL;
|
|
}
|
|
|
|
node = (TRI_aql_node_fcall_t*) TRI_Allocate(sizeof(TRI_aql_node_fcall_t));
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
InitNode(context, (TRI_aql_node_t*) node, AQL_NODE_FCALL);
|
|
|
|
node->_name = function->_internalName;
|
|
node->_parameters = (TRI_aql_node_t*) parameters;
|
|
|
|
return (TRI_aql_node_t*) node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief add a value to the end of a list
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool TRI_PushListAql (TRI_aql_parse_context_t* const context,
|
|
const TRI_aql_node_t* const value) {
|
|
TRI_aql_node_list_t* list = (TRI_aql_node_list_t*) TRI_PeekStackAql(context);
|
|
|
|
assert(context);
|
|
assert(list);
|
|
|
|
if (!value) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
TRI_PushBackVectorPointer(&list->_values, (void*) value);
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief add a value to the end of an array
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool TRI_PushArrayAql (TRI_aql_parse_context_t* const context,
|
|
const char* const name,
|
|
const TRI_aql_node_t* const value) {
|
|
TRI_aql_node_array_t* array = (TRI_aql_node_array_t*) TRI_PeekStackAql(context);
|
|
TRI_aql_node_array_element_t* element;
|
|
|
|
assert(context);
|
|
assert(array);
|
|
|
|
if (!value) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
element = (TRI_aql_node_array_element_t*) TRI_CreateNodeArrayElementAql(context, name, value);
|
|
if (!element) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (TRI_InsertKeyAssociativePointer(&array->_values, element->_name, (void*) element, false)) {
|
|
// duplicate element in a document/array, e.g. { "name" : "John", "name" : "Jim" }
|
|
TRI_SetErrorAql(context, TRI_ERROR_QUERY_DOCUMENT_ATTRIBUTE_REDECLARED, name);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Local Variables:
|
|
// mode: outline-minor
|
|
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
|
// End:
|