#At file:///Users/thek/Development/51-bug44521/ based on revid:pstoev@stripped
2935 Kristofer Pettersson 2009-07-01
Bug#44521 Prepared Statement: CALL p() - crashes: `! thd->main_da.is_sent' failed et.al.
For discussion.
Executing a stored procedure as a prepared statement can sometimes cause an
assertion in a debug build.
The reason is that the C API doesn't support multiple result sets for prepared
statements and attempting to execute a stored routine which returns multiple result
sets sometimes lead to a network error. The network error sets the diagnostic area
prematurely which later leads to the assert when an attempt is made to set a second
server state.
This patch fixes the issue by changing the scope of the error code returned by
sp_instr_stmt::execute() to include any error which happened during the execution.
An extra check is also made to make sure that the diagnostic area isn't set twice.
modified:
sql/sp_head.cc
sql/sql_parse.cc
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2009-05-30 13:32:28 +0000
+++ b/sql/sp_head.cc 2009-07-01 21:01:14 +0000
@@ -1249,7 +1249,7 @@ sp_head::execute(THD *thd)
*/
if (thd->prelocked_mode == NON_PRELOCKED)
thd->user_var_events_alloc= thd->mem_root;
-
+
err_status= i->execute(thd, &ip);
if (i->free_list)
@@ -2865,7 +2865,7 @@ sp_instr_stmt::execute(THD *thd, uint *n
if (!thd->is_error())
thd->main_da.reset_diagnostics_area();
}
- DBUG_RETURN(res);
+ DBUG_RETURN(res || thd->is_error());
}
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2009-06-05 11:23:58 +0000
+++ b/sql/sql_parse.cc 2009-07-01 21:01:14 +0000
@@ -954,6 +954,7 @@ bool dispatch_command(enum enum_server_c
char* packet, uint packet_length)
{
NET *net= &thd->net;
+ bool eof_has_been_sent= FALSE;
bool error= 0;
DBUG_ENTER("dispatch_command");
DBUG_PRINT("info",("packet: '%*.s'; command: %d", packet_length, packet, command));
@@ -1166,6 +1167,14 @@ bool dispatch_command(enum enum_server_c
case COM_STMT_EXECUTE:
{
mysqld_stmt_execute(thd, packet, packet_length);
+ /*
+ When executing a stored routine a network error may occur
+ (ER_NET_ERROR_ON_WRITE) which causes the diagnositc area
+ to be set. To avoid setting the diagnositc area twice we
+ need to remember this exception.
+ */
+ if (thd->main_da.is_sent)
+ eof_has_been_sent= TRUE;
break;
}
case COM_STMT_FETCH:
@@ -1580,8 +1589,12 @@ bool dispatch_command(enum enum_server_c
thd->mysys_var->abort= 0;
}
- net_end_statement(thd);
- query_cache_end_of_result(thd);
+ if (!eof_has_been_sent)
+ {
+ net_end_statement(thd);
+ query_cache_end_of_result(thd);
+ }
+
thd->proc_info= "closing tables";
/* Free tables */
@@ -4362,7 +4375,6 @@ create_sp_error:
thd->variables.select_limit= select_limit;
thd->server_status&= ~bits_to_be_cleared;
-
if (!res)
my_ok(thd, (ulong) (thd->row_count_func < 0 ? 0 :
thd->row_count_func));
Attachment: [text/bzr-bundle]