From 619aeb4afa3c3980f3be5dce3534474d4e9e6561 Mon Sep 17 00:00:00 2001 From: VilhoRaatikka Date: Tue, 24 Jun 2014 21:45:00 +0300 Subject: [PATCH] Query classifier can keep parse tree after the function that created it returns. Parse tree can then be queried from outside. Added skygw_query_classifier_get_stmtname which returns the name of statement, and skygw_query_classifier_free which frees mysql handle, parse tree and thread context (thd). --- query_classifier/query_classifier.cc | 60 +++++++++++++++++++++------- query_classifier/query_classifier.h | 36 +++++++++++------ 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/query_classifier/query_classifier.cc b/query_classifier/query_classifier.cc index 2da6d4ad5..ed4f93ea1 100644 --- a/query_classifier/query_classifier.cc +++ b/query_classifier/query_classifier.cc @@ -101,7 +101,8 @@ static int is_autocommit_stmt( */ skygw_query_type_t skygw_query_classifier_get_type( const char* query, - unsigned long client_flags) + unsigned long client_flags, + MYSQL** p_mysql) { MYSQL* mysql; char* query_str; @@ -129,9 +130,13 @@ skygw_query_type_t skygw_query_classifier_get_type( mysql_error(mysql)))); mysql_library_end(); - goto return_without_server; + goto return_qtype; } + if (p_mysql != NULL) + { + *p_mysql = mysql; + } /** Set methods and authentication to mysql */ mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_skygw"); mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL); @@ -143,28 +148,42 @@ skygw_query_type_t skygw_query_classifier_get_type( /** Get one or create new THD object to be use in parsing */ thd = get_or_create_thd_for_parsing(mysql, query_str); - if (thd == NULL) { - goto return_with_server_handle; + if (thd == NULL) + { + skygw_query_classifier_free(mysql); } /** Create parse_tree inside thd */ failp = create_parse_tree(thd); - if (failp) { - goto return_with_thd; + if (failp) + { + skygw_query_classifier_free(mysql); + *p_mysql = NULL; } qtype = resolve_query_type(thd); - -return_with_thd: - (*mysql->methods->free_embedded_thd)(mysql); - mysql->thd = 0; -return_with_server_handle: - mysql_close(mysql); - mysql_thread_end(); -return_without_server: + + if (p_mysql == NULL) + { + skygw_query_classifier_free(mysql); + } +return_qtype: return qtype; } +void skygw_query_classifier_free( + MYSQL* mysql) +{ + if (mysql->thd != NULL) + { + (*mysql->methods->free_embedded_thd)(mysql); + mysql->thd = NULL; + } + mysql_close(mysql); + mysql_thread_end(); +} + + /** * @node (write brief function description here) @@ -518,6 +537,11 @@ static skygw_query_type_t resolve_query_type( goto return_qtype; break; + case SQLCOM_PREPARE: + type |= QUERY_TYPE_PREPARE_NAMED_STMT; + goto return_qtype; + break; + default: break; } @@ -783,3 +807,11 @@ static int is_autocommit_stmt( return_rc: return rc; } + + +char* skygw_query_classifier_get_stmtname( + MYSQL* mysql) +{ + return ((THD *)(mysql->thd))->lex->prepared_stmt_name.str; + +} diff --git a/query_classifier/query_classifier.h b/query_classifier/query_classifier.h index 64727daa9..31f9cf44e 100644 --- a/query_classifier/query_classifier.h +++ b/query_classifier/query_classifier.h @@ -19,6 +19,7 @@ Copyright SkySQL Ab /** getpid */ #include +#include #include "../utils/skygw_utils.h" EXTERN_C_BLOCK_BEGIN @@ -29,25 +30,36 @@ EXTERN_C_BLOCK_BEGIN * is modified */ typedef enum { - QUERY_TYPE_UNKNOWN = 0x000, /*< Initial value, can't be tested bitwisely */ - QUERY_TYPE_LOCAL_READ = 0x001, /*< Read non-database data, execute in MaxScale */ - QUERY_TYPE_READ = 0x002, /*< No updates */ - QUERY_TYPE_WRITE = 0x004, /*< Master data will be modified */ - QUERY_TYPE_SESSION_WRITE = 0x008, /*< Session data will be modified */ - QUERY_TYPE_GLOBAL_WRITE = 0x010, /*< Global system variable modification */ - QUERY_TYPE_BEGIN_TRX = 0x020, /*< BEGIN or START TRANSACTION */ - QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x040,/*< SET autocommit=1 */ - QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x080,/*< SET autocommit=0 */ - QUERY_TYPE_ROLLBACK = 0x100, /*< ROLLBACK */ - QUERY_TYPE_COMMIT = 0x200 /*< COMMIT */ + QUERY_TYPE_UNKNOWN = 0x0000, /*< Initial value, can't be tested bitwisely */ + QUERY_TYPE_LOCAL_READ = 0x0001, /*< Read non-database data, execute in MaxScale */ + QUERY_TYPE_READ = 0x0002, /*< No updates */ + QUERY_TYPE_WRITE = 0x0004, /*< Master data will be modified */ + QUERY_TYPE_SESSION_WRITE = 0x0008, /*< Session data will be modified */ + QUERY_TYPE_GLOBAL_WRITE = 0x0010, /*< Global system variable modification */ + QUERY_TYPE_BEGIN_TRX = 0x0020, /*< BEGIN or START TRANSACTION */ + QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x0040, /*< SET autocommit=1 */ + QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x0080, /*< SET autocommit=0 */ + QUERY_TYPE_ROLLBACK = 0x0100, /*< ROLLBACK */ + QUERY_TYPE_COMMIT = 0x0200, /*< COMMIT */ + QUERY_TYPE_PREPARE_NAMED_STMT = 0x0400, /*< Prepared stmt with name from user */ + QUERY_TYPE_PREPARE_STMT = 0x0800, /*< Prepared stmt with id provided by server */ + QUERY_TYPE_EXEC_STMT = 0x1000 /*< Execute prepared statement */ } skygw_query_type_t; #define QUERY_IS_TYPE(mask,type) ((mask & type) == type) +/** + * Create THD and use it for creating parse tree. Examine parse tree and + * classify the query. + */ skygw_query_type_t skygw_query_classifier_get_type( const char* query_str, - unsigned long client_flags); + unsigned long client_flags, + MYSQL** mysql); +/** Free THD context and close MYSQL */ +void skygw_query_classifier_free(MYSQL* mysql); +char* skygw_query_classifier_get_stmtname(MYSQL* mysql); EXTERN_C_BLOCK_END