mirror of https://gitee.com/bigwinds/arangodb
explain command, 1st version, still unfinished
This commit is contained in:
parent
2e0edb9a79
commit
bd60683228
30
Makefile.in
30
Makefile.in
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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:
|
|
@ -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:
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
Loading…
Reference in New Issue