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).

This commit is contained in:
VilhoRaatikka
2014-06-24 21:45:00 +03:00
parent d0cae12ca5
commit 619aeb4afa
2 changed files with 70 additions and 26 deletions

View File

@ -101,7 +101,8 @@ static int is_autocommit_stmt(
*/ */
skygw_query_type_t skygw_query_classifier_get_type( skygw_query_type_t skygw_query_classifier_get_type(
const char* query, const char* query,
unsigned long client_flags) unsigned long client_flags,
MYSQL** p_mysql)
{ {
MYSQL* mysql; MYSQL* mysql;
char* query_str; char* query_str;
@ -129,9 +130,13 @@ skygw_query_type_t skygw_query_classifier_get_type(
mysql_error(mysql)))); mysql_error(mysql))));
mysql_library_end(); mysql_library_end();
goto return_without_server; goto return_qtype;
} }
if (p_mysql != NULL)
{
*p_mysql = mysql;
}
/** Set methods and authentication to mysql */ /** Set methods and authentication to mysql */
mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_skygw"); mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_skygw");
mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL); mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);
@ -143,25 +148,39 @@ skygw_query_type_t skygw_query_classifier_get_type(
/** Get one or create new THD object to be use in parsing */ /** Get one or create new THD object to be use in parsing */
thd = get_or_create_thd_for_parsing(mysql, query_str); thd = get_or_create_thd_for_parsing(mysql, query_str);
if (thd == NULL) { if (thd == NULL)
goto return_with_server_handle; {
skygw_query_classifier_free(mysql);
} }
/** Create parse_tree inside thd */ /** Create parse_tree inside thd */
failp = create_parse_tree(thd); failp = create_parse_tree(thd);
if (failp) { if (failp)
goto return_with_thd; {
skygw_query_classifier_free(mysql);
*p_mysql = NULL;
} }
qtype = resolve_query_type(thd); qtype = resolve_query_type(thd);
return_with_thd: if (p_mysql == NULL)
(*mysql->methods->free_embedded_thd)(mysql); {
mysql->thd = 0; skygw_query_classifier_free(mysql);
return_with_server_handle: }
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_close(mysql);
mysql_thread_end(); mysql_thread_end();
return_without_server:
return qtype;
} }
@ -518,6 +537,11 @@ static skygw_query_type_t resolve_query_type(
goto return_qtype; goto return_qtype;
break; break;
case SQLCOM_PREPARE:
type |= QUERY_TYPE_PREPARE_NAMED_STMT;
goto return_qtype;
break;
default: default:
break; break;
} }
@ -783,3 +807,11 @@ static int is_autocommit_stmt(
return_rc: return_rc:
return rc; return rc;
} }
char* skygw_query_classifier_get_stmtname(
MYSQL* mysql)
{
return ((THD *)(mysql->thd))->lex->prepared_stmt_name.str;
}

View File

@ -19,6 +19,7 @@ Copyright SkySQL Ab
/** getpid */ /** getpid */
#include <unistd.h> #include <unistd.h>
#include <mysql.h>
#include "../utils/skygw_utils.h" #include "../utils/skygw_utils.h"
EXTERN_C_BLOCK_BEGIN EXTERN_C_BLOCK_BEGIN
@ -29,25 +30,36 @@ EXTERN_C_BLOCK_BEGIN
* is modified * is modified
*/ */
typedef enum { typedef enum {
QUERY_TYPE_UNKNOWN = 0x000, /*< Initial value, can't be tested bitwisely */ QUERY_TYPE_UNKNOWN = 0x0000, /*< Initial value, can't be tested bitwisely */
QUERY_TYPE_LOCAL_READ = 0x001, /*< Read non-database data, execute in MaxScale */ QUERY_TYPE_LOCAL_READ = 0x0001, /*< Read non-database data, execute in MaxScale */
QUERY_TYPE_READ = 0x002, /*< No updates */ QUERY_TYPE_READ = 0x0002, /*< No updates */
QUERY_TYPE_WRITE = 0x004, /*< Master data will be modified */ QUERY_TYPE_WRITE = 0x0004, /*< Master data will be modified */
QUERY_TYPE_SESSION_WRITE = 0x008, /*< Session data will be modified */ QUERY_TYPE_SESSION_WRITE = 0x0008, /*< Session data will be modified */
QUERY_TYPE_GLOBAL_WRITE = 0x010, /*< Global system variable modification */ QUERY_TYPE_GLOBAL_WRITE = 0x0010, /*< Global system variable modification */
QUERY_TYPE_BEGIN_TRX = 0x020, /*< BEGIN or START TRANSACTION */ QUERY_TYPE_BEGIN_TRX = 0x0020, /*< BEGIN or START TRANSACTION */
QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x040,/*< SET autocommit=1 */ QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x0040, /*< SET autocommit=1 */
QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x080,/*< SET autocommit=0 */ QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x0080, /*< SET autocommit=0 */
QUERY_TYPE_ROLLBACK = 0x100, /*< ROLLBACK */ QUERY_TYPE_ROLLBACK = 0x0100, /*< ROLLBACK */
QUERY_TYPE_COMMIT = 0x200 /*< COMMIT */ 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; } skygw_query_type_t;
#define QUERY_IS_TYPE(mask,type) ((mask & type) == type) #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( skygw_query_type_t skygw_query_classifier_get_type(
const char* query_str, 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 EXTERN_C_BLOCK_END