diff options
author | unknown <holyfoot/hf@mysql.com/hfmain.(none)> | 2007-05-10 00:17:21 +0500 |
---|---|---|
committer | unknown <holyfoot/hf@mysql.com/hfmain.(none)> | 2007-05-10 00:17:21 +0500 |
commit | f2a52dd0f021b02177c10443cb1ee6b7ad20281a (patch) | |
tree | 5a715b5abe3283afbc2d322486f1f725316b9932 | |
parent | 187ccf4bca5bf865fec86581d894fb8e6df0792a (diff) | |
download | mariadb-git-f2a52dd0f021b02177c10443cb1ee6b7ad20281a.tar.gz |
Bug #27921 View ignores precision for CAST()
Item_decimal_typecast::print properly implemented
mysql-test/r/view.result:
Bug #27921 View ignores precision for CAST()
test result
mysql-test/t/view.test:
Bug #27921 View ignores precision for CAST()
test case
sql/field.cc:
zero decimals handling unified
sql/item_create.cc:
Bug #27921 View ignores precision for CAST()
create_func_cast parameters changed, zero precision handling unified
sql/item_create.h:
Bug #27921 View ignores precision for CAST()
create_func_cast parameters changed
sql/item_func.cc:
Bug #27921 View ignores precision for CAST()
Item_decimal_typecast::print properly implemented
sql/item_func.h:
Bug #27921 View ignores precision for CAST()
max_length counting fixed
sql/my_decimal.h:
Bug #27921 View ignores precision for CAST()
my_decimal_trim() implemented to unify zero precision handling
sql/sql_yacc.yy:
Bug #27921 View ignores precision for CAST()
create_func_cast calls simplified
-rw-r--r-- | mysql-test/r/view.result | 15 | ||||
-rw-r--r-- | mysql-test/t/view.test | 12 | ||||
-rw-r--r-- | sql/field.cc | 3 | ||||
-rw-r--r-- | sql/item_create.cc | 16 | ||||
-rw-r--r-- | sql/item_create.h | 3 | ||||
-rw-r--r-- | sql/item_func.cc | 19 | ||||
-rw-r--r-- | sql/item_func.h | 2 | ||||
-rw-r--r-- | sql/my_decimal.h | 13 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 12 |
9 files changed, 75 insertions, 20 deletions
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 70dd6b2550f..8d9d802949d 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1789,7 +1789,7 @@ drop table t1; create view v1 as select cast(1 as decimal); select * from v1; cast(1 as decimal) -1.00 +1 drop view v1; create table t1(f1 int); create table t2(f2 int); @@ -3354,4 +3354,17 @@ id select_type table type possible_keys key key_len ref rows Extra NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL Using filesort DROP VIEW v1; DROP TABLE t1; +CREATE VIEW v1 AS SELECT CAST( 1.23456789 AS DECIMAL( 7,5 ) ) AS col; +SELECT * FROM v1; +col +1.23457 +DESCRIBE v1; +Field Type Null Key Default Extra +col decimal(7,5) NO 0.00000 +DROP VIEW v1; +CREATE VIEW v1 AS SELECT CAST(1.23456789 AS DECIMAL(8,0)) AS col; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(1.23456789 as decimal(8,0)) AS `col` +DROP VIEW v1; End of 5.0 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index e5bf9de13eb..3275ba0a687 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3221,4 +3221,16 @@ EXPLAIN SELECT * FROM t1 UNION SELECT * FROM v1 ORDER BY a; DROP VIEW v1; DROP TABLE t1; +# +# Bug #27921 View ignores precision for CAST() +# +CREATE VIEW v1 AS SELECT CAST( 1.23456789 AS DECIMAL( 7,5 ) ) AS col; +SELECT * FROM v1; +DESCRIBE v1; +DROP VIEW v1; + +CREATE VIEW v1 AS SELECT CAST(1.23456789 AS DECIMAL(8,0)) AS col; +SHOW CREATE VIEW v1; +DROP VIEW v1; + --echo End of 5.0 tests. diff --git a/sql/field.cc b/sql/field.cc index b2def4ca8d2..d2e72371bc1 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8426,8 +8426,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, case FIELD_TYPE_NULL: break; case FIELD_TYPE_NEWDECIMAL: - if (!fld_length && !decimals) - length= 10; + my_decimal_trim(&length, &decimals); if (length > DECIMAL_MAX_PRECISION) { my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name, diff --git a/sql/item_create.cc b/sql/item_create.cc index c1a81da0285..c4008d36aae 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -445,11 +445,13 @@ Item *create_load_file(Item* a) } -Item *create_func_cast(Item *a, Cast_target cast_type, int len, int dec, +Item *create_func_cast(Item *a, Cast_target cast_type, + const char *c_len, const char *c_dec, CHARSET_INFO *cs) { Item *res; - int tmp_len; + ulong len; + uint dec; LINT_INIT(res); switch (cast_type) { @@ -460,15 +462,18 @@ Item *create_func_cast(Item *a, Cast_target cast_type, int len, int dec, case ITEM_CAST_TIME: res= new Item_time_typecast(a); break; case ITEM_CAST_DATETIME: res= new Item_datetime_typecast(a); break; case ITEM_CAST_DECIMAL: - tmp_len= (len>0) ? len : 10; - if (tmp_len < dec) + len= c_len ? atoi(c_len) : 0; + dec= c_dec ? atoi(c_dec) : 0; + my_decimal_trim(&len, &dec); + if (len < dec) { my_error(ER_M_BIGGER_THAN_D, MYF(0), ""); return 0; } - res= new Item_decimal_typecast(a, tmp_len, dec ? dec : 2); + res= new Item_decimal_typecast(a, len, dec); break; case ITEM_CAST_CHAR: + len= c_len ? atoi(c_len) : -1; res= new Item_char_typecast(a, len, cs ? cs : current_thd->variables.collation_connection); break; @@ -476,6 +481,7 @@ Item *create_func_cast(Item *a, Cast_target cast_type, int len, int dec, return res; } + Item *create_func_is_free_lock(Item* a) { current_thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); diff --git a/sql/item_create.h b/sql/item_create.h index 2ff849263c6..46b209b3e49 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -27,7 +27,8 @@ Item *create_func_bit_length(Item* a); Item *create_func_coercibility(Item* a); Item *create_func_ceiling(Item* a); Item *create_func_char_length(Item* a); -Item *create_func_cast(Item *a, Cast_target cast_type, int len, int dec, +Item *create_func_cast(Item *a, Cast_target cast_type, + const char *len, const char *dec, CHARSET_INFO *cs); Item *create_func_connection_id(void); Item *create_func_conv(Item* a, Item *b, Item *c); diff --git a/sql/item_func.cc b/sql/item_func.cc index e761cf7fb43..aa04e4176d6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1059,9 +1059,26 @@ my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec) void Item_decimal_typecast::print(String *str) { + char len_buf[20*3 + 1]; + char *end; + CHARSET_INFO *cs= str->charset(); + + uint precision= my_decimal_length_to_precision(max_length, decimals, + unsigned_flag); str->append(STRING_WITH_LEN("cast(")); args[0]->print(str); - str->append(STRING_WITH_LEN(" as decimal)")); + str->append(STRING_WITH_LEN(" as decimal(")); + + end=int10_to_str(precision, len_buf,10); + str->append(len_buf, (uint32) (end - len_buf)); + + str->append(','); + + end=int10_to_str(decimals, len_buf,10); + str->append(len_buf, (uint32) (end - len_buf)); + + str->append(')'); + str->append(')'); } diff --git a/sql/item_func.h b/sql/item_func.h index 952c828b251..597728cea6d 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -331,8 +331,8 @@ class Item_decimal_typecast :public Item_func public: Item_decimal_typecast(Item *a, int len, int dec) :Item_func(a) { - max_length= len + 2; decimals= dec; + max_length= my_decimal_precision_to_length(len, dec, unsigned_flag); } String *val_str(String *str); double val_real(); diff --git a/sql/my_decimal.h b/sql/my_decimal.h index 45270150d22..a30dceab19d 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -387,5 +387,18 @@ int my_decimal_cmp(const my_decimal *a, const my_decimal *b) return decimal_cmp((decimal_t*) a, (decimal_t*) b); } + +inline +void my_decimal_trim(ulong *precision, uint *scale) +{ + if (!(*precision) && !(*scale)) + { + *precision= 10; + *scale= 0; + return; + } +} + + #endif /*my_decimal_h*/ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4a50a602121..0bb5f6a5e25 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4699,15 +4699,12 @@ simple_expr: | ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); } | BINARY simple_expr %prec NEG { - $$= create_func_cast($2, ITEM_CAST_CHAR, -1, 0, &my_charset_bin); + $$= create_func_cast($2, ITEM_CAST_CHAR, NULL, NULL, &my_charset_bin); } | CAST_SYM '(' expr AS cast_type ')' { LEX *lex= Lex; - $$= create_func_cast($3, $5, - lex->length ? atoi(lex->length) : -1, - lex->dec ? atoi(lex->dec) : 0, - lex->charset); + $$= create_func_cast($3, $5, lex->length, lex->dec, lex->charset); if (!$$) MYSQL_YYABORT; } @@ -4715,10 +4712,7 @@ simple_expr: { $$= new Item_func_case(* $3, $2, $4 ); } | CONVERT_SYM '(' expr ',' cast_type ')' { - $$= create_func_cast($3, $5, - Lex->length ? atoi(Lex->length) : -1, - Lex->dec ? atoi(Lex->dec) : 0, - Lex->charset); + $$= create_func_cast($3, $5, Lex->length, Lex->dec, Lex->charset); if (!$$) MYSQL_YYABORT; } |