Bug #15510 mysql_warning_count returns 0 after mysql_stmt_fetch which should warn
Submitted: 6 Dec 2005 3:15 Modified: 8 Dec 2005 23:47
Reporter: Timothy Smith Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Prepared statements Severity:S2 (Serious)
Version:5.0.17-nightly-20051120 OS:Linux (linux)
Assigned to: Jim Winstead CPU Architecture:Any

[6 Dec 2005 3:15] Timothy Smith
Description:
A query which produces a warning, when fetched via mysql_stmt_fetch(), does not produce a warning count according to mysql_warning_count().

This worked correctly in 5.0.16, but currently it returns 0 instead of the correct count.

I tested this with a recent 5.0 build from BK, on FreeBSD and Linux.

How to repeat:
Here is a test case.  When run against 5.0.16, it exits successfully with no messages.  When run against 5.0.17-bk, it gives:

$ ./b1
!!! Error (91): 
  Expected value:1
  Returned value:0
   error: Assertion failed: (0), function main, file b1.cpp, line 91.
zsh: abort (core dumped)  ./b1

// This cpp file should be compilable with:
// 	gcc -g -I ${MYSQL_DIR}/include ${THIS_FILE} ${MYSQL_DIR}/lib/libmysqlclient.a -lm -lz -lstdc++

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <string>
#include <list>
#include <iostream>
#include <sstream>

// Connection parameters
const char *MYSQL_CMD = "mysql"; // Used for table creation
const char *HOST_NAME = NULL;
const char *USER_NAME = NULL;
const char *USER_PWD = NULL;
const char *DB_NAME = "test";
const char *UNIX_SOCKET = NULL;

// use "#define M_EXPECT_EQUALS (void)" to disable data validation
typedef enum { STR, SESS, STMT } ;
#define M_EXPECT_EQUALS(X,Y,T,V) if ( X==Y ); else { \
    cout << "!!! Error (" << __LINE__ << "): " << endl \
         << "  Expected value:" << X << endl \
         << "  Returned value:" << Y << endl; \
    switch (T) { \
        case STR : cout << "   error: " << (const char *)V << endl; break;\
        case SESS: cout << "   mysql error: " << mysql_error((MYSQL*)V) << endl; break;\
        case STMT: cout << "   mysql error: " << mysql_stmt_error((MYSQL_STMT*)V) << endl; break;\
    } \
    assert( 0 ); \
} \

#include "mysql.h"

using namespace std;

// Global variables
const char *m_text;
int m_ret;
int m_count;
int m_err;
MYSQL_RES *m_result;
MYSQL_ROW m_row;

// Helper functions
inline void set_bind_attrs(MYSQL_BIND *mysql_bind, enum_field_types ext_type, void *buf, int bufsz, unsigned long *act_len, my_bool *is_null)
{
   mysql_bind->buffer_type = ext_type;
   mysql_bind->buffer = buf;
   mysql_bind->length = act_len;
   mysql_bind->is_null = is_null;
   mysql_bind->buffer_length = bufsz;
}

int main(void)
{
   MYSQL *sess_1;
   sess_1 = mysql_init( NULL ); assert(sess_1);
   sess_1 = mysql_real_connect(sess_1, HOST_NAME, USER_NAME, USER_PWD, DB_NAME, 0, UNIX_SOCKET, 0); assert(sess_1);

    // Set sql_mode to ERROR_FOR_DIVISION_BY_ZERO so that we should get
    // a warning on a division by zero
   mysql_query(sess_1, "SET SESSION sql_mode=ERROR_FOR_DIVISION_BY_ZERO");

   MYSQL_STMT *stmt_1;
   stmt_1 = mysql_stmt_init(sess_1);

   m_text = "SELECT 1 FROM DUAL WHERE 1 / 0";
   m_ret = mysql_stmt_prepare(stmt_1,m_text,strlen(m_text)); M_EXPECT_EQUALS(0,m_ret,STMT,stmt_1);

   m_count = mysql_warning_count(sess_1); M_EXPECT_EQUALS(0,m_count,0,NULL);

   MYSQL_BIND *output_1 = (MYSQL_BIND *)calloc(1, sizeof(MYSQL_BIND));
   int data_3;
   unsigned long len_3;
   my_bool null_3;
   set_bind_attrs(&output_1[0],MYSQL_TYPE_LONG,&data_3,4,&len_3,&null_3);
   m_count = mysql_warning_count(sess_1); M_EXPECT_EQUALS(0,m_count,0,NULL);

   m_ret = mysql_stmt_execute(stmt_1); M_EXPECT_EQUALS(0,m_ret,STMT,stmt_1);
   m_count = mysql_warning_count(sess_1); M_EXPECT_EQUALS(0,m_count,0,NULL);

   mysql_stmt_bind_result(stmt_1,output_1);
   m_count = mysql_warning_count(sess_1); M_EXPECT_EQUALS(0,m_count,0,NULL);

   m_ret = mysql_stmt_fetch(stmt_1); M_EXPECT_EQUALS(100,m_ret,STMT,stmt_1);

   // The previous fetch should give a "division by zero" warning.
   m_count = mysql_warning_count(sess_1); M_EXPECT_EQUALS(1,m_count,0,NULL);

   m_ret = mysql_query(sess_1,"show warnings limit 0,1"); M_EXPECT_EQUALS(0,m_ret,SESS,sess_1);
   m_result = mysql_store_result(sess_1); assert(m_result);
   m_count = mysql_num_fields(m_result);M_EXPECT_EQUALS( 3,m_count,0,NULL );
   m_row = mysql_fetch_row(m_result); M_EXPECT_EQUALS(1365,atoi(m_row[1]),STR,"Unexpected warning code"); // Message: "Division by 0"
   mysql_free_result( m_result );

   m_ret = mysql_stmt_free_result(stmt_1); M_EXPECT_EQUALS(0,m_ret,STMT,stmt_1);
   m_ret = mysql_stmt_reset(stmt_1); M_EXPECT_EQUALS(0,m_ret,STMT,stmt_1);
   m_ret = mysql_stmt_close(stmt_1); M_EXPECT_EQUALS(0,m_ret,0,NULL);
   m_ret = mysql_rollback(sess_1); M_EXPECT_EQUALS(0,m_ret,SESS,sess_1);
   mysql_close(sess_1);

   return EXIT_SUCCESS;
}

Suggested fix:
n/a
[6 Dec 2005 23:50] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/internals/33105
[7 Dec 2005 17:37] Jim Winstead
Fixed in 5.0.17.
[8 Dec 2005 23:47] Paul Dubois
Noted in 5.0.17 changelog.
[31 Oct 2008 17:34] Sheeri Cabral
I have found this bug in mysqld 5.1.24-rc-log as well.  Was it fixed in the 5.1 tree?