diff --git a/client/mysql.cc b/client/mysql.cc index 900bdec067a..01308055ac0 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2241,8 +2241,10 @@ print_table_data(MYSQL_RES *result) MYSQL_ROW cur; MYSQL_FIELD *field; bool *num_flag; + bool *not_null_flag; num_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result)); + not_null_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result)); if (info_flag) { print_field_types(result); @@ -2260,7 +2262,7 @@ print_table_data(MYSQL_RES *result) length=max(length,field->max_length); if (length < 4 && !IS_NOT_NULL(field->flags)) length=4; // Room for "NULL" - field->max_length=length+1; + field->max_length=length; separator.fill(separator.length()+length+2,'-'); separator.append('+'); } @@ -2272,10 +2274,11 @@ print_table_data(MYSQL_RES *result) (void) tee_fputs("|", PAGER); for (uint off=0; (field = mysql_fetch_field(result)) ; off++) { - tee_fprintf(PAGER, " %-*s|",(int) min(field->max_length, + tee_fprintf(PAGER, " %-*s |",(int) min(field->max_length, MAX_COLUMN_LENGTH), field->name); num_flag[off]= IS_NUM(field->type); + not_null_flag[off]= IS_NOT_NULL(field->flags); } (void) tee_fputs("\n", PAGER); tee_puts((char*) separator.ptr(), PAGER); @@ -2295,7 +2298,8 @@ print_table_data(MYSQL_RES *result) uint visible_length; uint extra_padding; - if (lengths[off] == 0) + /* If this column may have a null value, use "NULL" for empty. */ + if (! not_null_flag[off] && (lengths[off] == 0)) { buffer= "NULL"; data_length= 4; @@ -2335,6 +2339,7 @@ print_table_data(MYSQL_RES *result) } tee_puts((char*) separator.ptr(), PAGER); my_afree((gptr) num_flag); + my_afree((gptr) not_null_flag); } @@ -2349,11 +2354,8 @@ tee_print_sized_data(const char *data, unsigned int data_length, unsigned int to unsigned int i; const char *p; - total_bytes_to_send -= 1; - /* Off by one, perhaps mistakenly accounting for a terminating NUL. */ - if (right_justified) - for (i= 0; i < (total_bytes_to_send - data_length); i++) + for (i= data_length; i < total_bytes_to_send; i++) tee_putc((int)' ', PAGER); for (i= 0, p= data; i < data_length; i+= 1, p+= 1) @@ -2365,7 +2367,7 @@ tee_print_sized_data(const char *data, unsigned int data_length, unsigned int to } if (! right_justified) - for (i= 0; i < (total_bytes_to_send - data_length); i++) + for (i= data_length; i < total_bytes_to_send; i++) tee_putc((int)' ', PAGER); } diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 46c37795531..0b706b24488 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1030,3 +1030,13 @@ c res y,abc abc y,abc abc drop table t1; +select cast(rtrim(' 20.06 ') as decimal(19,2)); +cast(rtrim(' 20.06 ') as decimal(19,2)) +20.06 +select cast(ltrim(' 20.06 ') as decimal(19,2)); +cast(ltrim(' 20.06 ') as decimal(19,2)) +20.06 +select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)); +cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)) +20.06 +End of 5.0 tests diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index ae50c714bba..a067d3ad0f8 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -85,3 +85,15 @@ c_cp932 | NULL | NULL | Τη γλώσσα | | NULL | NULL | ᛖᚴ ᚷᛖᛏ | +------+------+---------------------------+ ++------+---+------+ +| i | j | k | ++------+---+------+ +| NULL | 1 | NULL | ++------+---+------+ ++-------+---------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++-------+---------+------+-----+---------+-------+ +| i | int(11) | YES | | NULL | | +| j | int(11) | NO | | NULL | | +| k | int(11) | YES | | NULL | | ++-------+---------+------+-----+---------+-------+ diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index ef20d766bce..85cedee0f4a 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -684,4 +684,11 @@ insert into t1 values ('y,abc'),('y,abc'); select c, substring_index(lcase(c), @q:=',', -1) as res from t1; drop table t1; -# End of 5.0 tests +# +# Bug #17043: Casting trimmed string to decimal loses precision +# +select cast(rtrim(' 20.06 ') as decimal(19,2)); +select cast(ltrim(' 20.06 ') as decimal(19,2)); +select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)); + +--echo End of 5.0 tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 95cba2743da..e76553f42e7 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -67,3 +67,8 @@ drop table t1; # --exec $MYSQL -t --default-character-set utf8 test -e "create table t1 (i int, j int, k char(25) charset utf8); insert into t1 (i) values (1); insert into t1 (k) values ('<----------------------->'); insert into t1 (k) values ('<-----'); insert into t1 (k) values ('Τη γλώσσα'); insert into t1 (k) values ('ᛖᚴ ᚷᛖᛏ'); select * from t1; DROP TABLE t1;" +# +# "DESCRIBE" commands may return strange NULLness flags. +# +--exec $MYSQL -t --default-character-set utf8 test -e "create table t1 (i int, j int not null, k int); insert into t1 values (null, 1, null); select * from t1; describe t1; drop table t1;" + diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index dc14bd93136..cbdfdeef05f 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -80,6 +80,20 @@ String *Item_str_func::check_well_formed_result(String *str) } +my_decimal *Item_str_func::val_decimal(my_decimal *decimal_value) +{ + DBUG_ASSERT(fixed == 1); + char buff[64]; + String *res, tmp(buff,sizeof(buff), &my_charset_bin); + res= val_str(&tmp); + if (!res) + return 0; + (void)str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(), + res->length(), res->charset(), decimal_value); + return decimal_value; +} + + double Item_str_func::val_real() { DBUG_ASSERT(fixed == 1); diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 6a95a9e5d1f..7d7b62df0dc 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -33,6 +33,7 @@ public: Item_str_func(List &list) :Item_func(list) {decimals=NOT_FIXED_DEC; } longlong val_int(); double val_real(); + my_decimal *val_decimal(my_decimal *); enum Item_result result_type () const { return STRING_RESULT; } void left_right_max_length(); String *check_well_formed_result(String *str);