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;
}