diff --git a/query_classifier/query_classifier.cc b/query_classifier/query_classifier.cc index d722c2b16..4e3befaa3 100644 --- a/query_classifier/query_classifier.cc +++ b/query_classifier/query_classifier.cc @@ -544,7 +544,8 @@ static skygw_query_type_t resolve_query_type( { type |= QUERY_TYPE_WRITE; - if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) + if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE && + lex->sql_command == SQLCOM_CREATE_TABLE) { type |= QUERY_TYPE_CREATE_TMP_TABLE; } @@ -870,7 +871,6 @@ char* skygw_query_classifier_get_stmtname( } /** - * Finds the head of the list of tables affected by the current select statement. * @param thd Pointer to a valid THD * @return Pointer to the head of the TABLE_LIST chain or NULL in case of an error @@ -908,7 +908,6 @@ char** skygw_get_table_names(GWBUF* querybuf,int* tblsize) MYSQL* mysql; THD* thd; TABLE_LIST* tbl; - SELECT_LEX*slx; int i = 0, currtblsz = 0; char**tables,**tmp; @@ -975,7 +974,78 @@ char** skygw_get_table_names(GWBUF* querybuf,int* tblsize) *tblsize = i; return tables; } +/** + * Extract the name of the created table. + * @param querybuf Buffer to use. + * @return A pointer to the name if a table was created, otherwise NULL + */ +char* skygw_get_created_table_name(GWBUF* querybuf) +{ + parsing_info_t* pi; + MYSQL* mysql; + THD* thd; + if (!GWBUF_IS_PARSED(querybuf)) + { + return NULL; + } + pi = (parsing_info_t *)gwbuf_get_buffer_object_data(querybuf, + GWBUF_PARSING_INFO); + + if (pi == NULL) + { + return NULL; + } + + if ((mysql = (MYSQL *)pi->pi_handle) == NULL || + (thd = (THD *)mysql->thd) == NULL) + { + ss_dassert(mysql != NULL && + thd != NULL); + return NULL; + } + + if(thd->lex->create_last_non_select_table && + thd->lex->create_last_non_select_table->table_name){ + char* name = strdup(thd->lex->create_last_non_select_table->table_name); + return name; + }else{ + return NULL; + } + +} +/** + * Checks whether the buffer contains a DROP TABLE... query. + * @param querybuf Buffer to inspect + * @return true if it contains the query otherwise false + */ +bool is_drop_table_query(GWBUF* querybuf) +{ + parsing_info_t* pi; + MYSQL* mysql; + THD* thd; + + if (!GWBUF_IS_PARSED(querybuf)) + { + return false; + } + pi = (parsing_info_t *)gwbuf_get_buffer_object_data(querybuf, + GWBUF_PARSING_INFO); + if (pi == NULL) + { + return false; + } + + if ((mysql = (MYSQL *)pi->pi_handle) == NULL || + (thd = (THD *)mysql->thd) == NULL) + { + ss_dassert(mysql != NULL && + thd != NULL); + return false; + } + + return thd->lex->sql_command == SQLCOM_DROP_TABLE; +} /* * Replace user-provided literals with question marks. Return a copy of the diff --git a/query_classifier/query_classifier.h b/query_classifier/query_classifier.h index 10098ff14..ccf08a6ea 100644 --- a/query_classifier/query_classifier.h +++ b/query_classifier/query_classifier.h @@ -74,6 +74,8 @@ skygw_query_type_t query_classifier_get_type(GWBUF* querybuf); /** Free THD context and close MYSQL */ char* skygw_query_classifier_get_stmtname(MYSQL* mysql); +char* skygw_get_created_table_name(GWBUF* querybuf); +bool is_drop_table_query(GWBUF* querybuf); void* skygw_get_affected_tables(void* thdp); char** skygw_get_table_names(GWBUF* querybuf,int* tblsize); char* skygw_get_canonical(GWBUF* querybuf); diff --git a/server/modules/routing/readwritesplit/readwritesplit.c b/server/modules/routing/readwritesplit/readwritesplit.c index aca14218d..93fd3fd36 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.c +++ b/server/modules/routing/readwritesplit/readwritesplit.c @@ -287,6 +287,9 @@ static int hashcmpfun (void *, void *); static int hashkeyfun( void* key) { + if(key == NULL){ + return 0; + } unsigned int hash = 0,c = 0; char* ptr = (char*)key; while((c = *ptr++)){ @@ -1246,7 +1249,6 @@ static int routeQuery( HASHTABLE* h; MYSQL_session* data; size_t len; - MYSQL* mysql = NULL; route_target_t route_target; @@ -1541,40 +1543,35 @@ static int routeQuery( } target_dcb = master_dcb; } - /** Lock router session */ - /*if (!rses_begin_locked_router_action(router_cli_ses)) - { - goto return_ret; - } */ + /** * If query is of type QUERY_TYPE_CREATE_TMP_TABLE then find out * the database and table name, create a hashvalue and * add it to the router client session's property. If property - * doesn't exist then create it first. + * doesn't exist then create it first. If the query is DROP TABLE... + * then see if it targets a temporary table and remove it from the hashtable + * if it does. */ - - if(QUERY_IS_TYPE(qtype, QUERY_TYPE_CREATE_TMP_TABLE) || - packet_type == MYSQL_COM_DROP_DB){ - - tbl = skygw_get_table_names(querybuf,&tsize); - - if(tsize == 1 && tbl[0]) - { /**One valid table created*/ - - klen = strlen(dbname) + strlen(tbl[0]) + 2; + + if(QUERY_IS_TYPE(qtype, QUERY_TYPE_CREATE_TMP_TABLE)){ + + bool is_temp = true; + char* tblname = NULL; + + tblname = skygw_get_created_table_name(querybuf); + if(tblname && strlen(tblname) > 0){ + klen = strlen(dbname) + strlen(tblname) + 2; hkey = calloc(klen,sizeof(char)); strcpy(hkey,dbname); strcat(hkey,"."); - strcat(hkey,tbl[0]); + strcat(hkey,tblname); + }else{ + hkey = NULL; + } - } - if(QUERY_IS_TYPE(qtype, QUERY_TYPE_CREATE_TMP_TABLE)){ - - bool is_temp = true; - if(rses_prop_tmp == NULL){ if((rses_prop_tmp = (rses_property_t*)calloc(1,sizeof(rses_property_t)))){ @@ -1603,7 +1600,7 @@ static int routeQuery( } - if( + if( hkey && hashtable_add( rses_prop_tmp->rses_prop_data.temp_tables, (void *)hkey, @@ -1616,40 +1613,51 @@ static int routeQuery( "Temporary table conflict in hashtable: %s",hkey))); } + #if defined(SS_DEBUG) - bool retkey = hashtable_fetch( - rses_prop_tmp->rses_prop_data.temp_tables, + bool retkey = hashtable_fetch(rses_prop_tmp->rses_prop_data.temp_tables, hkey); - if(retkey){ - LOGIF(LT, (skygw_log_write( - LOGFILE_TRACE, - "Temporary table added: %s",hkey))); - } + if(retkey) + { + LOGIF(LT, (skygw_log_write(LOGFILE_TRACE, + "Temporary table added: %s",hkey))); + } #endif - + free(hkey); } /**Check if DROP TABLE... targets a temporary table*/ - if(packet_type == MYSQL_COM_DROP_DB) + if(is_drop_table_query(querybuf)) { - if(rses_prop_tmp && rses_prop_tmp->rses_prop_data.temp_tables) - { - hashtable_delete(rses_prop_tmp->rses_prop_data.temp_tables, (void *)hkey); - } - } - - free(hkey); - if(tsize > 0) - { + tbl = skygw_get_table_names(querybuf,&tsize); + for(i = 0;irses_prop_data.temp_tables) + { + if(hashtable_delete(rses_prop_tmp->rses_prop_data.temp_tables, (void *)hkey)) + { + LOGIF(LT, (skygw_log_write(LOGFILE_TRACE, + "Temporary table dropped: %s",hkey))); + } + } + free(tbl[i]); + free(hkey); } free(tbl); - } - } + } + + if (master_dcb == NULL) {