diff --git a/query_classifier/makefile b/query_classifier/makefile index b08f0a9bd..35ef36d2a 100644 --- a/query_classifier/makefile +++ b/query_classifier/makefile @@ -8,6 +8,8 @@ SRCS := query_classifier.cc UTILS_PATH := $(ROOT_PATH)/utils QUERY_CLASSIFIER_PATH := $(ROOT_PATH)/query_classifier LOG_MANAGER_PATH := $(ROOT_PATH)/log_manager +SERVER_INC_PATH := $(ROOT_PATH)/server/include +MODULE_INC_PATH := $(ROOT_PATH)/server/modules/include makeall: clean all @@ -43,6 +45,9 @@ libcomp: $(CPP) -c $(CFLAGS) \ $(MYSQL_HEADERS) \ -I$(LOG_MANAGER_PATH) \ + -I$(SERVER_INC_PATH) \ + -I$(MODULE_INC_PATH) \ + -I$(UTILS_PATH) \ -I./ \ -fPIC ./query_classifier.cc -o query_classifier.o @@ -66,6 +71,9 @@ depend: $(CPP) -M $(CFLAGS) \ $(MYSQL_HEADERS) \ -I$(LOG_MANAGER_PATH) \ + -I$(SERVER_INC_PATH) \ + -I$(MODULE_INC_PATH) \ + -I$(UTILS_PATH) \ -I./ \ $(SRCS) > depend diff --git a/query_classifier/query_classifier.cc b/query_classifier/query_classifier.cc index 77b939819..7354d9639 100644 --- a/query_classifier/query_classifier.cc +++ b/query_classifier/query_classifier.cc @@ -34,6 +34,7 @@ #include "../utils/skygw_types.h" #include "../utils/skygw_debug.h" #include +#include #include #include @@ -83,122 +84,146 @@ static bool skygw_stmt_causes_implicit_commit( static int is_autocommit_stmt( LEX* lex); -/** - * @node (write brief function description here) - * - * Parameters: - * @param query_str - - * - * - * @param client_flag - - * - * - * @return - * +static bool query_is_parsed( + GWBUF* buf); + +static void parsing_info_set_plain_str(void* ptr, + char* str); + +/** + * Calls parser for the query includede in the buffer. Creates and adds parsing + * information to buffer if it doesn't exist already. Resolves the query type. * - * @details (write detailed description here) - * + * @param querybuf buffer including the query and possibly the parsing information + * + * @return query type */ -skygw_query_type_t skygw_query_classifier_get_type( - const char* query, - unsigned long client_flags, - MYSQL** p_mysql) +skygw_query_type_t query_classifier_get_type( + GWBUF* querybuf) { - MYSQL* mysql; - char* query_str; - const char* user = "skygw"; - const char* db = "skygw"; - THD* thd; + MYSQL* mysql; skygw_query_type_t qtype = QUERY_TYPE_UNKNOWN; - bool failp = FALSE; - - ss_info_dassert(query != NULL, ("query_str is NULL")); + bool succp; - query_str = const_cast(query); - LOGIF(LT, (skygw_log_write( - LOGFILE_TRACE, - "Query : \"%s\"", query_str))); + ss_info_dassert(querybuf != NULL, ("querybuf is NULL")); - /** Get server handle */ - mysql = mysql_init(NULL); - - if (mysql == NULL) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error : call to mysql_real_connect failed due %d, %s.", - mysql_errno(mysql), - mysql_error(mysql)))); - - mysql_library_end(); - goto return_qtype; - } - - if (p_mysql != NULL) + /** Create parsing info for the query and store it to buffer */ + if (!query_is_parsed(querybuf)) { - *p_mysql = mysql; + succp = parse_query(querybuf); } - /** Set methods and authentication to mysql */ - mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_skygw"); - mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL); - mysql->methods = &embedded_methods; - mysql->user = my_strdup(user, MYF(0)); - mysql->db = my_strdup(db, MYF(0)); - mysql->passwd = NULL; - - /** 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) + /** Read thd pointer and resolve the query type with it. */ + if (succp) { - skygw_query_classifier_free(mysql); - *p_mysql = NULL; - goto return_qtype; - } - /** - * Create parse_tree inside thd. - * thd and even lex are readable even if parser failed so let it - * continue despite failure. - */ - failp = create_parse_tree(thd); - qtype = resolve_query_type(thd); + parsing_info_t* pi = (parsing_info_t*)gwbuf_get_parsing_info(querybuf); + mysql = (MYSQL *)pi->pi_handle; - if (p_mysql == NULL) - { - skygw_query_classifier_free(mysql); + /** Find out the query type */ + if (mysql != NULL) + { + qtype = resolve_query_type((THD *)mysql->thd); + } } -return_qtype: return qtype; } - -void skygw_query_classifier_free( - MYSQL* mysql) +/** + * Create parsing info and try to parse the query included in the query buffer. + * Store pointer to created parse_tree_t object to buffer. + * + * @param querybuf buffer including the query and possibly the parsing information + * + * @return true if succeed, false otherwise + */ +bool parse_query ( + GWBUF* querybuf) { - if (mysql->thd != NULL) + bool succp; + THD* thd; + uint8_t* data; + size_t len; + char* query_str; + parsing_info_t* pi; + + CHK_GWBUF(querybuf); + ss_dassert(!query_is_parsed(querybuf)); + + if (querybuf->gwbuf_parsing_info == NULL) { - (*mysql->methods->free_embedded_thd)(mysql); - mysql->thd = NULL; + /** Create parsing info */ + querybuf->gwbuf_parsing_info = parsing_info_init(parsing_info_done); } - mysql_close(mysql); - mysql_thread_end(); -} + + if (querybuf->gwbuf_parsing_info == NULL) + { + succp = false; + goto retblock; + } + /** Extract query and copy it to different buffer */ + data = (uint8_t*)GWBUF_DATA(querybuf); + len = MYSQL_GET_PACKET_LEN(data)-1; /*< distract 1 for packet type byte */ + query_str = (char *)malloc(len+1); + + if (query_str == NULL) + { + succp = false; + goto retblock; + } + memcpy(query_str, &data[5], len); + memset(&query_str[len], 0, 1); + parsing_info_set_plain_str(querybuf->gwbuf_parsing_info, query_str); + + /** Get one or create new THD object to be use in parsing */ + pi = (parsing_info_t *)querybuf->gwbuf_parsing_info; + thd = get_or_create_thd_for_parsing((MYSQL *)pi->pi_handle, query_str); + + if (thd == NULL) + { + parsing_info_done(querybuf->gwbuf_parsing_info); + querybuf->gwbuf_parsing_info = NULL; + succp = false; + goto retblock; + } + /** + * Create parse_tree inside thd. + * thd and lex are readable even if creating parse tree fails. + */ + create_parse_tree(thd); + succp = true; +retblock: + return succp; +} +/** + * If buffer has non-NULL gwbuf_parsing_info it is parsed and it has parsing + * information included. + * + * @param buf buffer being examined + * + * @return true or false + */ +static bool query_is_parsed( + GWBUF* buf) +{ + if (buf->gwbuf_parsing_info != NULL) + { + return true; + } + return false; +} -/** - * @node (write brief function description here) + +/** + * Create a thread context, thd, init embedded server, connect to it, and allocate + * query to thd. * * Parameters: - * @param mysql - - * - * - * @param query_str - - * - * - * @return - * + * @param mysql Database handle * - * @details (write detailed description here) + * @param query_str Query in plain txt string + * + * @return Thread context pointer * */ static THD* get_or_create_thd_for_parsing( @@ -821,8 +846,7 @@ char* skygw_query_classifier_get_stmtname( * Replace user-provided literals with question marks. Return a copy of the * querystr with replacements. * - * @param mysql Database pointer - * @param querystr Query string + * @param querybuf GWBUF buffer including necessary parsing info * * @return Copy of querystr where literals are replaces with question marks or * NULL if querystr is NULL, thread context or lex are NULL or if replacement @@ -832,23 +856,32 @@ char* skygw_query_classifier_get_stmtname( * VARBIN_ITEM,NULL_ITEM */ char* skygw_get_canonical( - MYSQL* mysql, - char* querystr) + GWBUF* querybuf) { - THD* thd; - LEX* lex; - bool found = false; - char* newstr = NULL; - Item* item; + parsing_info_t* pi; + MYSQL* mysql; + THD* thd; + LEX* lex; + bool found = false; + char* newstr = NULL; + Item* item; + char* querystr; - ss_dassert(mysql != NULL && querystr != NULL); - - if (querystr == NULL || - mysql == NULL || + if (querybuf->gwbuf_parsing_info == NULL) + { + goto retblock; + } + pi = (parsing_info_t*)querybuf->gwbuf_parsing_info; + + if ((querystr = pi->pi_query_plain_str) == NULL || + (mysql = (MYSQL *)pi->pi_handle) == NULL || (thd = (THD *)mysql->thd) == NULL || (lex = thd->lex) == NULL) { - ss_dassert(thd != NULL && lex != NULL); + ss_dassert(querystr != NULL && + mysql != NULL && + thd != NULL && + lex != NULL); goto retblock; } @@ -858,12 +891,13 @@ char* skygw_get_canonical( itype = item->type(); - if (itype == Item::STRING_ITEM || + if (item->name != NULL && + (itype == Item::STRING_ITEM || itype == Item::INT_ITEM || itype == Item::DECIMAL_ITEM || itype == Item::REAL_ITEM || itype == Item::VARBIN_ITEM || - itype == Item::NULL_ITEM) + itype == Item::NULL_ITEM)) { if (!found) { @@ -881,4 +915,117 @@ char* skygw_get_canonical( } /*< for */ retblock: return newstr; +} + + +/** + * Create parsing information; initialize mysql handle, allocate parsing info + * struct and set handle and free function pointer to it. + * + * @param donefun pointer to free function + * + * @return pointer to parsing information + */ +parsing_info_t* parsing_info_init( + void (*donefun)(void *)) +{ + parsing_info_t* pi = NULL; + MYSQL* mysql; + const char* user = "skygw"; + const char* db = "skygw"; + + ss_dassert(donefun != NULL); + + /** Get server handle */ + mysql = mysql_init(NULL); + ss_dassert(mysql != NULL); + + if (mysql == NULL) { + LOGIF(LE, (skygw_log_write_flush( + LOGFILE_ERROR, + "Error : call to mysql_real_connect failed due %d, %s.", + mysql_errno(mysql), + mysql_error(mysql)))); + + mysql_library_end(); + goto retblock; + } + /** Set methods and authentication to mysql */ + mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_skygw"); + mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL); + mysql->methods = &embedded_methods; + mysql->user = my_strdup(user, MYF(0)); + mysql->db = my_strdup(db, MYF(0)); + mysql->passwd = NULL; + + pi = (parsing_info_t*)calloc(1, sizeof(parsing_info_t)); + + if (pi == NULL) + { + mysql_close(mysql); + mysql_thread_end(); + goto retblock; + } +#if defined(SS_DEBUG) + pi->pi_chk_top = CHK_NUM_PINFO; + pi->pi_chk_tail = CHK_NUM_PINFO; +#endif + /** Set handle and free function to parsing info struct */ + pi->pi_handle = mysql; + pi->pi_done_fp = donefun; + +retblock: + return pi; +} + +/** + * Free function for parsing info. Called by gwbuf_free or in case initialization + * of parsing information fails. + * + * @param ptr Pointer to parsing information, cast required + * + * @return void + * + */ +void parsing_info_done( + void* ptr) +{ + parsing_info_t* pi = (parsing_info_t *)ptr; + + if (pi->pi_handle != NULL) + { + MYSQL* mysql = (MYSQL *)pi->pi_handle; + + if (mysql->thd != NULL) + { + (*mysql->methods->free_embedded_thd)(mysql); + mysql->thd = NULL; + } + mysql_close(mysql); + mysql_thread_end(); + } + /** Free plain text query string */ + if (pi->pi_query_plain_str != NULL) + { + free(pi->pi_query_plain_str); + } + free(pi); +} + +/** + * Add plain text query string to parsing info. + * + * @param ptr Pointer to parsing info struct, cast required + * @param str String to be added + * + * @return void + */ +static void parsing_info_set_plain_str( + void* ptr, + char* str) +{ + parsing_info_t* pi = (parsing_info_t *)ptr; + CHK_PARSING_INFO(pi); + + pi->pi_query_plain_str = str; } \ No newline at end of file diff --git a/query_classifier/query_classifier.h b/query_classifier/query_classifier.h index fa7cefc78..beef84c2c 100644 --- a/query_classifier/query_classifier.h +++ b/query_classifier/query_classifier.h @@ -20,7 +20,8 @@ Copyright SkySQL Ab /** getpid */ #include #include -#include "../utils/skygw_utils.h" +#include +#include EXTERN_C_BLOCK_BEGIN @@ -52,15 +53,15 @@ typedef enum { * 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, - MYSQL** mysql); +skygw_query_type_t query_classifier_get_type(GWBUF* querybuf); /** Free THD context and close MYSQL */ -void skygw_query_classifier_free(MYSQL* mysql); -char* skygw_query_classifier_get_stmtname(MYSQL* mysql); -char* skygw_get_canonical(MYSQL* mysql, char* querystr); +char* skygw_query_classifier_get_stmtname(MYSQL* mysql); +char* skygw_get_canonical(GWBUF* querybuf); +bool parse_query (GWBUF* querybuf); +parsing_info_t* parsing_info_init(void (*donefun)(void *)); +void parsing_info_done(void* ptr); + EXTERN_C_BLOCK_END diff --git a/server/core/buffer.c b/server/core/buffer.c index d3278a505..47e9a22eb 100644 --- a/server/core/buffer.c +++ b/server/core/buffer.c @@ -83,7 +83,7 @@ SHARED_BUF *sbuf; rval->sbuf = sbuf; rval->next = NULL; rval->gwbuf_type = GWBUF_TYPE_UNDEFINED; - rval->command = 0; + rval->gwbuf_parsing_info = NULL; CHK_GWBUF(rval); return rval; } @@ -102,6 +102,11 @@ gwbuf_free(GWBUF *buf) free(buf->sbuf->data); free(buf->sbuf); } + if (buf->gwbuf_parsing_info != NULL) + { + parsing_info_t* pi = (parsing_info_t *)buf->gwbuf_parsing_info; + pi->pi_done_fp(pi); + } free(buf); } @@ -131,6 +136,7 @@ GWBUF *rval; rval->end = buf->end; rval->gwbuf_type = buf->gwbuf_type; rval->next = NULL; + rval->gwbuf_parsing_info = NULL; CHK_GWBUF(rval); return rval; } @@ -157,6 +163,7 @@ GWBUF *gwbuf_clone_portion( clonebuf->end = (void *)((char *)clonebuf->start)+length; clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone the type for now */ clonebuf->next = NULL; + clonebuf->gwbuf_parsing_info = NULL; CHK_GWBUF(clonebuf); return clonebuf; @@ -336,5 +343,10 @@ void gwbuf_set_type( } } - +void* gwbuf_get_parsing_info( + GWBUF* buf) +{ + CHK_GWBUF(buf); + return buf->gwbuf_parsing_info; +} diff --git a/server/core/modutil.c b/server/core/modutil.c index 78f389ebf..781c55763 100644 --- a/server/core/modutil.c +++ b/server/core/modutil.c @@ -29,6 +29,7 @@ */ #include #include +#include /** * Check if a GWBUF structure is a MySQL COM_QUERY packet @@ -171,3 +172,57 @@ GWBUF *addition; return orig; } + +/** + * Copy query string from GWBUF buffer to separate memory area. + * + * @param buf GWBUF buffer including the query + * + * @return Plaint text query if the packet type is COM_QUERY. Otherwise return + * a string including the packet type. + */ +char* modutil_get_query( + GWBUF* buf) +{ + uint8_t* packet; + mysql_server_cmd_t packet_type; + size_t len; + char* query_str; + + packet = GWBUF_DATA(buf); + packet_type = packet[4]; + + switch (packet_type) { + case MYSQL_COM_QUIT: + len = strlen("[Quit msg]")+1; + if ((query_str = (char *)malloc(len+1)) == NULL) + { + goto retblock; + } + memcpy(query_str, "[Quit msg]", len); + memset(&query_str[len], 0, 1); + break; + + case MYSQL_COM_QUERY: + len = MYSQL_GET_PACKET_LEN(packet)-1; /*< distract 1 for packet type byte */ + if ((query_str = (char *)malloc(len+1)) == NULL) + { + goto retblock; + } + memcpy(query_str, &packet[5], len); + memset(&query_str[len], 0, 1); + break; + + default: + len = strlen(STRPACKETTYPE(packet_type))+1; + if ((query_str = (char *)malloc(len+1)) == NULL) + { + goto retblock; + } + memcpy(query_str, STRPACKETTYPE(packet_type), len); + memset(&query_str[len], 0, 1); + break; + } /*< switch */ +retblock: + return query_str; +} \ No newline at end of file diff --git a/server/include/buffer.h b/server/include/buffer.h index 9729c538c..57e20dc2e 100644 --- a/server/include/buffer.h +++ b/server/include/buffer.h @@ -43,6 +43,7 @@ */ #include +EXTERN_C_BLOCK_BEGIN typedef enum { @@ -73,6 +74,20 @@ typedef struct { int refcount; /*< Reference count on the buffer */ } SHARED_BUF; + +typedef struct parsing_info_st { +#if defined(SS_DEBUG) + skygw_chk_t pi_chk_top; +#endif + void* pi_handle; /*< parsing info object pointer */ + char* pi_query_plain_str; /*< query as plain string */ + void (*pi_done_fp)(void *); /*< clean-up function for parsing info */ +#if defined(SS_DEBUG) + skygw_chk_t pi_chk_tail; +#endif +} parsing_info_t; + + /** * The buffer structure used by the descriptor control blocks. * @@ -86,7 +101,7 @@ typedef struct gwbuf { void *start; /*< Start of the valid data */ void *end; /*< First byte after the valid data */ SHARED_BUF *sbuf; /*< The shared buffer with the real data */ - int command;/*< The command type for the queue */ + void *gwbuf_parsing_info; /*< parsing info object pointer */ gwbuf_type_t gwbuf_type; /*< buffer's data type information */ } GWBUF; @@ -121,4 +136,10 @@ extern unsigned int gwbuf_length(GWBUF *head); extern GWBUF *gwbuf_clone_portion(GWBUF *head, size_t offset, size_t len); extern GWBUF *gwbuf_clone_transform(GWBUF *head, gwbuf_type_t type); extern void gwbuf_set_type(GWBUF *head, gwbuf_type_t type); +void* gwbuf_get_parsing_info(GWBUF* buf); + + +EXTERN_C_BLOCK_END + + #endif diff --git a/server/include/modutil.h b/server/include/modutil.h index 00336f937..a0624752a 100644 --- a/server/include/modutil.h +++ b/server/include/modutil.h @@ -36,4 +36,6 @@ extern int modutil_is_SQL(GWBUF *); extern int modutil_extract_SQL(GWBUF *, char **, int *); extern int modutil_MySQL_Query(GWBUF *, char **, int *, int *); extern GWBUF *modutil_replace_SQL(GWBUF *, char *); +char* modutil_get_query(GWBUF* buf); + #endif diff --git a/server/modules/routing/readwritesplit/readwritesplit.c b/server/modules/routing/readwritesplit/readwritesplit.c index 24262bc6d..f89f68562 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.c +++ b/server/modules/routing/readwritesplit/readwritesplit.c @@ -31,6 +31,7 @@ #include #include #include +#include #include MODULE_INFO info = { @@ -703,7 +704,7 @@ static void* newSession( backend_ref[i].bref_sescmd_cur.scmd_cur_ptr_property = &client_rses->rses_properties[RSES_PROP_TYPE_SESCMD]; backend_ref[i].bref_sescmd_cur.scmd_cur_cmd = NULL; - } + } max_nslaves = rses_get_max_slavecount(client_rses, router_nservers); max_slave_rlag = rses_get_max_replication_lag(client_rses); @@ -1031,9 +1032,6 @@ static int routeQuery( GWBUF* querybuf) { skygw_query_type_t qtype = QUERY_TYPE_UNKNOWN; - GWBUF* plainsqlbuf = NULL; - char* querystr = NULL; - char* startpos; mysql_server_cmd_t packet_type; uint8_t* packet; int ret = 0; @@ -1042,8 +1040,6 @@ static int routeQuery( ROUTER_INSTANCE* inst = (ROUTER_INSTANCE *)instance; ROUTER_CLIENT_SES* router_cli_ses = (ROUTER_CLIENT_SES *)router_session; bool rses_is_closed = false; - size_t len; - MYSQL* mysql = NULL; CHK_CLIENT_RSES(router_cli_ses); @@ -1066,6 +1062,8 @@ static int routeQuery( */ if (packet_type != MYSQL_COM_QUIT) { + char* query_str = modutil_get_query(querybuf); + LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, @@ -1073,15 +1071,15 @@ static int routeQuery( "backend server. %s.", STRPACKETTYPE(packet_type), STRQTYPE(qtype), - (querystr == NULL ? "(empty)" : querystr), + (query_str == NULL ? "(empty)" : query_str), (rses_is_closed ? "Router was closed" : "Router has no backend servers where to " "route to")))); + free(querybuf); } goto return_ret; } inst->stats.n_queries++; - startpos = (char *)&packet[5]; master_dcb = router_cli_ses->rses_master_ref->bref_dcb; CHK_DCB(master_dcb); @@ -1105,44 +1103,16 @@ static int routeQuery( break; case MYSQL_COM_QUERY: - plainsqlbuf = gwbuf_clone_transform(querybuf, - GWBUF_TYPE_PLAINSQL); - len = GWBUF_LENGTH(plainsqlbuf); - /** unnecessary if buffer includes additional terminating null */ - querystr = (char *)malloc(len+1); - memcpy(querystr, startpos, len); - memset(&querystr[len], 0, 1); - /** - * Use mysql handle to query information from parse tree. - * call skygw_query_classifier_free before exit! - */ - qtype = skygw_query_classifier_get_type(querystr, 0, &mysql); + qtype = query_classifier_get_type(querybuf); break; case MYSQL_COM_STMT_PREPARE: - plainsqlbuf = gwbuf_clone_transform(querybuf, - GWBUF_TYPE_PLAINSQL); - len = GWBUF_LENGTH(plainsqlbuf); - /** unnecessary if buffer includes additional terminating null */ - querystr = (char *)malloc(len+1); - memcpy(querystr, startpos, len); - memset(&querystr[len], 0, 1); - qtype = skygw_query_classifier_get_type(querystr, 0, &mysql); + qtype = query_classifier_get_type(querybuf); qtype |= QUERY_TYPE_PREPARE_STMT; break; case MYSQL_COM_STMT_EXECUTE: /** Parsing is not needed for this type of packet */ -#if defined(NOT_USED) - plainsqlbuf = gwbuf_clone_transform(querybuf, - GWBUF_TYPE_PLAINSQL); - len = GWBUF_LENGTH(plainsqlbuf); - /** unnecessary if buffer includes additional terminating null */ - querystr = (char *)malloc(len+1); - memcpy(querystr, startpos, len); - memset(&querystr[len], 0, 1); - qtype = skygw_query_classifier_get_type(querystr, 0, &mysql); -#endif qtype = QUERY_TYPE_EXEC_STMT; break; @@ -1207,7 +1177,7 @@ static int routeQuery( */ bool succp = route_session_write( router_cli_ses, - querybuf, + gwbuf_clone(querybuf), inst, packet_type, qtype); @@ -1238,7 +1208,7 @@ static int routeQuery( if (succp) { - if ((ret = slave_dcb->func.write(slave_dcb, querybuf)) == 1) + if ((ret = slave_dcb->func.write(slave_dcb, gwbuf_clone(querybuf))) == 1) { backend_ref_t* bref; @@ -1252,10 +1222,12 @@ static int routeQuery( } else { + char* query_str = modutil_get_query(querybuf); LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, "Error : Routing query \"%s\" failed.", - querystr))); + (query_str == NULL ? "not available" : query_str)))); + free(query_str); } } rses_end_locked_router_action(router_cli_ses); @@ -1296,7 +1268,7 @@ static int routeQuery( if (succp) { - if ((ret = master_dcb->func.write(master_dcb, querybuf)) == 1) + if ((ret = master_dcb->func.write(master_dcb, gwbuf_clone(querybuf))) == 1) { backend_ref_t* bref; @@ -1323,11 +1295,10 @@ static int routeQuery( } return_ret: #if defined(SS_DEBUG) - if (mysql != NULL && true) { char* canonical_query_str; - canonical_query_str = skygw_get_canonical(mysql, querystr); + canonical_query_str = skygw_get_canonical(querybuf); if (canonical_query_str != NULL) { @@ -1339,18 +1310,7 @@ return_ret: } } #endif - if (plainsqlbuf != NULL) - { - gwbuf_free(plainsqlbuf); - } - if (querystr != NULL) - { - free(querystr); - } - if (mysql != NULL) - { - skygw_query_classifier_free(mysql); - } + gwbuf_free(querybuf); return ret; } diff --git a/utils/skygw_debug.h b/utils/skygw_debug.h index 43a609a40..9ffc5e7e2 100644 --- a/utils/skygw_debug.h +++ b/utils/skygw_debug.h @@ -123,7 +123,8 @@ typedef enum skygw_chk_t { CHK_NUM_SESCMD_CUR, CHK_NUM_BACKEND, CHK_NUM_BACKEND_REF, - CHK_NUM_PREP_STMT + CHK_NUM_PREP_STMT, + CHK_NUM_PINFO } skygw_chk_t; # define STRBOOL(b) ((b) ? "true" : "false") @@ -486,6 +487,13 @@ typedef enum skygw_chk_t { "Prepared statement struct has invalid check fields"); \ } +#define CHK_PARSING_INFO(p) { \ + ss_info_dassert((p)->pi_chk_top == CHK_NUM_PINFO && \ + (p)->pi_chk_tail == CHK_NUM_PINFO, \ + "Parsing info struct has invalid check fields"); \ +} + + #if defined(SS_DEBUG) bool conn_open[10240];