mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
A fix and test case for Bug#6096 "field.max_length is always zero for
numeric columns (stmt_resultset_metadata)"
This commit is contained in:
@ -1752,6 +1752,7 @@ static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data);
|
||||
*/
|
||||
#define MAX_DATETIME_REP_LENGTH 12
|
||||
|
||||
#define MAX_DOUBLE_STRING_REP_LENGTH 331
|
||||
|
||||
/**************** Misc utility functions ****************************/
|
||||
|
||||
@ -3265,7 +3266,12 @@ static void read_binary_time(MYSQL_TIME *tm, uchar **pos)
|
||||
tm->second= (uint) to[7];
|
||||
tm->second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0;
|
||||
tm->year= tm->month= 0;
|
||||
|
||||
if (tm->day)
|
||||
{
|
||||
/* Convert days to hours at once */
|
||||
tm->hour+= tm->day*24;
|
||||
tm->day= 0;
|
||||
}
|
||||
*pos+= length;
|
||||
}
|
||||
else
|
||||
@ -3558,7 +3564,7 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
|
||||
floating point -> string conversion nicely, honor all typecodes
|
||||
and param->offset possibly set in mysql_stmt_fetch_column
|
||||
*/
|
||||
char buff[331];
|
||||
char buff[MAX_DOUBLE_STRING_REP_LENGTH];
|
||||
char *end;
|
||||
/* TODO: move this to a header shared between client and server. */
|
||||
#define NOT_FIXED_DEC 31
|
||||
@ -3992,32 +3998,43 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
|
||||
switch (field->type) {
|
||||
case MYSQL_TYPE_NULL: /* for dummy binds */
|
||||
param->pack_length= 0;
|
||||
field->max_length= 0;
|
||||
break;
|
||||
case MYSQL_TYPE_TINY:
|
||||
param->pack_length= 1;
|
||||
field->max_length= 4; /* as in '-127' */
|
||||
break;
|
||||
case MYSQL_TYPE_YEAR:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
param->pack_length= 2;
|
||||
field->max_length= 6; /* as in '-32767' */
|
||||
break;
|
||||
case MYSQL_TYPE_INT24:
|
||||
field->max_length= 9; /* as in '16777216' or in '-8388607' */
|
||||
param->pack_length= 4;
|
||||
break;
|
||||
case MYSQL_TYPE_LONG:
|
||||
field->max_length= 11; /* '-2147483647' */
|
||||
param->pack_length= 4;
|
||||
break;
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
field->max_length= 21; /* '18446744073709551616' */
|
||||
param->pack_length= 8;
|
||||
break;
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
param->pack_length= 4;
|
||||
field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
|
||||
break;
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
param->pack_length= 8;
|
||||
field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
|
||||
break;
|
||||
case MYSQL_TYPE_TIME:
|
||||
case MYSQL_TYPE_DATE:
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
param->skip_result= skip_result_with_length;
|
||||
field->max_length= MAX_DATE_STRING_REP_LENGTH;
|
||||
break;
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
case MYSQL_TYPE_ENUM:
|
||||
|
@ -743,9 +743,6 @@ void set_zero_time(MYSQL_TIME *tm)
|
||||
int my_time_to_str(const MYSQL_TIME *l_time, char *to)
|
||||
{
|
||||
uint extra_hours= 0;
|
||||
/* Get extra hours, if we are getting data from the server */
|
||||
if (l_time->year == 0 && l_time->month == 0)
|
||||
extra_hours= l_time->day*24;
|
||||
return my_sprintf(to, (to, "%s%02d:%02d:%02d",
|
||||
(l_time->neg ? "-" : ""),
|
||||
extra_hours+ l_time->hour,
|
||||
|
@ -10713,6 +10713,106 @@ static void test_bug6081()
|
||||
rc= simple_command(mysql, COM_CREATE_DB, current_db,
|
||||
(ulong)strlen(current_db), 0);
|
||||
myquery_r(rc);
|
||||
rc= mysql_select_db(mysql, current_db);
|
||||
myquery(rc);
|
||||
}
|
||||
|
||||
|
||||
static void test_bug6096()
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_RES *query_result, *stmt_metadata;
|
||||
const char *stmt_text;
|
||||
MYSQL_BIND bind[12];
|
||||
MYSQL_FIELD *query_field_list, *stmt_field_list;
|
||||
ulong query_field_count, stmt_field_count;
|
||||
int rc;
|
||||
uint i;
|
||||
|
||||
myheader("test_bug6096");
|
||||
|
||||
stmt_text= "drop table if exists t1";
|
||||
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
|
||||
myquery(rc);
|
||||
|
||||
stmt_text= "create table t1 (c_tinyint tinyint, c_smallint smallint, "
|
||||
" c_mediumint mediumint, c_int int, "
|
||||
" c_bigint bigint, c_float float, "
|
||||
" c_double double, c_varchar varchar(20), "
|
||||
" c_char char(20), c_time time, c_date date, "
|
||||
" c_datetime datetime)";
|
||||
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
|
||||
myquery(rc);
|
||||
stmt_text= "insert into t1 values (-100, -20000, 30000000, 4, 8, 1.0, "
|
||||
"2.0, 'abc', 'def', now(), now(), now())";
|
||||
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
|
||||
myquery(rc);
|
||||
|
||||
stmt_text= "select * from t1";
|
||||
|
||||
/* Run select in prepared and non-prepared mode and compare metadata */
|
||||
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
|
||||
myquery(rc);
|
||||
query_result= mysql_store_result(mysql);
|
||||
query_field_list= mysql_fetch_fields(query_result);
|
||||
query_field_count= mysql_num_fields(query_result);
|
||||
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
|
||||
check_execute(stmt, rc);
|
||||
rc= mysql_stmt_execute(stmt);
|
||||
check_execute(stmt, rc);
|
||||
rc= 1;
|
||||
mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*)&rc);
|
||||
mysql_stmt_store_result(stmt);
|
||||
stmt_metadata= mysql_stmt_result_metadata(stmt);
|
||||
stmt_field_list= mysql_fetch_fields(stmt_metadata);
|
||||
stmt_field_count= mysql_num_fields(stmt_metadata);
|
||||
DIE_UNLESS(stmt_field_count == query_field_count);
|
||||
|
||||
/* Print out and check the metadata */
|
||||
|
||||
printf(" ---------------------------------------------------------------\n");
|
||||
printf(" | Metadata \n");
|
||||
printf(" ---------------------------------------------------------------\n");
|
||||
printf(" | Query | Prepared statement \n");
|
||||
printf(" ---------------------------------------------------------------\n");
|
||||
printf(" field name | length | max_length | length | max_length \n");
|
||||
printf(" ---------------------------------------------------------------\n");
|
||||
|
||||
for (i= 0; i < query_field_count; ++i)
|
||||
{
|
||||
MYSQL_FIELD *f1= &query_field_list[i], *f2= &stmt_field_list[i];
|
||||
printf(" %-11s | %9lu | %10lu | %9lu | %10lu \n",
|
||||
f1->name, f1->length, f1->max_length, f2->length, f2->max_length);
|
||||
DIE_UNLESS(f1->length == f2->length);
|
||||
}
|
||||
printf(" ---------------------------------------------------------------\n");
|
||||
|
||||
/* Bind and fetch the data */
|
||||
|
||||
bzero(bind, sizeof(bind));
|
||||
for (i= 0; i < stmt_field_count; ++i)
|
||||
{
|
||||
bind[i].buffer_type= MYSQL_TYPE_STRING;
|
||||
bind[i].buffer_length= stmt_field_list[i].max_length + 1;
|
||||
bind[i].buffer= malloc(bind[i].buffer_length);
|
||||
}
|
||||
mysql_stmt_bind_result(stmt, bind);
|
||||
rc= mysql_stmt_fetch(stmt);
|
||||
check_execute(stmt, rc);
|
||||
rc= mysql_stmt_fetch(stmt);
|
||||
DIE_UNLESS(rc == MYSQL_NO_DATA);
|
||||
|
||||
/* Clean up */
|
||||
|
||||
for (i= 0; i < stmt_field_count; ++i)
|
||||
free(bind[i].buffer);
|
||||
mysql_stmt_close(stmt);
|
||||
mysql_free_result(query_result);
|
||||
stmt_text= "drop table t1";
|
||||
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
|
||||
myquery(rc);
|
||||
}
|
||||
|
||||
|
||||
@ -11031,6 +11131,7 @@ int main(int argc, char **argv)
|
||||
test_bug6059(); /* correct metadata for SELECT ... INTO OUTFILE */
|
||||
test_bug6046(); /* NATURAL JOIN transformation works in PS */
|
||||
test_bug6081(); /* test of mysql_create_db()/mysql_rm_db() */
|
||||
test_bug6096(); /* max_length for numeric columns */
|
||||
/*
|
||||
XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
|
||||
DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
|
||||
|
Reference in New Issue
Block a user