summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc560
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