mirror of https://gitee.com/bigwinds/arangodb
added AHUACATL_EXPLAIN() function
This commit is contained in:
parent
057ad98019
commit
385f0fdf97
|
@ -133,9 +133,11 @@ static TRI_aql_explain_t* CreateExplain (void) {
|
|||
|
||||
static void FreeExplain (TRI_aql_explain_t* const explain) {
|
||||
assert(explain);
|
||||
assert(explain->_result);
|
||||
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, explain->_result);
|
||||
// note: explain->_result is intentionally not freed here
|
||||
// the value is returned by TRI_ExplainAql() and must be
|
||||
// freed by the caller
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, explain);
|
||||
}
|
||||
|
||||
|
@ -172,43 +174,55 @@ static TRI_aql_node_t* ProcessStatement (TRI_aql_statement_walker_t* const walke
|
|||
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);
|
||||
TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 1);
|
||||
TRI_json_t* row;
|
||||
TRI_json_t* expression;
|
||||
|
||||
row = GetRowProtoType(explain, node);
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
|
||||
row,
|
||||
"variable",
|
||||
TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));
|
||||
|
||||
expression = StringifyNode(expressionNode);
|
||||
if (expression != NULL) {
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
|
||||
row,
|
||||
"value",
|
||||
expression);
|
||||
}
|
||||
|
||||
AddRow(explain, row);
|
||||
break;
|
||||
}
|
||||
|
@ -276,15 +290,16 @@ static TRI_aql_node_t* ProcessStatement (TRI_aql_statement_walker_t* const walke
|
|||
/// @brief explain a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_ExplainAql (TRI_aql_context_t* const context) {
|
||||
TRI_json_t* TRI_ExplainAql (TRI_aql_context_t* const context) {
|
||||
TRI_aql_statement_walker_t* walker;
|
||||
TRI_aql_explain_t* explain;
|
||||
TRI_json_t* result;
|
||||
|
||||
explain = CreateExplain();
|
||||
if (explain == NULL) {
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
walker = TRI_CreateStatementWalkerAql((void*) explain,
|
||||
|
@ -297,25 +312,17 @@ bool TRI_ExplainAql (TRI_aql_context_t* const context) {
|
|||
FreeExplain(explain);
|
||||
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
result = explain->_result;
|
||||
|
||||
FreeExplain(explain);
|
||||
|
||||
TRI_FreeStatementWalkerAql(walker);
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -72,9 +72,11 @@ TRI_aql_explain_t;
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief explain a query
|
||||
///
|
||||
/// note: the caller of this function must free the returned json_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_ExplainAql (TRI_aql_context_t* const);
|
||||
TRI_json_t* TRI_ExplainAql (TRI_aql_context_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "Ahuacatl/ahuacatl-ast-node.h"
|
||||
#include "Ahuacatl/ahuacatl-codegen.h"
|
||||
#include "Ahuacatl/ahuacatl-context.h"
|
||||
#include "Ahuacatl/ahuacatl-explain.h"
|
||||
#include "Ahuacatl/ahuacatl-result.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "BasicsC/conversions.h"
|
||||
|
@ -1704,7 +1705,7 @@ static v8::Handle<v8::Value> JS_Cursor (v8::Arguments const& argv) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates code for an Ahuacatl query and runs it
|
||||
/// @brief creates code for an AQL query and runs it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
|
||||
|
@ -1737,7 +1738,7 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
|
|||
bool doCount = false;
|
||||
// maximum number of results to return at once
|
||||
uint32_t batchSize = 1000;
|
||||
// directly return the results as a javascript array instrad of a cursor (performance optimisation)
|
||||
// directly return the results as a javascript array instead of a cursor object (performance optimisation)
|
||||
bool allowDirectReturn = false;
|
||||
if (argc > 2) {
|
||||
doCount = TRI_ObjectToBoolean(argv[2]);
|
||||
|
@ -1781,7 +1782,79 @@ static v8::Handle<v8::Value> JS_RunAhuacatl (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief parses a query and returns the parse result
|
||||
/// @brief explains an AQL query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_ExplainAhuacatl (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
v8::TryCatch tryCatch;
|
||||
const uint32_t argc = argv.Length();
|
||||
|
||||
if (argc < 1 || argc > 2) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("usage: AHUACATL_EXPLAIN(<querystring>, <bindvalues>)")));
|
||||
}
|
||||
|
||||
TRI_vocbase_t* vocbase = GetContextVocBase();
|
||||
if (!vocbase) {
|
||||
v8::Handle<v8::Object> errorObject = TRI_CreateErrorObject(TRI_ERROR_INTERNAL, "corrupted vocbase");
|
||||
|
||||
return scope.Close(v8::ThrowException(errorObject));
|
||||
}
|
||||
|
||||
// get the query string
|
||||
v8::Handle<v8::Value> queryArg = argv[0];
|
||||
if (!queryArg->IsString()) {
|
||||
v8::Handle<v8::Object> errorObject = TRI_CreateErrorObject(TRI_ERROR_BAD_PARAMETER, "expecting string for <querystring>");
|
||||
|
||||
return scope.Close(v8::ThrowException(errorObject));
|
||||
}
|
||||
|
||||
const string queryString = TRI_ObjectToString(queryArg);
|
||||
|
||||
// bind parameters
|
||||
triagens::rest::JsonContainer parameters(TRI_UNKNOWN_MEM_ZONE, argc > 1 ? TRI_JsonObject(argv[1]) : 0);
|
||||
|
||||
TRI_aql_context_t* context = TRI_CreateContextAql(vocbase, queryString.c_str());
|
||||
if (!context) {
|
||||
v8::Handle<v8::Object> errorObject = TRI_CreateErrorObject(TRI_ERROR_OUT_OF_MEMORY, "out of memory");
|
||||
|
||||
return scope.Close(v8::ThrowException(errorObject));
|
||||
}
|
||||
|
||||
TRI_json_t* explain = 0;
|
||||
|
||||
if (!TRI_ValidateQueryContextAql(context) ||
|
||||
!TRI_BindQueryContextAql(context, parameters.ptr()) ||
|
||||
!TRI_OptimiseQueryContextAql(context) ||
|
||||
!(explain = TRI_ExplainAql(context))) {
|
||||
v8::Handle<v8::Object> errorObject = CreateErrorObjectAhuacatl(&context->_error);
|
||||
TRI_FreeContextAql(context);
|
||||
return scope.Close(v8::ThrowException(errorObject));
|
||||
}
|
||||
|
||||
assert(explain);
|
||||
|
||||
v8::Handle<v8::Value> result;
|
||||
result = TRI_ObjectJson(explain);
|
||||
TRI_FreeContextAql(context);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, explain);
|
||||
|
||||
if (tryCatch.HasCaught()) {
|
||||
if (tryCatch.Exception()->IsObject() && v8::Handle<v8::Array>::Cast(tryCatch.Exception())->HasOwnProperty(v8::String::New("errorNum"))) {
|
||||
// we already have an ArangoError object
|
||||
return scope.Close(v8::ThrowException(tryCatch.Exception()));
|
||||
}
|
||||
|
||||
// create a new error object
|
||||
v8::Handle<v8::Object> errorObject = TRI_CreateErrorObject(TRI_ERROR_QUERY_SCRIPT, TRI_ObjectToString(tryCatch.Exception()).c_str());
|
||||
return scope.Close(v8::ThrowException(errorObject));
|
||||
}
|
||||
|
||||
return scope.Close(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief parses an AQL query and returns the parse result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_ParseAhuacatl (v8::Arguments const& argv) {
|
||||
|
@ -4601,6 +4674,10 @@ TRI_v8_global_t* TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocba
|
|||
context->Global()->Set(v8::String::New("AHUACATL_RUN"),
|
||||
v8::FunctionTemplate::New(JS_RunAhuacatl)->GetFunction(),
|
||||
v8::ReadOnly);
|
||||
|
||||
context->Global()->Set(v8::String::New("AHUACATL_EXPLAIN"),
|
||||
v8::FunctionTemplate::New(JS_ExplainAhuacatl)->GetFunction(),
|
||||
v8::ReadOnly);
|
||||
|
||||
context->Global()->Set(v8::String::New("AHUACATL_PARSE"),
|
||||
v8::FunctionTemplate::New(JS_ParseAhuacatl)->GetFunction(),
|
||||
|
|
Loading…
Reference in New Issue