diff options
-rw-r--r-- | libmysql/libmysql.c | 21 | ||||
-rw-r--r-- | sql-common/my_time.c | 3 | ||||
-rw-r--r-- | tests/client_test.c | 101 |
3 files changed, 120 insertions, 5 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 2dfdfbb687b..9195f0a5bc5 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -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: diff --git a/sql-common/my_time.c b/sql-common/my_time.c index be349285b88..6c020466e1e 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -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, diff --git a/tests/client_test.c b/tests/client_test.c index 562f6e307d3..48676ae7e12 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -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. |