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?

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.041 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.