1
0
Fork 0

added AHUACATL_EXPLAIN() function

This commit is contained in:
Jan Steemann 2012-06-11 14:22:12 +02:00
parent 057ad98019
commit 385f0fdf97
3 changed files with 109 additions and 23 deletions

View File

@ -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;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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);
////////////////////////////////////////////////////////////////////////////////
/// @}

View File

@ -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(),