Bug #4184 mysql_stmt_fetch() fetches wrong MSQL_TIME values

Submitted: 17 Jun 2004 13:51 Modified: 1 Sep 2004 16:26
Reporter: Anthon Ouwendijk Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S2 (Serious)
Version:4.1.2 OS:HP/UX (HP-UX 11)
Assigned to: Konstantin Osipov CPU Architecture:Any

[17 Jun 2004 13:51] Anthon Ouwendijk
Description:
Description: This happens when the C API for prepared statements is used.
A sample C source has been included.

Queries that
 - GROUP on more than one column,
 - AND have a aggr function (max/min/avg) on a <date> column
 - AND have a DESC order on one of the group-by columns
return corrupt MYSQL_TIME values.

The following query succeeds:
    select col1, col2, MIN(<date>) group by col1, col2 order by col1<n>
The following query fails:
    select col1, col2, MIN(<date>) group by col1, col2 order by col1<n> DESC

How to repeat:
Table dump:

CREATE TABLE tdbtst180000 (
  t_empno int(11) NOT NULL default '0',
  t_projno varchar(6) collate latin1_bin NOT NULL default '',
  t_emstdate date NOT NULL default '0000-00-00',
  t_emendate date NOT NULL default '0000-00-00',
  PRIMARY KEY  (t_empno,t_projno,t_emstdate,t_emendate),
  UNIQUE KEY tdbtst180000$idx2 (t_projno,t_empno,t_emstdate,t_emendate)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;

INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (10, 'AD3100', '1982-01-01', '1982-07-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (10, 'MA2100', '1982-01-01', '1982-11-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (10, 'MA2110', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (20, 'PL2100', '1982-01-01', '1982-09-15');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (30, 'IF1000', '1982-06-01', '1983-01-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (30, 'IF2000', '1982-01-01', '1983-01-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (50, 'OP1000', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (50, 'OP2010', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (70, 'AD3110', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (90, 'OP1010', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (100, 'OP2010', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (110, 'MA2100', '1982-01-01', '1982-03-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (130, 'IF1000', '1982-01-01', '1982-10-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (140, 'IF1000', '1982-10-01', '1983-01-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (140, 'IF2000', '1982-01-01', '1982-03-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (150, 'MA2112', '1982-01-01', '1982-07-15');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (160, 'MA2113', '1982-07-15', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (170, 'MA2112', '1982-01-01', '1983-06-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (170, 'MA2113', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (180, 'MA2113', '1982-04-01', '1982-06-15');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (190, 'MA2112', '1982-02-01', '1982-10-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (200, 'MA2111', '1982-01-01', '1982-06-15');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (210, 'MA2113', '1982-10-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (220, 'MA2111', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (230, 'AD3111', '1982-01-01', '1982-03-15');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (240, 'AD3111', '1982-02-15', '1982-09-15');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (250, 'AD3112', '1982-01-01', '1982-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (260, 'AD3113', '1982-06-15', '1982-07-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (270, 'AD3113', '1982-03-01', '1982-04-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (280, 'OP1010', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (290, 'OP1010', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (300, 'OP1010', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (310, 'OP1010', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (320, 'OP2011', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (330, 'OP2012', '1982-01-01', '1983-02-01');
INSERT INTO tdbtst180000 (t_empno, t_projno, t_emstdate, t_emendate) VALUES (340, 'OP2013', '1982-01-01', '1983-02-01');

Reproducing C-code:

#include <stdlib.h>
#include <mysql.h>

typedef enum {
	BUG_UNKNOWN	= -1,	/* Error occurred */
	BUG_SOLVED	= 0,
	BUG_PRESENT	= 1,
} BugStatus;

char * str_bug_stat( BugStatus bugstat )
{
	if ( bugstat == BUG_PRESENT  ) {
		return "Bug still present";
	} else if ( bugstat == BUG_SOLVED ) {
		return "Bug solved";
	}
	return "Status UNKNOWN (or error occurred)";
}

BugStatus do_the_bug_test( MYSQL * mysql, char ** desc )
{
	MYSQL_STMT *	stmt;

	/* Bind data */
	MYSQL_BIND	bind[3];
	unsigned long	length[2];
	my_bool		is_null[2];
	int		int_data;
	MYSQL_TIME	time_data;
	char		str_data[64];

	char		query[256];
	int		rows = 0;

	*desc =
	"MySQL Bug Baan-040616	\"SELECT col1, col2, fun(<date>) group by col1, col2 order by col<n> DESC\" returns corrupt <date>\n"
	"			ok:	select col1, col2, MIN(<date>) group by col1, col2 order by col1<n>\n"
	"			err:	select col1, col2, MIN(<date>) group by col1, col2 order by col1<n> DESC\n";

	if ( !(stmt = mysql_stmt_init(mysql) ) ) {
		return BUG_UNKNOWN;
	}
	sprintf( query, "select t_empno, t_projno, MIN( t_emstdate ) from tdbtst180000 group by 1, 2 order by 1 desc" );

	if (mysql_stmt_prepare(stmt, query, strlen(query))) {
		mysql_stmt_close(stmt);
		return BUG_UNKNOWN;
	}

	if (mysql_stmt_execute(stmt)) {
		mysql_stmt_close(stmt);
		return BUG_UNKNOWN;
	}

	/* Bind the result buffers */

	bind[0].buffer_type= MYSQL_TYPE_LONG;
	bind[0].buffer= (char *)&int_data;
	bind[0].is_null= &is_null[0];
	bind[0].length= &length[0];

	bind[1].buffer_type= MYSQL_TYPE_STRING;
	bind[1].buffer= str_data;
	bind[1].buffer_length = sizeof(str_data);
	bind[1].is_null= &is_null[1];
	bind[1].length= &length[1];

	bind[2].buffer_type= MYSQL_TYPE_DATE;
	bind[2].buffer= (char *)&time_data;
	bind[2].is_null= &is_null[2];
	bind[2].length= &length[2];

	if (mysql_stmt_bind_result(stmt, bind)) {
		mysql_stmt_close(stmt);
		return BUG_UNKNOWN;
	}

	/* Fetch all rows */
	while (!mysql_stmt_fetch(stmt))
	{
		MYSQL_TIME * tp = &time_data;

		rows++;

		if (is_null[0] || is_null[1] || is_null[2])
			return BUG_UNKNOWN;
			
		printf ( "empno %d, projno %s, date %d/%d/%d\n", int_data, str_data, tp->year, tp->month, tp->day );

		if ( tp->year != 1982
		  || tp->month < 1	|| tp->month > 12
		  || tp->day < 1	|| tp->day > 31
		) {
			return BUG_PRESENT; }
	}

	/* Close the statement */
	mysql_stmt_close(stmt);

	if ( rows ) {
		return BUG_SOLVED;
	} else {
		return BUG_UNKNOWN;
	}
}

main()
{
	MYSQL *		mysql = mysql_init( NULL );
	BugStatus	bugstat;
	char *		desc;

	/* Bind data */

	if ( ! mysql_real_connect( mysql,
					/* host */ NULL,
					/* user */ User,
					/* pwd */ Passwd,
					/* dbase */ Dbase, 

					/* uint port */ 0,
					/* char * socket */ NULL,
					/* client_flag */ 0 ) )
	{
		fprintf(stderr, " mysql_real_connec() failed\n");
		exit(0);
	}

	bugstat = do_the_bug_test( mysql, &desc );
	fprintf(stdout, "%s\n%s\n\n", desc, str_bug_stat( bugstat ) );

	return 0;
}
[20 Jul 2004 5:34] Konstantin Osipov
Could you please check if this one is still present?
See also my comment for Bug #4183 "mysql_stmt_fetch() fetches numbers in wrong byte order"
[1 Sep 2004 16:26] Konstantin Osipov
This bug was fixed along with Bug#4183.

mysqldev@hpux11:~/kostja/mysql-4.1.4-gamma/tests> make
        cc -DUNDEF_THREADS_HACK -I. -I. -I.. -I../include      -O -DDBUG_OFF -g 
   -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCN
_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_BROKEN_INLIN
cc: warning 454: Option O0 overrides previous setting of O2.
cc: warning 483: The DOC (Debug of Optimized Code) option is unavailable with th
ored.
        /bin/sh ../libtool --preserve-dup-deps --mode=link cc  -O -DDBUG_OFF -g 
   -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCN
_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_BROKEN_INLIN
 ../libmysql/libmysqlclient.la  -lnsl -lm  ../zlib/libz.la 
cc -O -DDBUG_OFF -g -z +O0 +DA2.0W +DD64 -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE
N_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHR
DHAVE_BROKEN_INLINE -o 4184 4184.o  ../libmysql/.libs/libmysqlclient.a -lpthread
libs/libz.a -lpthread -lnsl -lm -lpthread
cc: warning 454: Option O0 overrides previous setting of O2.
mysqldev@hpux11:~/kostja/mysql-4.1.4-gamma/tests> ./4184
empno 340, projno OP2013, date 1982/1/1
empno 330, projno OP2012, date 1982/1/1
empno 320, projno OP2011, date 1982/1/1
empno 310, projno OP1010, date 1982/1/1
empno 300, projno OP1010, date 1982/1/1
empno 290, projno OP1010, date 1982/1/1
empno 280, projno OP1010, date 1982/1/1
empno 270, projno AD3113, date 1982/3/1
empno 260, projno AD3113, date 1982/6/15
empno 250, projno AD3112, date 1982/1/1
empno 240, projno AD3111, date 1982/2/15
empno 230, projno AD3111, date 1982/1/1
empno 220, projno MA2111, date 1982/1/1
empno 210, projno MA2113, date 1982/10/1
empno 200, projno MA2111, date 1982/1/1
empno 190, projno MA2112, date 1982/2/1
empno 180, projno MA2113, date 1982/4/1
empno 170, projno MA2112, date 1982/1/1
empno 170, projno MA2113, date 1982/1/1
empno 160, projno MA2113, date 1982/7/15
empno 150, projno MA2112, date 1982/1/1
empno 140, projno IF1000, date 1982/10/1
empno 140, projno IF2000, date 1982/1/1
empno 130, projno IF1000, date 1982/1/1
empno 110, projno MA2100, date 1982/1/1
empno 100, projno OP2010, date 1982/1/1
empno 90, projno OP1010, date 1982/1/1
empno 70, projno AD3110, date 1982/1/1
empno 50, projno OP1000, date 1982/1/1
empno 50, projno OP2010, date 1982/1/1
empno 30, projno IF1000, date 1982/6/1
empno 30, projno IF2000, date 1982/1/1
empno 20, projno PL2100, date 1982/1/1
empno 10, projno AD3100, date 1982/1/1
empno 10, projno MA2100, date 1982/1/1
empno 10, projno MA2110, date 1982/1/1
MySQL Bug Baan-040616  "SELECT col1, col2, fun(<date>) group by col1, col2 order
urns corrupt <date>
     ok: select col1, col2, MIN(<date>) group by col1, col2 order by col1<n>
     err:  select col1, col2, MIN(<date>) group by col1, col2 order by col1<n> D

Bug solved

mysqldev@hpux11:~/kostja/mysql-4.1.4-gamma/tests>

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

Page generated in 0.042 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.