1
0
Fork 0

explain command, 1st version, still unfinished

This commit is contained in:
Jan Steemann 2012-06-11 13:36:11 +02:00
parent 2e0edb9a79
commit bd60683228
16 changed files with 788 additions and 126 deletions

View File

@ -454,6 +454,7 @@ am__bin_arangod_SOURCES_DIST = arangod/Actions/actions.cpp \
arangod/Ahuacatl/ahuacatl-context.c \
arangod/Ahuacatl/ahuacatl-conversions.c \
arangod/Ahuacatl/ahuacatl-error.c \
arangod/Ahuacatl/ahuacatl-explain.c \
arangod/Ahuacatl/ahuacatl-functions.c \
arangod/Ahuacatl/ahuacatl-grammar.c \
arangod/Ahuacatl/ahuacatl-index.c \
@ -508,6 +509,7 @@ am_bin_arangod_OBJECTS = \
arangod/Ahuacatl/bin_arangod-ahuacatl-context.$(OBJEXT) \
arangod/Ahuacatl/bin_arangod-ahuacatl-conversions.$(OBJEXT) \
arangod/Ahuacatl/bin_arangod-ahuacatl-error.$(OBJEXT) \
arangod/Ahuacatl/bin_arangod-ahuacatl-explain.$(OBJEXT) \
arangod/Ahuacatl/bin_arangod-ahuacatl-functions.$(OBJEXT) \
arangod/Ahuacatl/bin_arangod-ahuacatl-grammar.$(OBJEXT) \
arangod/Ahuacatl/bin_arangod-ahuacatl-index.$(OBJEXT) \
@ -1209,6 +1211,7 @@ bin_arangod_SOURCES = arangod/Actions/actions.cpp \
arangod/Ahuacatl/ahuacatl-context.c \
arangod/Ahuacatl/ahuacatl-conversions.c \
arangod/Ahuacatl/ahuacatl-error.c \
arangod/Ahuacatl/ahuacatl-explain.c \
arangod/Ahuacatl/ahuacatl-functions.c \
arangod/Ahuacatl/ahuacatl-grammar.c \
arangod/Ahuacatl/ahuacatl-index.c \
@ -1327,8 +1330,7 @@ UNITTESTS_SERVER = $(addprefix --unit-tests ,$(SHELL_SERVER))
################################################################################
################################################################################
SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-operators.js \
@srcdir@/js/server/tests/ahuacatl-escaping.js \
SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-escaping.js \
@srcdir@/js/server/tests/ahuacatl-functions.js \
@srcdir@/js/server/tests/ahuacatl-variables.js \
@srcdir@/js/server/tests/ahuacatl-bind.js \
@ -1344,7 +1346,8 @@ SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-operators.js \
@srcdir@/js/server/tests/ahuacatl-queries-variables.js \
@srcdir@/js/server/tests/ahuacatl-queries-geo.js \
@srcdir@/js/server/tests/ahuacatl-queries-collection.js \
@srcdir@/js/server/tests/ahuacatl-queries-noncollection.js
@srcdir@/js/server/tests/ahuacatl-queries-noncollection.js \
@srcdir@/js/server/tests/ahuacatl-operators.js
UNITTESTS_SERVER_AHUACATL = $(addprefix --unit-tests ,$(SHELL_SERVER_AHUACATL))
@ -2142,6 +2145,9 @@ arangod/Ahuacatl/bin_arangod-ahuacatl-conversions.$(OBJEXT): \
arangod/Ahuacatl/bin_arangod-ahuacatl-error.$(OBJEXT): \
arangod/Ahuacatl/$(am__dirstamp) \
arangod/Ahuacatl/$(DEPDIR)/$(am__dirstamp)
arangod/Ahuacatl/bin_arangod-ahuacatl-explain.$(OBJEXT): \
arangod/Ahuacatl/$(am__dirstamp) \
arangod/Ahuacatl/$(DEPDIR)/$(am__dirstamp)
arangod/Ahuacatl/bin_arangod-ahuacatl-functions.$(OBJEXT): \
arangod/Ahuacatl/$(am__dirstamp) \
arangod/Ahuacatl/$(DEPDIR)/$(am__dirstamp)
@ -2419,6 +2425,7 @@ mostlyclean-compile:
-rm -f arangod/Ahuacatl/bin_arangod-ahuacatl-context.$(OBJEXT)
-rm -f arangod/Ahuacatl/bin_arangod-ahuacatl-conversions.$(OBJEXT)
-rm -f arangod/Ahuacatl/bin_arangod-ahuacatl-error.$(OBJEXT)
-rm -f arangod/Ahuacatl/bin_arangod-ahuacatl-explain.$(OBJEXT)
-rm -f arangod/Ahuacatl/bin_arangod-ahuacatl-functions.$(OBJEXT)
-rm -f arangod/Ahuacatl/bin_arangod-ahuacatl-grammar.$(OBJEXT)
-rm -f arangod/Ahuacatl/bin_arangod-ahuacatl-index.$(OBJEXT)
@ -2664,6 +2671,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-context.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-conversions.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-error.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-explain.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-functions.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-grammar.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-index.Po@am__quote@
@ -3043,6 +3051,22 @@ arangod/Ahuacatl/bin_arangod-ahuacatl-error.obj: arangod/Ahuacatl/ahuacatl-error
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o arangod/Ahuacatl/bin_arangod-ahuacatl-error.obj `if test -f 'arangod/Ahuacatl/ahuacatl-error.c'; then $(CYGPATH_W) 'arangod/Ahuacatl/ahuacatl-error.c'; else $(CYGPATH_W) '$(srcdir)/arangod/Ahuacatl/ahuacatl-error.c'; fi`
arangod/Ahuacatl/bin_arangod-ahuacatl-explain.o: arangod/Ahuacatl/ahuacatl-explain.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT arangod/Ahuacatl/bin_arangod-ahuacatl-explain.o -MD -MP -MF arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-explain.Tpo -c -o arangod/Ahuacatl/bin_arangod-ahuacatl-explain.o `test -f 'arangod/Ahuacatl/ahuacatl-explain.c' || echo '$(srcdir)/'`arangod/Ahuacatl/ahuacatl-explain.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-explain.Tpo arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-explain.Po
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='arangod/Ahuacatl/ahuacatl-explain.c' object='arangod/Ahuacatl/bin_arangod-ahuacatl-explain.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o arangod/Ahuacatl/bin_arangod-ahuacatl-explain.o `test -f 'arangod/Ahuacatl/ahuacatl-explain.c' || echo '$(srcdir)/'`arangod/Ahuacatl/ahuacatl-explain.c
arangod/Ahuacatl/bin_arangod-ahuacatl-explain.obj: arangod/Ahuacatl/ahuacatl-explain.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT arangod/Ahuacatl/bin_arangod-ahuacatl-explain.obj -MD -MP -MF arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-explain.Tpo -c -o arangod/Ahuacatl/bin_arangod-ahuacatl-explain.obj `if test -f 'arangod/Ahuacatl/ahuacatl-explain.c'; then $(CYGPATH_W) 'arangod/Ahuacatl/ahuacatl-explain.c'; else $(CYGPATH_W) '$(srcdir)/arangod/Ahuacatl/ahuacatl-explain.c'; fi`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-explain.Tpo arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-explain.Po
@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='arangod/Ahuacatl/ahuacatl-explain.c' object='arangod/Ahuacatl/bin_arangod-ahuacatl-explain.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o arangod/Ahuacatl/bin_arangod-ahuacatl-explain.obj `if test -f 'arangod/Ahuacatl/ahuacatl-explain.c'; then $(CYGPATH_W) 'arangod/Ahuacatl/ahuacatl-explain.c'; else $(CYGPATH_W) '$(srcdir)/arangod/Ahuacatl/ahuacatl-explain.c'; fi`
arangod/Ahuacatl/bin_arangod-ahuacatl-functions.o: arangod/Ahuacatl/ahuacatl-functions.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(bin_arangod_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT arangod/Ahuacatl/bin_arangod-ahuacatl-functions.o -MD -MP -MF arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-functions.Tpo -c -o arangod/Ahuacatl/bin_arangod-ahuacatl-functions.o `test -f 'arangod/Ahuacatl/ahuacatl-functions.c' || echo '$(srcdir)/'`arangod/Ahuacatl/ahuacatl-functions.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-functions.Tpo arangod/Ahuacatl/$(DEPDIR)/bin_arangod-ahuacatl-functions.Po

View File

@ -178,8 +178,7 @@ unittests-shell-server:
## SHELL SERVER TESTS (AHUACATL)
################################################################################
SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-operators.js \
@srcdir@/js/server/tests/ahuacatl-escaping.js \
SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-escaping.js \
@srcdir@/js/server/tests/ahuacatl-functions.js \
@srcdir@/js/server/tests/ahuacatl-variables.js \
@srcdir@/js/server/tests/ahuacatl-bind.js \
@ -195,7 +194,8 @@ SHELL_SERVER_AHUACATL = @srcdir@/js/server/tests/ahuacatl-operators.js \
@srcdir@/js/server/tests/ahuacatl-queries-variables.js \
@srcdir@/js/server/tests/ahuacatl-queries-geo.js \
@srcdir@/js/server/tests/ahuacatl-queries-collection.js \
@srcdir@/js/server/tests/ahuacatl-queries-noncollection.js
@srcdir@/js/server/tests/ahuacatl-queries-noncollection.js \
@srcdir@/js/server/tests/ahuacatl-operators.js
.PHONY: unittests-shell-server-ahuacatl

View File

@ -42,7 +42,7 @@
/// @brief check if a node is a bind parameter and convert it into a value node
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* ModifyNode (void* data,
static TRI_aql_node_t* ModifyNode (TRI_aql_statement_walker_t* const walker,
TRI_aql_node_t* node) {
TRI_aql_bind_parameter_t* bind;
TRI_associative_pointer_t* bindValues;
@ -54,7 +54,7 @@ static TRI_aql_node_t* ModifyNode (void* data,
}
// we found a parameter node
context = (TRI_aql_context_t*) data;
context = (TRI_aql_context_t*) walker->_data;
assert(context);
bindValues = (TRI_associative_pointer_t*) &context->_parameters._values;
@ -68,7 +68,10 @@ static TRI_aql_node_t* ModifyNode (void* data,
if (*name == '@') {
// a collection name bind parameter
if (bind->_value->_type == TRI_JSON_STRING) {
char* collectionName = TRI_RegisterStringAql(context, bind->_value->_value._string.data, strlen(bind->_value->_value._string.data), false);
char* collectionName = TRI_RegisterStringAql(context,
bind->_value->_value._string.data,
strlen(bind->_value->_value._string.data),
false);
node = TRI_CreateNodeCollectionAql(context, collectionName);
}
else {

View File

@ -30,6 +30,7 @@
#include "Ahuacatl/ahuacatl-ast-node.h"
#include "Ahuacatl/ahuacatl-bind-parameter.h"
#include "Ahuacatl/ahuacatl-collections.h"
#include "Ahuacatl/ahuacatl-explain.h"
#include "Ahuacatl/ahuacatl-optimiser.h"
#include "Ahuacatl/ahuacatl-parser-functions.h"
#include "Ahuacatl/ahuacatl-scope.h"
@ -340,6 +341,7 @@ bool TRI_OptimiseQueryContextAql (TRI_aql_context_t* const context) {
return false;
}
// TRI_ExplainAql(context);
// TRI_DumpStatementsAql(context->_statements);
return true;
@ -372,54 +374,6 @@ bool TRI_LockQueryContextAql (TRI_aql_context_t* const context) {
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a new variable scope
////////////////////////////////////////////////////////////////////////////////
TRI_aql_scope2_t* TRI_CreateScopeAql (void) {
TRI_aql_scope2_t* scope;
scope = (TRI_aql_scope2_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_scope2_t), false);
if (!scope) {
return NULL;
}
TRI_InitAssociativePointer(&scope->_variables,
TRI_UNKNOWN_MEM_ZONE,
&TRI_HashStringKeyAssociativePointer,
&TRI_HashVariableAql,
&TRI_EqualVariableAql,
0);
scope->_last = NULL;
return scope;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free a variable scope
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeScopeAql (TRI_aql_scope2_t* const scope) {
size_t i, length;
assert(scope);
// free variables lookup hash
length = scope->_variables._nrAlloc;
for (i = 0; i < length; ++i) {
TRI_aql_variable_t* variable = scope->_variables._table[i];
if (variable) {
TRI_FreeVariableAql(variable);
}
}
TRI_DestroyAssociativePointer(&scope->_variables);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, scope);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief register a node
////////////////////////////////////////////////////////////////////////////////

View File

@ -55,17 +55,6 @@ extern "C" {
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief a variable scope
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_aql_scope2_s {
struct TRI_aql_scope_s* _parent; // parent scope
TRI_associative_pointer_t _variables; // symbol table
void* _last;
}
TRI_aql_scope2_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief the context for parsing a query
////////////////////////////////////////////////////////////////////////////////

View File

@ -26,13 +26,85 @@
////////////////////////////////////////////////////////////////////////////////
#include "Ahuacatl/ahuacatl-conversions.h"
#include "Ahuacatl/ahuacatl-node.h"
// -----------------------------------------------------------------------------
// --SECTION-- private types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief typedef for value list iteration callback function
////////////////////////////////////////////////////////////////////////////////
typedef bool (*convert_f) (TRI_string_buffer_t* const, const TRI_aql_node_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
static const char* GetStringOperator (const TRI_aql_node_type_e type) {
switch (type) {
case TRI_AQL_NODE_OPERATOR_UNARY_PLUS:
return " + ";
case TRI_AQL_NODE_OPERATOR_UNARY_MINUS:
return " - ";
case TRI_AQL_NODE_OPERATOR_UNARY_NOT:
return " ! ";
case TRI_AQL_NODE_OPERATOR_BINARY_AND:
return " && ";
case TRI_AQL_NODE_OPERATOR_BINARY_OR:
return " || ";
case TRI_AQL_NODE_OPERATOR_BINARY_PLUS:
return " + ";
case TRI_AQL_NODE_OPERATOR_BINARY_MINUS:
return " - ";
case TRI_AQL_NODE_OPERATOR_BINARY_TIMES:
return " * ";
case TRI_AQL_NODE_OPERATOR_BINARY_DIV:
return " / ";
case TRI_AQL_NODE_OPERATOR_BINARY_MOD:
return " % ";
case TRI_AQL_NODE_OPERATOR_BINARY_EQ:
return " == ";
case TRI_AQL_NODE_OPERATOR_BINARY_NE:
return " != ";
case TRI_AQL_NODE_OPERATOR_BINARY_LT:
return " < ";
case TRI_AQL_NODE_OPERATOR_BINARY_LE:
return " <= ";
case TRI_AQL_NODE_OPERATOR_BINARY_GT:
return " > ";
case TRI_AQL_NODE_OPERATOR_BINARY_GE:
return " >= ";
case TRI_AQL_NODE_OPERATOR_BINARY_IN:
return " in ";
default:
assert(false);
return NULL;
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief append list values to a string buffer
////////////////////////////////////////////////////////////////////////////////
static bool AppendListValues (TRI_string_buffer_t* const buffer,
const TRI_aql_node_t* const node) {
const TRI_aql_node_t* const node,
convert_f func) {
size_t i, n;
n = node->_members._length;
@ -43,7 +115,7 @@ static bool AppendListValues (TRI_string_buffer_t* const buffer,
}
}
if (!TRI_NodeJavascriptAql(buffer, TRI_AQL_NODE_MEMBER(node, i))) {
if (!func(buffer, TRI_AQL_NODE_MEMBER(node, i))) {
return false;
}
}
@ -51,6 +123,10 @@ static bool AppendListValues (TRI_string_buffer_t* const buffer,
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
@ -307,7 +383,7 @@ bool TRI_NodeJavascriptAql (TRI_string_buffer_t* const buffer,
return false;
}
if (!AppendListValues(buffer, node)) {
if (!AppendListValues(buffer, node, &TRI_NodeJavascriptAql)) {
return false;
}
@ -317,7 +393,7 @@ bool TRI_NodeJavascriptAql (TRI_string_buffer_t* const buffer,
return false;
}
if (!AppendListValues(buffer, node)) {
if (!AppendListValues(buffer, node, &TRI_NodeJavascriptAql)) {
return false;
}
@ -327,6 +403,172 @@ bool TRI_NodeJavascriptAql (TRI_string_buffer_t* const buffer,
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief convert a value node to a string representation, used for printing it
////////////////////////////////////////////////////////////////////////////////
bool TRI_ValueStringAql (TRI_string_buffer_t* const buffer,
const TRI_aql_value_t* const value,
const TRI_aql_value_type_e type) {
switch (type) {
case TRI_AQL_TYPE_FAIL:
return (TRI_AppendStringStringBuffer(buffer, "fail") == TRI_ERROR_NO_ERROR);
case TRI_AQL_TYPE_NULL:
return (TRI_AppendStringStringBuffer(buffer, "null") == TRI_ERROR_NO_ERROR);
case TRI_AQL_TYPE_BOOL:
return (TRI_AppendStringStringBuffer(buffer, value->_value._bool ? "true" : "false") == TRI_ERROR_NO_ERROR);
case TRI_AQL_TYPE_INT:
return (TRI_AppendInt64StringBuffer(buffer, value->_value._int) == TRI_ERROR_NO_ERROR);
case TRI_AQL_TYPE_DOUBLE:
return (TRI_AppendDoubleStringBuffer(buffer, value->_value._double) == TRI_ERROR_NO_ERROR);
case TRI_AQL_TYPE_STRING: {
if (TRI_AppendCharStringBuffer(buffer, '"') != TRI_ERROR_NO_ERROR) {
return false;
}
if (TRI_AppendStringStringBuffer(buffer, value->_value._string) != TRI_ERROR_NO_ERROR) {
return false;
}
return (TRI_AppendCharStringBuffer(buffer, '"') == TRI_ERROR_NO_ERROR);
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief convert a node to its string representation, used for printing it
////////////////////////////////////////////////////////////////////////////////
bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer,
const TRI_aql_node_t* const node) {
switch (node->_type) {
case TRI_AQL_NODE_VALUE:
return TRI_ValueStringAql(buffer, &node->_value, node->_value._type);
case TRI_AQL_NODE_ARRAY_ELEMENT:
if (!TRI_ValueStringAql(buffer, &node->_value, TRI_AQL_TYPE_STRING)) {
return false;
}
if (TRI_AppendCharStringBuffer(buffer, ':') != TRI_ERROR_NO_ERROR) {
return false;
}
return TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 0));
case TRI_AQL_NODE_LIST:
if (TRI_AppendCharStringBuffer(buffer, '[') != TRI_ERROR_NO_ERROR) {
return false;
}
if (!AppendListValues(buffer, node, &TRI_NodeStringAql)) {
return false;
}
return (TRI_AppendCharStringBuffer(buffer, ']') == TRI_ERROR_NO_ERROR);
case TRI_AQL_NODE_ARRAY:
if (TRI_AppendCharStringBuffer(buffer, '{') != TRI_ERROR_NO_ERROR) {
return false;
}
if (!AppendListValues(buffer, node, &TRI_NodeStringAql)) {
return false;
}
return (TRI_AppendCharStringBuffer(buffer, '}') == TRI_ERROR_NO_ERROR);
case TRI_AQL_NODE_OPERATOR_UNARY_PLUS:
case TRI_AQL_NODE_OPERATOR_UNARY_MINUS:
case TRI_AQL_NODE_OPERATOR_UNARY_NOT:
if (!TRI_AppendStringStringBuffer(buffer, GetStringOperator(node->_type)) == TRI_ERROR_NO_ERROR) {
return false;
}
return TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 0));
case TRI_AQL_NODE_OPERATOR_BINARY_AND:
case TRI_AQL_NODE_OPERATOR_BINARY_OR:
case TRI_AQL_NODE_OPERATOR_BINARY_PLUS:
case TRI_AQL_NODE_OPERATOR_BINARY_MINUS:
case TRI_AQL_NODE_OPERATOR_BINARY_TIMES:
case TRI_AQL_NODE_OPERATOR_BINARY_DIV:
case TRI_AQL_NODE_OPERATOR_BINARY_MOD:
case TRI_AQL_NODE_OPERATOR_BINARY_EQ:
case TRI_AQL_NODE_OPERATOR_BINARY_NE:
case TRI_AQL_NODE_OPERATOR_BINARY_LT:
case TRI_AQL_NODE_OPERATOR_BINARY_LE:
case TRI_AQL_NODE_OPERATOR_BINARY_GT:
case TRI_AQL_NODE_OPERATOR_BINARY_GE:
case TRI_AQL_NODE_OPERATOR_BINARY_IN:
if (!TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 0))) {
return false;
}
if (!TRI_AppendStringStringBuffer(buffer, GetStringOperator(node->_type)) == TRI_ERROR_NO_ERROR) {
return false;
}
return TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 1));
case TRI_AQL_NODE_OPERATOR_TERNARY:
if (!TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 0))) {
return false;
}
if (!TRI_AppendStringStringBuffer(buffer, " ? ") == TRI_ERROR_NO_ERROR) {
return false;
}
if (!TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 1))) {
return false;
}
if (!TRI_AppendStringStringBuffer(buffer, " : ") == TRI_ERROR_NO_ERROR) {
return false;
}
return TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 2));
case TRI_AQL_NODE_ATTRIBUTE_ACCESS:
if (!TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 0))) {
return false;
}
if (!TRI_AppendStringStringBuffer(buffer, ".") == TRI_ERROR_NO_ERROR) {
return false;
}
return TRI_AppendStringStringBuffer(buffer, TRI_AQL_NODE_STRING(node)) == TRI_ERROR_NO_ERROR;
case TRI_AQL_NODE_INDEXED:
if (!TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 0))) {
return false;
}
if (!TRI_AppendStringStringBuffer(buffer, "[") == TRI_ERROR_NO_ERROR) {
return false;
}
if (!TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 1))) {
return false;
}
return TRI_AppendStringStringBuffer(buffer, "]") == TRI_ERROR_NO_ERROR;
case TRI_AQL_NODE_EXPAND:
// TODO
break;
case TRI_AQL_NODE_REFERENCE:
return TRI_AppendStringStringBuffer(buffer, TRI_AQL_NODE_STRING(node)) == TRI_ERROR_NO_ERROR;
case TRI_AQL_NODE_COLLECTION:
if (!TRI_NodeStringAql(buffer, TRI_AQL_NODE_MEMBER(node, 0))) {
return false;
}
return true;
default: {
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -77,6 +77,21 @@ bool TRI_ValueJavascriptAql (TRI_string_buffer_t* const,
bool TRI_NodeJavascriptAql (TRI_string_buffer_t* const,
const TRI_aql_node_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @brief convert a value node to a string representation
////////////////////////////////////////////////////////////////////////////////
bool TRI_ValueStringAql (TRI_string_buffer_t* const,
const TRI_aql_value_t* const,
const TRI_aql_value_type_e);
////////////////////////////////////////////////////////////////////////////////
/// @brief convert a node to its string representation, used for printing it
////////////////////////////////////////////////////////////////////////////////
bool TRI_NodeStringAql (TRI_string_buffer_t* const ,
const TRI_aql_node_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,328 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Ahuacatl, explain
///
/// @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/ahuacatl-explain.h"
#include "Ahuacatl/ahuacatl-conversions.h"
#include "Ahuacatl/ahuacatl-scope.h"
#include "Ahuacatl/ahuacatl-statement-walker.h"
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief convert a node to its string representation
////////////////////////////////////////////////////////////////////////////////
static TRI_json_t* StringifyNode (const TRI_aql_node_t* const node) {
TRI_json_t* result;
TRI_string_buffer_t buffer;
assert(node);
TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);
if (!TRI_NodeStringAql(&buffer, node)) {
return NULL;
}
result = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, buffer._buffer);
TRI_DestroyStringBuffer(&buffer);
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a row to the result json structure
////////////////////////////////////////////////////////////////////////////////
static inline bool AddRow (TRI_aql_explain_t* const explain, TRI_json_t* value) {
return TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, explain->_result, value) == TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get an empty row protoype
////////////////////////////////////////////////////////////////////////////////
static inline TRI_json_t* GetRowProtoType (TRI_aql_explain_t* const explain,
const TRI_aql_node_t* const node) {
TRI_json_t* row;
row = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
if (row == NULL) {
return NULL;
}
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
row,
"id",
TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, (double) ++explain->_count));
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
row,
"level",
TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, (double) explain->_level - 1));
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
row,
"type",
TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_NodeNameAql(node->_type)));
return row;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an explain structure
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_explain_t* CreateExplain (void) {
TRI_aql_explain_t* explain;
explain = (TRI_aql_explain_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_explain_t), false);
if (explain == NULL) {
return NULL;
}
explain->_count = 0;
explain->_level = 0;
explain->_result = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE);
if (explain->_result == NULL) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, explain);
return NULL;
}
return explain;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free an explain structure
////////////////////////////////////////////////////////////////////////////////
static void FreeExplain (TRI_aql_explain_t* const explain) {
assert(explain);
assert(explain->_result);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, explain->_result);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, explain);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief process a single statement
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* ProcessStatement (TRI_aql_statement_walker_t* const walker,
TRI_aql_node_t* node) {
TRI_aql_explain_t* explain;
TRI_aql_node_type_e type = node->_type;
explain = (TRI_aql_explain_t*) walker->_data;
switch (type) {
case TRI_AQL_NODE_SCOPE_START: {
++explain->_level;
break;
}
case TRI_AQL_NODE_SCOPE_END: {
--explain->_level;
break;
}
case TRI_AQL_NODE_FOR: {
TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 0);
TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 1);
TRI_json_t* row;
TRI_json_t* condition;
row = GetRowProtoType(explain, node);
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
row,
"variable",
TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));
condition = StringifyNode(expressionNode);
if (condition != NULL) {
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
row,
"value",
condition);
}
AddRow(explain, row);
break;
}
case TRI_AQL_NODE_FILTER: {
// TODO
TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 0);
TRI_json_t* row;
TRI_json_t* condition;
row = GetRowProtoType(explain, node);
condition = StringifyNode(expressionNode);
if (condition != NULL) {
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
row,
"condition",
condition);
}
AddRow(explain, row);
break;
}
case TRI_AQL_NODE_LET: {
// TODO
TRI_json_t* row;
TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 0);
row = GetRowProtoType(explain, node);
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
row,
"variable",
TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));
AddRow(explain, row);
break;
}
case TRI_AQL_NODE_SORT: {
// TODO
/*
TRI_aql_node_t* conditionNode = TRI_AQL_NODE_MEMBER(node, 0);
value = GetRowProtoType(explain, node);
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
value,
"condition",
TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));
AddRow(explain, value);
*/
break;
}
case TRI_AQL_NODE_LIMIT: {
TRI_aql_node_t* offsetNode = TRI_AQL_NODE_MEMBER(node, 0);
TRI_aql_node_t* countNode = TRI_AQL_NODE_MEMBER(node, 1);
TRI_json_t* row;
row = GetRowProtoType(explain, node);
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
row,
"offset",
TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_DOUBLE(offsetNode)));
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
row,
"count",
TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, (double) TRI_AQL_NODE_DOUBLE(countNode)));
AddRow(explain, row);
break;
}
case TRI_AQL_NODE_COLLECT: {
// TODO
break;
}
default: {
}
}
return NULL;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief explain a query
////////////////////////////////////////////////////////////////////////////////
bool TRI_ExplainAql (TRI_aql_context_t* const context) {
TRI_aql_statement_walker_t* walker;
TRI_aql_explain_t* explain;
explain = CreateExplain();
if (explain == NULL) {
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return false;
}
walker = TRI_CreateStatementWalkerAql((void*) explain,
false,
NULL,
&ProcessStatement,
NULL);
if (walker == NULL) {
FreeExplain(explain);
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
return false;
}
TRI_WalkStatementsAql(walker, context->_statements);
{ // TODO: move to function
TRI_string_buffer_t sb;
TRI_InitStringBuffer(&sb, TRI_UNKNOWN_MEM_ZONE);
TRI_StringifyJson(&sb, explain->_result);
printf("%s\n", sb._buffer);
TRI_DestroyStringBuffer(&sb);
}
FreeExplain(explain);
TRI_FreeStatementWalkerAql(walker);
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -0,0 +1,92 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Ahuacatl, explain
///
/// @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
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_DURHAM_AHUACATL_EXPLAIN_H
#define TRIAGENS_DURHAM_AHUACATL_EXPLAIN_H 1
#include <BasicsC/common.h>
#include <BasicsC/json.h>
#include <BasicsC/vector.h>
#include "Ahuacatl/ahuacatl-context.h"
#include "Ahuacatl/ahuacatl-node.h"
#include "Ahuacatl/ahuacatl-log.h"
#include "Ahuacatl/ahuacatl-scope.h"
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// --SECTION-- public types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_aql_explain_s {
size_t _count;
size_t _level;
TRI_json_t* _result;
}
TRI_aql_explain_t;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief explain a query
////////////////////////////////////////////////////////////////////////////////
bool TRI_ExplainAql (TRI_aql_context_t* const);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -149,7 +149,7 @@ const char* TRI_NodeNameAql (const TRI_aql_node_type_e type) {
case TRI_AQL_NODE_FCALL:
return "function call";
}
assert(false);
return "undefined";
}

