From ec9ac3fe5c823b6ae7ccb0902c267b811bf732e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 16:17:10 +0400 Subject: A fix and a test case for Bug#10794 "mysql_stmt_attr_set no open cursor after mysql_stmt_execute" + post-review fixes. The bug was caused by wrong flags in stmt->server_status on the client side: if there was no cursor, the server didn't send server_status flags to the client, and the old flags were used to set up the fetch function of a statement. Consequently, stmt_read_row_from_cursor was used when there was no cursor. The fix fixes the server to always send server flags to the client. include/mysql_com.h: Update stale comments. libmysql/libmysql.c: Remove an extra assignment. libmysqld/lib_sql.cc: Update to correspond to the changed signature of send_eof sql/protocol.cc: Actual fix for bug#10794: create a function that writes the eof packet to network and use it from send_fields. We need to send a full eof packet from send_fields to inform the client about the cursor status (that there is no cursor in this case). sql/protocol.h: Remove an unused parameter for send_eof. tests/mysql_client_test.c: A test case for Bug#10794 "mysql_stmt_attr_set no open cursor after mysql_stmt_execute" --- sql/protocol.cc | 64 +++++++++++++++++++++++++++++++++------------------------ sql/protocol.h | 2 +- 2 files changed, 38 insertions(+), 28 deletions(-) (limited to 'sql') diff --git a/sql/protocol.cc b/sql/protocol.cc index 1c399a89a99..ade94a483a8 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -28,6 +28,7 @@ #include static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024; +static void write_eof_packet(THD *thd, NET *net); #ifndef EMBEDDED_LIBRARY bool Protocol::net_store_data(const char *from, uint length) @@ -362,43 +363,52 @@ static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ */ void -send_eof(THD *thd, bool no_flush) +send_eof(THD *thd) { NET *net= &thd->net; DBUG_ENTER("send_eof"); if (net->vio != 0 && !net->no_send_eof) { - if (thd->client_capabilities & CLIENT_PROTOCOL_41) - { - uchar buff[5]; - /* Don't send warn count during SP execution, as the warn_list - is cleared between substatements, and mysqltest gets confused */ - uint tmp= (thd->spcont ? 0 : min(thd->total_warn_count, 65535)); - buff[0]=254; - int2store(buff+1, tmp); - /* - The following test should never be true, but it's better to do it - because if 'is_fatal_error' is set the server is not going to execute - other queries (see the if test in dispatch_command / COM_QUERY) - */ - if (thd->is_fatal_error) - thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; - int2store(buff+3, thd->server_status); - VOID(my_net_write(net,(char*) buff,5)); - VOID(net_flush(net)); - } - else - { - VOID(my_net_write(net,eof_buff,1)); - if (!no_flush) - VOID(net_flush(net)); - } + write_eof_packet(thd, net); + VOID(net_flush(net)); thd->net.no_send_error= 1; DBUG_PRINT("info", ("EOF sent, so no more error sending allowed")); } DBUG_VOID_RETURN; } + +/* + Format EOF packet according to the current protocol and + write it to the network output buffer. +*/ + +static void write_eof_packet(THD *thd, NET *net) +{ + if (thd->client_capabilities & CLIENT_PROTOCOL_41) + { + uchar buff[5]; + /* + Don't send warn count during SP execution, as the warn_list + is cleared between substatements, and mysqltest gets confused + */ + uint tmp= (thd->spcont ? 0 : min(thd->total_warn_count, 65535)); + buff[0]= 254; + int2store(buff+1, tmp); + /* + The following test should never be true, but it's better to do it + because if 'is_fatal_error' is set the server is not going to execute + other queries (see the if test in dispatch_command / COM_QUERY) + */ + if (thd->is_fatal_error) + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; + int2store(buff+3, thd->server_status); + VOID(my_net_write(net, (char*) buff, 5)); + } + else + VOID(my_net_write(net, eof_buff, 1)); +} + /* Please client to send scrambled_password in old format. SYNOPSYS @@ -640,7 +650,7 @@ bool Protocol::send_fields(List *list, uint flags) } if (flags & SEND_EOF) - my_net_write(&thd->net, eof_buff, 1); + write_eof_packet(thd, &thd->net); DBUG_RETURN(prepare_for_send(list)); err: diff --git a/sql/protocol.h b/sql/protocol.h index 5b402cb2669..2717d2258fa 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -179,7 +179,7 @@ void net_printf_error(THD *thd, uint sql_errno, ...); void net_send_error(THD *thd, uint sql_errno=0, const char *err=0); void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, const char *info=0); -void send_eof(THD *thd, bool no_flush=0); +void send_eof(THD *thd); bool send_old_password_request(THD *thd); char *net_store_length(char *packet,uint length); char *net_store_data(char *to,const char *from, uint length); -- cgit v1.2.1