Commit ec9ac3fe authored by unknown's avatar unknown
Browse files

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"
parent 7a5ec760
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -137,14 +137,14 @@ enum enum_server_command
#define SERVER_QUERY_NO_GOOD_INDEX_USED 16
#define SERVER_QUERY_NO_INDEX_USED      32
/*
  The server was able to fulfill client request and open read-only
  non-scrollable cursor for the query.  This flag comes in server
  status with reply to COM_EXECUTE and COM_EXECUTE_DIRECT commands.
  The server was able to fulfill the clients request and opened a
  read-only non-scrollable cursor for a query. This flag comes
  in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
*/
#define SERVER_STATUS_CURSOR_EXISTS 64
/*
  This flag is sent with last row of read-only cursor, in reply to
  COM_FETCH command.
  This flag is sent when a read-only cursor is exhausted, in reply to
  COM_STMT_FETCH command.
*/
#define SERVER_STATUS_LAST_ROW_SENT 128
#define SERVER_STATUS_DB_DROPPED        256 /* A database was dropped */
+0 −1
Original line number Diff line number Diff line
@@ -2726,7 +2726,6 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row)
      set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
      return 1;
    }
    stmt->server_status= mysql->server_status;
    if (cli_read_binary_rows(stmt))
      return 1;
    stmt->server_status= mysql->server_status;
+1 −1
Original line number Diff line number Diff line
@@ -773,7 +773,7 @@ send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message)
}

void
send_eof(THD *thd, bool no_flush)
send_eof(THD *thd)
{
}

+37 −27
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <stdarg.h>

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,17 +363,35 @@ 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)
  {
    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 */
    /*
      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);
@@ -385,18 +404,9 @@ send_eof(THD *thd, bool no_flush)
      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));
    }
    thd->net.no_send_error= 1;
    DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
  }
  DBUG_VOID_RETURN;
}

/*
@@ -640,7 +650,7 @@ bool Protocol::send_fields(List<Item> *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:
+1 −1
Original line number Diff line number Diff line
@@ -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);
Loading