View File

@ -46,13 +46,15 @@
/// @brief optimise a node recursively
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* ProcessNode (void*, TRI_aql_node_t*);
static TRI_aql_node_t* ProcessNode (TRI_aql_statement_walker_t* const,
TRI_aql_node_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief optimise a statement
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* ProcessStatement (void*, TRI_aql_node_t*);
static TRI_aql_node_t* ProcessStatement (TRI_aql_statement_walker_t* const,
TRI_aql_node_t*);
////////////////////////////////////////////////////////////////////////////////
/// @}
@ -980,8 +982,9 @@ static TRI_aql_node_t* OptimiseStatement (TRI_aql_context_t* const context,
/// this is the callback function used by the statement walker
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* ProcessNode (void* data, TRI_aql_node_t* node) {
TRI_aql_context_t* context = (TRI_aql_context_t*) data;
static TRI_aql_node_t* ProcessNode (TRI_aql_statement_walker_t* const walker,
TRI_aql_node_t* node) {
TRI_aql_context_t* context = (TRI_aql_context_t*) walker->_data;
return OptimiseNode(context, node);
}
@ -992,8 +995,9 @@ static TRI_aql_node_t* ProcessNode (void* data, TRI_aql_node_t* node) {
/// this is the callback function used by the statement walker
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* ProcessStatement (void* data, TRI_aql_node_t* node) {
TRI_aql_context_t* context = (TRI_aql_context_t*) data;
static TRI_aql_node_t* ProcessStatement (TRI_aql_statement_walker_t* const walker,
TRI_aql_node_t* node) {
TRI_aql_context_t* context = (TRI_aql_context_t*) walker->_data;
TRI_aql_node_t* result = node;
if (node) {
@ -1003,9 +1007,6 @@ static TRI_aql_node_t* ProcessStatement (void* data, TRI_aql_node_t* node) {
StartScope(context, TRI_AQL_SCOPE_FOR, node, TRI_AQL_NODE_STRING(nameNode));
}
/* else if (node->_type == TRI_AQL_NODE_SUBQUERY) {
StartScope(context, TRI_AQL_SCOPE_FUNCTION, NULL, NULL);
}*/ // TODO: REMOVE
result = OptimiseStatement(context, node);
@ -1014,11 +1015,6 @@ static TRI_aql_node_t* ProcessStatement (void* data, TRI_aql_node_t* node) {
PatchForLoops(context);
EndScope(context, true);
}
/* TODO: REMOVE
else if (node->_type == TRI_AQL_NODE_SUBQUERY) {
EndScope(context, false);
}
*/
}
return result;

View File

@ -74,6 +74,9 @@ static inline TRI_aql_scope_e CurrentType (TRI_aql_context_t* const context) {
////////////////////////////////////////////////////////////////////////////////
/// @brief get the type for the next scope
///
/// this returns TRI_AQL_SCOPE_FOR_NESTED for a nested for scope, and the
/// originally requested type in all other cases
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_scope_e NextType (TRI_aql_context_t* const context,

View File

@ -101,9 +101,7 @@ static void DumpValue (TRI_aql_dump_t* const state, const TRI_aql_node_t* const
/// @brief increase the indent level by one
////////////////////////////////////////////////////////////////////////////////
static void Indent (void* data) {
TRI_aql_dump_t* state = (TRI_aql_dump_t*) data;
static inline void Indent (TRI_aql_dump_t* const state) {
++state->_indent;
}
@ -111,8 +109,7 @@ static void Indent (void* data) {
/// @brief decrease the indent level by one
////////////////////////////////////////////////////////////////////////////////
static void Outdent (void* data) {
TRI_aql_dump_t* state = (TRI_aql_dump_t*) data;
static inline void Outdent (TRI_aql_dump_t* const state) {
assert(state->_indent > 0);
--state->_indent;
@ -122,13 +119,16 @@ static void Outdent (void* data) {
/// @brief dump an AST node
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* DumpNode (void* data, TRI_aql_node_t* const node) {
TRI_aql_dump_t* state = (TRI_aql_dump_t*) data;
static TRI_aql_node_t* DumpNode (TRI_aql_statement_walker_t* const walker,
TRI_aql_node_t* const node) {
TRI_aql_dump_t* state = (TRI_aql_dump_t*) walker->_data;
if (node == NULL) {
return node;
}
assert(state);
PrintType(state, node->_type);
Indent(state);
@ -168,26 +168,30 @@ static TRI_aql_node_t* DumpNode (void* data, TRI_aql_node_t* const node) {
/// @brief dump a statement
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* DumpStatementStart (void* data, TRI_aql_node_t* const node) {
static TRI_aql_node_t* DumpStatementStart (TRI_aql_statement_walker_t* const walker,
TRI_aql_node_t* const node) {
if (node == NULL) {
return node;
}
Indent((TRI_aql_dump_t*) data);
assert(walker);
Indent((TRI_aql_dump_t*) walker->_data);
return DumpNode(data, node);
return DumpNode(walker, node);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief dump an AST node
////////////////////////////////////////////////////////////////////////////////
static TRI_aql_node_t* DumpStatementEnd (void* data, TRI_aql_node_t* const node) {
static TRI_aql_node_t* DumpStatementEnd (TRI_aql_statement_walker_t* const walker,
TRI_aql_node_t* const node) {
if (node == NULL) {
return node;
}
Outdent((TRI_aql_dump_t*) data);
assert(walker);
Outdent((TRI_aql_dump_t*) walker->_data);
return node;
}

View File

@ -46,14 +46,25 @@
static void VisitStatement (TRI_aql_statement_walker_t* const walker,
const size_t position,
TRI_aql_visit_statement_f func) {
TRI_aql_visit_f func) {
TRI_aql_node_t* node;
TRI_aql_node_t* modified;
node = (TRI_aql_node_t*) TRI_AtVectorPointer(&walker->_statements->_statements, position);
assert(node);
modified = func(walker->_data, node);
// handle scopes
if (node->_type == TRI_AQL_NODE_SCOPE_START) {
TRI_PushBackVectorPointer(&walker->_currentScopes, TRI_AQL_NODE_DATA(node));
}
else if (node->_type == TRI_AQL_NODE_SCOPE_END) {
size_t n = walker->_currentScopes._length;
assert(n > 0);
TRI_RemoveVectorPointer(&walker->_currentScopes, n - 1);
}
modified = func(walker, node);
if (walker->_canModify && modified != node) {
if (modified == NULL) {
modified = TRI_GetNopNodeAql();
@ -86,7 +97,7 @@ static void VisitMembers (TRI_aql_statement_walker_t* const walker,
VisitMembers(walker, member);
modified = walker->visitMember(walker->_data, member);
modified = walker->visitMember(walker, member);
if (walker->_canModify && modified != member) {
if (modified == NULL) {
modified = TRI_GetNopNodeAql();
@ -112,6 +123,10 @@ static void RunWalk (TRI_aql_statement_walker_t* const walker) {
node = (TRI_aql_node_t*) TRI_AtVectorPointer(&walker->_statements->_statements, i);
if (!node) {
continue;
}
if (walker->preVisitStatement != NULL) {
// this might change the node ptr
VisitStatement(walker, i, walker->preVisitStatement);
@ -148,9 +163,9 @@ static void RunWalk (TRI_aql_statement_walker_t* const walker) {
TRI_aql_statement_walker_t* TRI_CreateStatementWalkerAql (void* data,
const bool canModify,
TRI_aql_visit_node_f visitMember,
TRI_aql_visit_statement_f preVisitStatement,
TRI_aql_visit_statement_f postVisitStatement) {
TRI_aql_visit_f visitMember,
TRI_aql_visit_f preVisitStatement,
TRI_aql_visit_f postVisitStatement) {
TRI_aql_statement_walker_t* walker;
walker = (TRI_aql_statement_walker_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_statement_walker_t), false);
@ -165,6 +180,8 @@ TRI_aql_statement_walker_t* TRI_CreateStatementWalkerAql (void* data,
walker->preVisitStatement = preVisitStatement;
walker->postVisitStatement = postVisitStatement;
TRI_InitVectorPointer(&walker->_currentScopes, TRI_UNKNOWN_MEM_ZONE);
return walker;
}
@ -175,6 +192,8 @@ TRI_aql_statement_walker_t* TRI_CreateStatementWalkerAql (void* data,
void TRI_FreeStatementWalkerAql (TRI_aql_statement_walker_t* const walker) {
assert(walker);
TRI_DestroyVectorPointer(&walker->_currentScopes);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, walker);
}

View File

@ -30,10 +30,7 @@
#include <BasicsC/common.h>
#include <BasicsC/strings.h>
#include <BasicsC/hashes.h>
#include <BasicsC/vector.h>
#include <BasicsC/associative.h>
#include <BasicsC/json.h>
#include "Ahuacatl/ahuacatl-ast-node.h"
#include "Ahuacatl/ahuacatl-context.h"
@ -56,18 +53,6 @@ extern "C" {
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief typedef for node visitation function
////////////////////////////////////////////////////////////////////////////////
typedef TRI_aql_node_t* (*TRI_aql_visit_node_f)(void*, TRI_aql_node_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief typedef for statement visitation function
////////////////////////////////////////////////////////////////////////////////
typedef TRI_aql_node_t* (*TRI_aql_visit_statement_f)(void*, TRI_aql_node_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief tree walker container
////////////////////////////////////////////////////////////////////////////////
@ -76,13 +61,20 @@ typedef struct TRI_aql_statement_walker_s {
void* _data;
bool _canModify;
TRI_aql_statement_list_t* _statements;
TRI_vector_pointer_t _currentScopes;
TRI_aql_visit_node_f visitMember;
TRI_aql_visit_statement_f preVisitStatement;
TRI_aql_visit_statement_f postVisitStatement;
TRI_aql_node_t* (*visitMember)(struct TRI_aql_statement_walker_s* const, TRI_aql_node_t*);
TRI_aql_node_t* (*preVisitStatement)(struct TRI_aql_statement_walker_s* const, TRI_aql_node_t*);
TRI_aql_node_t* (*postVisitStatement)(struct TRI_aql_statement_walker_s* const, TRI_aql_node_t*);
}
TRI_aql_statement_walker_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief typedef for node visitation function
////////////////////////////////////////////////////////////////////////////////
typedef TRI_aql_node_t* (*TRI_aql_visit_f)(TRI_aql_statement_walker_t* const, TRI_aql_node_t*);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@ -102,9 +94,9 @@ TRI_aql_statement_walker_t;
TRI_aql_statement_walker_t* TRI_CreateStatementWalkerAql (void*,
const bool,
TRI_aql_visit_node_f,
TRI_aql_visit_statement_f,
TRI_aql_visit_statement_f);
TRI_aql_visit_f,
TRI_aql_visit_f,
TRI_aql_visit_f);
////////////////////////////////////////////////////////////////////////////////
/// @brief free a statement walker

View File

@ -23,6 +23,7 @@ bin_arangod_SOURCES = \
arangod/Ahuacatl/ahuacatl-context.c \
arangod/Ahuacatl/ahuacatl-conversions.c \
arangod/Ahuacatl/ahuacatl-error.c \
arangod/Ahuacatl/ahuacatl-explain.c \
arangod/Ahuacatl/ahuacatl-functions.c \
arangod/Ahuacatl/ahuacatl-grammar.c \
arangod/Ahuacatl/ahuacatl-index.c \