diff options
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r-- | sql/sql_parse.cc | 560 |
1 files changed, 454 insertions, 106 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 53295a7ccfd..7c50e4ed680 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -92,6 +92,7 @@ #include "transaction.h" #include "sql_audit.h" #include "sql_prepare.h" +#include "sql_cte.h" #include "debug_sync.h" #include "probes_mysql.h" #include "set_var.h" @@ -110,7 +111,7 @@ #include "wsrep_thd.h" static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, - Parser_state *parser_state); + Parser_state *parser_state, bool is_next_command); /** @defgroup Runtime_Environment Runtime Environment @@ -118,8 +119,6 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, */ /* Used in error handling only */ -#define SP_TYPE_STRING(LP) \ - ((LP)->sphead->m_type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE") #define SP_COM_STRING(LP) \ ((LP)->sql_command == SQLCOM_CREATE_SPFUNCTION || \ (LP)->sql_command == SQLCOM_ALTER_FUNCTION || \ @@ -136,38 +135,263 @@ static bool check_rename_table(THD *, TABLE_LIST *, TABLE_LIST *); const char *any_db="*any*"; // Special symbol for check_access -const LEX_STRING command_name[]={ - { C_STRING_WITH_LEN("Sleep") }, - { C_STRING_WITH_LEN("Quit") }, - { C_STRING_WITH_LEN("Init DB") }, - { C_STRING_WITH_LEN("Query") }, - { C_STRING_WITH_LEN("Field List") }, - { C_STRING_WITH_LEN("Create DB") }, - { C_STRING_WITH_LEN("Drop DB") }, - { C_STRING_WITH_LEN("Refresh") }, - { C_STRING_WITH_LEN("Shutdown") }, - { C_STRING_WITH_LEN("Statistics") }, - { C_STRING_WITH_LEN("Processlist") }, - { C_STRING_WITH_LEN("Connect") }, - { C_STRING_WITH_LEN("Kill") }, - { C_STRING_WITH_LEN("Debug") }, - { C_STRING_WITH_LEN("Ping") }, - { C_STRING_WITH_LEN("Time") }, - { C_STRING_WITH_LEN("Delayed insert") }, - { C_STRING_WITH_LEN("Change user") }, - { C_STRING_WITH_LEN("Binlog Dump") }, - { C_STRING_WITH_LEN("Table Dump") }, - { C_STRING_WITH_LEN("Connect Out") }, - { C_STRING_WITH_LEN("Register Slave") }, - { C_STRING_WITH_LEN("Prepare") }, - { C_STRING_WITH_LEN("Execute") }, - { C_STRING_WITH_LEN("Long Data") }, - { C_STRING_WITH_LEN("Close stmt") }, - { C_STRING_WITH_LEN("Reset stmt") }, - { C_STRING_WITH_LEN("Set option") }, - { C_STRING_WITH_LEN("Fetch") }, - { C_STRING_WITH_LEN("Daemon") }, - { C_STRING_WITH_LEN("Error") } // Last command number +const LEX_STRING command_name[257]={ + { C_STRING_WITH_LEN("Sleep") }, //0 + { C_STRING_WITH_LEN("Quit") }, //1 + { C_STRING_WITH_LEN("Init DB") }, //2 + { C_STRING_WITH_LEN("Query") }, //3 + { C_STRING_WITH_LEN("Field List") }, //4 + { C_STRING_WITH_LEN("Create DB") }, //5 + { C_STRING_WITH_LEN("Drop DB") }, //6 + { C_STRING_WITH_LEN("Refresh") }, //7 + { C_STRING_WITH_LEN("Shutdown") }, //8 + { C_STRING_WITH_LEN("Statistics") }, //9 + { C_STRING_WITH_LEN("Processlist") }, //10 + { C_STRING_WITH_LEN("Connect") }, //11 + { C_STRING_WITH_LEN("Kill") }, //12 + { C_STRING_WITH_LEN("Debug") }, //13 + { C_STRING_WITH_LEN("Ping") }, //14 + { C_STRING_WITH_LEN("Time") }, //15 + { C_STRING_WITH_LEN("Delayed insert") }, //16 + { C_STRING_WITH_LEN("Change user") }, //17 + { C_STRING_WITH_LEN("Binlog Dump") }, //18 + { C_STRING_WITH_LEN("Table Dump") }, //19 + { C_STRING_WITH_LEN("Connect Out") }, //20 + { C_STRING_WITH_LEN("Register Slave") }, //21 + { C_STRING_WITH_LEN("Prepare") }, //22 + { C_STRING_WITH_LEN("Execute") }, //23 + { C_STRING_WITH_LEN("Long Data") }, //24 + { C_STRING_WITH_LEN("Close stmt") }, //25 + { C_STRING_WITH_LEN("Reset stmt") }, //26 + { C_STRING_WITH_LEN("Set option") }, //27 + { C_STRING_WITH_LEN("Fetch") }, //28 + { C_STRING_WITH_LEN("Daemon") }, //29 + { 0, 0 }, //30 + { 0, 0 }, //31 + { 0, 0 }, //32 + { 0, 0 }, //33 + { 0, 0 }, //34 + { 0, 0 }, //35 + { 0, 0 }, //36 + { 0, 0 }, //37 + { 0, 0 }, //38 + { 0, 0 }, //39 + { 0, 0 }, //40 + { 0, 0 }, //41 + { 0, 0 }, //42 + { 0, 0 }, //43 + { 0, 0 }, //44 + { 0, 0 }, //45 + { 0, 0 }, //46 + { 0, 0 }, //47 + { 0, 0 }, //48 + { 0, 0 }, //49 + { 0, 0 }, //50 + { 0, 0 }, //51 + { 0, 0 }, //52 + { 0, 0 }, //53 + { 0, 0 }, //54 + { 0, 0 }, //55 + { 0, 0 }, //56 + { 0, 0 }, //57 + { 0, 0 }, //58 + { 0, 0 }, //59 + { 0, 0 }, //60 + { 0, 0 }, //61 + { 0, 0 }, //62 + { 0, 0 }, //63 + { 0, 0 }, //64 + { 0, 0 }, //65 + { 0, 0 }, //66 + { 0, 0 }, //67 + { 0, 0 }, //68 + { 0, 0 }, //69 + { 0, 0 }, //70 + { 0, 0 }, //71 + { 0, 0 }, //72 + { 0, 0 }, //73 + { 0, 0 }, //74 + { 0, 0 }, //75 + { 0, 0 }, //76 + { 0, 0 }, //77 + { 0, 0 }, //78 + { 0, 0 }, //79 + { 0, 0 }, //80 + { 0, 0 }, //81 + { 0, 0 }, //82 + { 0, 0 }, //83 + { 0, 0 }, //84 + { 0, 0 }, //85 + { 0, 0 }, //86 + { 0, 0 }, //87 + { 0, 0 }, //88 + { 0, 0 }, //89 + { 0, 0 }, //90 + { 0, 0 }, //91 + { 0, 0 }, //92 + { 0, 0 }, //93 + { 0, 0 }, //94 + { 0, 0 }, //95 + { 0, 0 }, //96 + { 0, 0 }, //97 + { 0, 0 }, //98 + { 0, 0 }, //99 + { 0, 0 }, //100 + { 0, 0 }, //101 + { 0, 0 }, //102 + { 0, 0 }, //103 + { 0, 0 }, //104 + { 0, 0 }, //105 + { 0, 0 }, //106 + { 0, 0 }, //107 + { 0, 0 }, //108 + { 0, 0 }, //109 + { 0, 0 }, //110 + { 0, 0 }, //111 + { 0, 0 }, //112 + { 0, 0 }, //113 + { 0, 0 }, //114 + { 0, 0 }, //115 + { 0, 0 }, //116 + { 0, 0 }, //117 + { 0, 0 }, //118 + { 0, 0 }, //119 + { 0, 0 }, //120 + { 0, 0 }, //121 + { 0, 0 }, //122 + { 0, 0 }, //123 + { 0, 0 }, //124 + { 0, 0 }, //125 + { 0, 0 }, //126 + { 0, 0 }, //127 + { 0, 0 }, //128 + { 0, 0 }, //129 + { 0, 0 }, //130 + { 0, 0 }, //131 + { 0, 0 }, //132 + { 0, 0 }, //133 + { 0, 0 }, //134 + { 0, 0 }, //135 + { 0, 0 }, //136 + { 0, 0 }, //137 + { 0, 0 }, //138 + { 0, 0 }, //139 + { 0, 0 }, //140 + { 0, 0 }, //141 + { 0, 0 }, //142 + { 0, 0 }, //143 + { 0, 0 }, //144 + { 0, 0 }, //145 + { 0, 0 }, //146 + { 0, 0 }, //147 + { 0, 0 }, //148 + { 0, 0 }, //149 + { 0, 0 }, //150 + { 0, 0 }, //151 + { 0, 0 }, //152 + { 0, 0 }, //153 + { 0, 0 }, //154 + { 0, 0 }, //155 + { 0, 0 }, //156 + { 0, 0 }, //157 + { 0, 0 }, //158 + { 0, 0 }, //159 + { 0, 0 }, //160 + { 0, 0 }, //161 + { 0, 0 }, //162 + { 0, 0 }, //163 + { 0, 0 }, //164 + { 0, 0 }, //165 + { 0, 0 }, //166 + { 0, 0 }, //167 + { 0, 0 }, //168 + { 0, 0 }, //169 + { 0, 0 }, //170 + { 0, 0 }, //171 + { 0, 0 }, //172 + { 0, 0 }, //173 + { 0, 0 }, //174 + { 0, 0 }, //175 + { 0, 0 }, //176 + { 0, 0 }, //177 + { 0, 0 }, //178 + { 0, 0 }, //179 + { 0, 0 }, //180 + { 0, 0 }, //181 + { 0, 0 }, //182 + { 0, 0 }, //183 + { 0, 0 }, //184 + { 0, 0 }, //185 + { 0, 0 }, //186 + { 0, 0 }, //187 + { 0, 0 }, //188 + { 0, 0 }, //189 + { 0, 0 }, //190 + { 0, 0 }, //191 + { 0, 0 }, //192 + { 0, 0 }, //193 + { 0, 0 }, //194 + { 0, 0 }, //195 + { 0, 0 }, //196 + { 0, 0 }, //197 + { 0, 0 }, //198 + { 0, 0 }, //199 + { 0, 0 }, //200 + { 0, 0 }, //201 + { 0, 0 }, //202 + { 0, 0 }, //203 + { 0, 0 }, //204 + { 0, 0 }, //205 + { 0, 0 }, //206 + { 0, 0 }, //207 + { 0, 0 }, //208 + { 0, 0 }, //209 + { 0, 0 }, //210 + { 0, 0 }, //211 + { 0, 0 }, //212 + { 0, 0 }, //213 + { 0, 0 }, //214 + { 0, 0 }, //215 + { 0, 0 }, //216 + { 0, 0 }, //217 + { 0, 0 }, //218 + { 0, 0 }, //219 + { 0, 0 }, //220 + { 0, 0 }, //221 + { 0, 0 }, //222 + { 0, 0 }, //223 + { 0, 0 }, //224 + { 0, 0 }, //225 + { 0, 0 }, //226 + { 0, 0 }, //227 + { 0, 0 }, //228 + { 0, 0 }, //229 + { 0, 0 }, //230 + { 0, 0 }, //231 + { 0, 0 }, //232 + { 0, 0 }, //233 + { 0, 0 }, //234 + { 0, 0 }, //235 + { 0, 0 }, //236 + { 0, 0 }, //237 + { 0, 0 }, //238 + { 0, 0 }, //239 + { 0, 0 }, //240 + { 0, 0 }, //241 + { 0, 0 }, //242 + { 0, 0 }, //243 + { 0, 0 }, //244 + { 0, 0 }, //245 + { 0, 0 }, //246 + { 0, 0 }, //247 + { 0, 0 }, //248 + { 0, 0 }, //249 + { 0, 0 }, //250 + { 0, 0 }, //251 + { 0, 0 }, //252 + { 0, 0 }, //253 + { C_STRING_WITH_LEN("Com_multi") }, //254 + { C_STRING_WITH_LEN("Error") } // Last command number 255 }; const char *xa_state_names[]={ @@ -269,7 +493,7 @@ void init_update_queries(void) memset(server_command_flags, 0, sizeof(server_command_flags)); server_command_flags[COM_STATISTICS]= CF_SKIP_QUERY_ID | CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; - server_command_flags[COM_PING]= CF_SKIP_QUERY_ID | CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; + server_command_flags[COM_PING]= CF_SKIP_QUERY_ID | CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK | CF_NO_COM_MULTI; server_command_flags[COM_QUIT]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_PROCESS_INFO]= CF_SKIP_WSREP_CHECK; @@ -278,6 +502,10 @@ void init_update_queries(void) server_command_flags[COM_SLEEP]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_TIME]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_END]= CF_SKIP_WSREP_CHECK; + for (uint i= COM_MDB_GAP_BEG; i <= COM_MDB_GAP_END; i++) + { + server_command_flags[i]= CF_SKIP_WSREP_CHECK; + } /* COM_QUERY, COM_SET_OPTION and COM_STMT_XXX are allowed to pass the early @@ -290,6 +518,7 @@ void init_update_queries(void) server_command_flags[COM_STMT_RESET]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_EXECUTE]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_SEND_LONG_DATA]= CF_SKIP_WSREP_CHECK; + server_command_flags[COM_MULTI]= CF_SKIP_WSREP_CHECK | CF_NO_COM_MULTI; /* Initialize the sql command flags array. */ memset(sql_command_flags, 0, sizeof(sql_command_flags)); @@ -673,7 +902,7 @@ void execute_init_command(THD *thd, LEX_STRING *init_command, */ save_vio= thd->net.vio; thd->net.vio= 0; - dispatch_command(COM_QUERY, thd, buf, len); + dispatch_command(COM_QUERY, thd, buf, len, FALSE, FALSE); thd->client_capabilities= save_client_capabilities; thd->net.vio= save_vio; @@ -791,7 +1020,7 @@ static void handle_bootstrap_impl(THD *thd) break; } - mysql_parse(thd, thd->query(), length, &parser_state); + mysql_parse(thd, thd->query(), length, &parser_state, FALSE); bootstrap_error= thd->is_error(); thd->protocol->end_statement(); @@ -889,6 +1118,23 @@ void cleanup_items(Item *item) DBUG_VOID_RETURN; } +static enum enum_server_command fetch_command(THD *thd, char *packet) +{ + enum enum_server_command + command= (enum enum_server_command) (uchar) packet[0]; + NET *net= &thd->net; + DBUG_ENTER("fetch_command"); + + if (command >= COM_END || + (command >= COM_MDB_GAP_BEG && command <= COM_MDB_GAP_END)) + command= COM_END; // Wrong command + + DBUG_PRINT("info",("Command on %s = %d (%s)", + vio_description(net->vio), command, + command_name[command].str)); + DBUG_RETURN(command); +} + #ifndef EMBEDDED_LIBRARY @@ -1077,14 +1323,8 @@ bool do_command(THD *thd) /* Do not rely on my_net_read, extra safety against programming errors. */ packet[packet_length]= '\0'; /* safety */ - command= (enum enum_server_command) (uchar) packet[0]; - if (command >= COM_END) - command= COM_END; // Wrong command - - DBUG_PRINT("info",("Command on %s = %d (%s)", - vio_description(net->vio), command, - command_name[command].str)); + command= fetch_command(thd, packet); #ifdef WITH_WSREP /* @@ -1110,7 +1350,8 @@ bool do_command(THD *thd) DBUG_ASSERT(packet_length); DBUG_ASSERT(!thd->apc_target.is_enabled()); - return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1)); + return_value= dispatch_command(command, thd, packet+1, + (uint) (packet_length-1), FALSE, FALSE); #ifdef WITH_WSREP if (WSREP(thd)) { @@ -1128,7 +1369,7 @@ bool do_command(THD *thd) my_charset_latin1.csname); } return_value= dispatch_command(command, thd, thd->wsrep_retry_query, - thd->wsrep_retry_query_len); + thd->wsrep_retry_query_len, FALSE, FALSE); thd->variables.character_set_client = current_charset; } @@ -1220,6 +1461,44 @@ static my_bool deny_updates_if_read_only_option(THD *thd, /** + check COM_MULTI packet + + @param thd thread handle + @param packet pointer on the packet of commands + @param packet_length length of this packet + + @retval 0 - Error + @retval # - Number of commands in the batch +*/ + +uint maria_multi_check(THD *thd, char *packet, uint packet_length) +{ + uint counter= 0; + DBUG_ENTER("maria_multi_check"); + while (packet_length) + { + // length of command + 3 bytes where that length was stored + uint subpacket_length= (uint3korr(packet) + 3); + DBUG_PRINT("info", ("sub-packet length: %d command: %x", + subpacket_length, packet[3])); + + if (subpacket_length == 3 || + subpacket_length > packet_length) + { + my_message(ER_UNKNOWN_COM_ERROR, ER_THD(thd, ER_UNKNOWN_COM_ERROR), + MYF(0)); + DBUG_RETURN(0); + } + + counter++; + packet+= subpacket_length; + packet_length-= subpacket_length; + } + DBUG_RETURN(counter); +} + + +/** Perform one connection-level (COM_XXXX) command. @param command type of command to perform @@ -1228,6 +1507,8 @@ static my_bool deny_updates_if_read_only_option(THD *thd, @param packet_length length of packet + 1 (to show that data is null-terminated) except for COM_SLEEP, where it can be zero. + @param is_com_multi recursive call from COM_MULTI + @param is_next_command there will be more command in the COM_MULTI batch @todo set thd->lex->sql_command to SQLCOM_END here. @@ -1241,15 +1522,24 @@ static my_bool deny_updates_if_read_only_option(THD *thd, COM_QUIT/COM_SHUTDOWN */ bool dispatch_command(enum enum_server_command command, THD *thd, - char* packet, uint packet_length) + char* packet, uint packet_length, bool is_com_multi, + bool is_next_command) { NET *net= &thd->net; bool error= 0; bool do_end_of_statement= true; DBUG_ENTER("dispatch_command"); - DBUG_PRINT("info", ("command: %d", command)); + DBUG_PRINT("info", ("command: %d %s", command, + (command_name[command].str != 0 ? + command_name[command].str : + "<?>"))); + bool drop_more_results= 0; + + if (!is_com_multi) + inc_thread_running(); - inc_thread_running(); + /* keep it withing 1 byte */ + compile_time_assert(COM_END == 255); #ifdef WITH_WSREP if (WSREP(thd)) @@ -1339,6 +1629,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, beginning of each command. */ thd->server_status&= ~SERVER_STATUS_CLEAR_SET; + if (is_next_command) + { + drop_more_results= !MY_TEST(thd->server_status & + SERVER_MORE_RESULTS_EXISTS); + thd->server_status|= SERVER_MORE_RESULTS_EXISTS; + } + switch (command) { case COM_INIT_DB: { @@ -1487,9 +1784,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; if (WSREP_ON) - wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); + wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state, + is_next_command); else - mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); + mysql_parse(thd, thd->query(), thd->query_length(), &parser_state, + is_next_command); while (!thd->killed && (parser_state.m_lip.found_semicolon != NULL) && ! thd->is_error()) @@ -1574,9 +1873,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* TODO: set thd->lex->sql_command to SQLCOM_END here */ if (WSREP_ON) - wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); + wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state, + is_next_command); else - mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); + mysql_parse(thd, beginning_of_next_stmt, length, &parser_state, + is_next_command); } @@ -1628,6 +1929,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } packet= arg_end + 1; thd->reset_for_next_command(); + // thd->reset_for_next_command reset state => restore it + if (is_next_command) + thd->server_status|= SERVER_MORE_RESULTS_EXISTS; lex_start(thd); /* Must be before we init the table list. */ if (lower_case_table_names) @@ -1906,6 +2210,66 @@ bool dispatch_command(enum enum_server_command command, THD *thd, general_log_print(thd, command, NullS); my_eof(thd); break; + case COM_MULTI: + { + uint counter; + uint current_com= 0; + DBUG_ASSERT(!is_com_multi); + if (!(thd->client_capabilities & CLIENT_MULTI_RESULTS)) + { + /* The client does not support multiple result sets being sent back */ + my_error(ER_COMMULTI_BADCONTEXT, MYF(0)); + break; + } + + if (!(counter= maria_multi_check(thd, packet, packet_length))) + break; + + { + /* We have to store next length because it will be destroyed by '\0' */ + uint next_subpacket_length= uint3korr(packet); + unsigned char *readbuff= net->buff; + + if (net_allocate_new_packet(net, thd, MYF(0))) + break; + + while (packet_length) + { + current_com++; + uint subpacket_length= next_subpacket_length + 3; + if (subpacket_length < packet_length) + next_subpacket_length= uint3korr(packet + subpacket_length); + /* safety like in do_command() */ + packet[subpacket_length]= '\0'; + + enum enum_server_command subcommand= fetch_command(thd, (packet + 3)); + + if (server_command_flags[subcommand] & CF_NO_COM_MULTI) + { + my_error(ER_BAD_COMMAND_IN_MULTI, MYF(0), command_name[subcommand]); + goto com_multi_end; + } + + if (dispatch_command(subcommand, thd, packet + (1 + 3), + subpacket_length - (1 + 3), TRUE, + (current_com != counter))) + { + DBUG_ASSERT(thd->is_error()); + goto com_multi_end; + } + + DBUG_ASSERT(subpacket_length <= packet_length); + packet+= subpacket_length; + packet_length-= subpacket_length; + } + +com_multi_end: + /* release old buffer */ + DBUG_ASSERT(net->buff == net->write_pos); // nothing to send + my_free(readbuff); + } + break; + } case COM_SLEEP: case COM_CONNECT: // Impossible here case COM_TIME: // Impossible from client @@ -1942,9 +2306,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd_proc_info(thd, "updating status"); /* Finalize server status flags after executing a command. */ thd->update_server_status(); - thd->protocol->end_statement(); - query_cache_end_of_result(thd); + if (command != COM_MULTI) + { + thd->protocol->end_statement(); + query_cache_end_of_result(thd); + } } + if (drop_more_results) + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; if (!thd->is_error() && !thd->killed_errno()) mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0); @@ -1968,8 +2337,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->m_statement_psi= NULL; thd->m_digest= NULL; - dec_thread_running(); - thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory + if (!is_com_multi) + { + dec_thread_running(); + thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory + } free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); #if defined(ENABLED_PROFILING) @@ -5121,7 +5493,6 @@ end_with_restore_list: { uint namelen; char *name; - int sp_result= SP_INTERNAL_ERROR; DBUG_ASSERT(lex->sphead != 0); DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */ @@ -5132,23 +5503,12 @@ end_with_restore_list: if (check_db_name(&lex->sphead->m_db)) { my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str); - goto create_sp_error; + goto error; } if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, NULL, NULL, 0, 0)) - goto create_sp_error; - - /* - Check that a database directory with this name - exists. Design note: This won't work on virtual databases - like information_schema. - */ - if (check_db_dir_existence(lex->sphead->m_db.str)) - { - my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str); - goto create_sp_error; - } + goto error; /* Checking the drop permissions if CREATE OR REPLACE is used */ if (lex->create_info.or_replace()) @@ -5156,7 +5516,7 @@ end_with_restore_list: if (check_routine_access(thd, ALTER_PROC_ACL, lex->spname->m_db.str, lex->spname->m_name.str, lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) - goto create_sp_error; + goto error; } name= lex->sphead->name(&namelen); @@ -5168,18 +5528,17 @@ end_with_restore_list: if (udf) { my_error(ER_UDF_EXISTS, MYF(0), name); - goto create_sp_error; + goto error; } } #endif if (sp_process_definer(thd)) - goto create_sp_error; + goto error; WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) - res= (sp_result= sp_create_routine(thd, lex->sphead->m_type, lex->sphead)); - switch (sp_result) { - case SP_OK: { + if (!sp_create_routine(thd, lex->sphead->m_type, lex->sphead)) + { #ifndef NO_EMBEDDED_ACCESS_CHECKS /* only add privileges if really neccessary */ @@ -5244,31 +5603,8 @@ end_with_restore_list: } #endif - break; } - case SP_WRITE_ROW_FAILED: - my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name); - break; - case SP_BAD_IDENTIFIER: - my_error(ER_TOO_LONG_IDENT, MYF(0), name); - break; - case SP_BODY_TOO_LONG: - my_error(ER_TOO_LONG_BODY, MYF(0), name); - break; - case SP_FLD_STORE_FAILED: - my_error(ER_CANT_CREATE_SROUTINE, MYF(0), name); - break; - default: - my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name); - break; - } /* end switch */ - - /* - Capture all errors within this CASE and - clean up the environment. - */ -create_sp_error: - if (sp_result != SP_OK ) + else goto error; my_ok(thd); break; /* break super switch */ @@ -5668,6 +6004,8 @@ create_sp_error: if (check_global_access(thd, SUPER_ACL)) break; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + res= create_server(thd, &lex->server_options); break; } @@ -5679,6 +6017,8 @@ create_sp_error: if (check_global_access(thd, SUPER_ACL)) break; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + if ((error= alter_server(thd, &lex->server_options))) { DBUG_PRINT("info", ("problem altering server <%s>", @@ -5697,6 +6037,8 @@ create_sp_error: if (check_global_access(thd, SUPER_ACL)) break; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + if ((err_code= drop_server(thd, &lex->server_options))) { if (! lex->if_exists() && err_code == ER_FOREIGN_SERVER_DOESNT_EXIST) @@ -5873,6 +6215,9 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) new (thd->mem_root) Item_int(thd, (ulonglong) thd->variables.select_limit); } + if (check_dependencies_in_with_clauses(lex->with_clauses_list)) + return 1; + if (!(res= open_and_lock_tables(thd, all_tables, TRUE, 0))) { if (lex->describe) @@ -7155,7 +7500,7 @@ void mysql_init_multi_delete(LEX *lex) } static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, - Parser_state *parser_state) + Parser_state *parser_state, bool is_next_command) { #ifdef WITH_WSREP bool is_autocommit= @@ -7174,7 +7519,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query(), thd->query_length()); } - mysql_parse(thd, rawbuf, length, parser_state); + mysql_parse(thd, rawbuf, length, parser_state, is_next_command); if (WSREP(thd)) { /* wsrep BF abort in query exec phase */ @@ -7272,10 +7617,11 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, @param length Length of the query text @param[out] found_semicolon For multi queries, position of the character of the next query in the query text. + @param is_next_command there will be more command in the COM_MULTI batch */ void mysql_parse(THD *thd, char *rawbuf, uint length, - Parser_state *parser_state) + Parser_state *parser_state, bool is_next_command) { int error __attribute__((unused)); DBUG_ENTER("mysql_parse"); @@ -7299,6 +7645,8 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, */ lex_start(thd); thd->reset_for_next_command(); + if (is_next_command) + thd->server_status|= SERVER_MORE_RESULTS_EXISTS; if (query_cache_send_result_to_client(thd, rawbuf, length) <= 0) { @@ -7989,7 +8337,7 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg) @retval FALSE if all is OK @retval - TRUE if a memory allocation error occured + TRUE if a memory allocation error occurred */ bool |