From 42894ed0b870f4adfc6023404877732a08b1ec22 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 29 Oct 2007 12:20:21 +0400 Subject: Fix for bug #30782: Truncated UNSIGNED BIGINT columns only in SELECT w/ CASE, JOIN, and ORDER BY Problem: improper maximum length calculation of the CASE function leads to decimal value truncation (storing/retrieving decimal field values). Fix: accurately calculate maximum length/unsigned flag/decimals parameters of the CASE function. mysql-test/r/case.result: Fix for bug #30782: Truncated UNSIGNED BIGINT columns only in SELECT w/ CASE, JOIN, and ORDER BY - test result. mysql-test/t/case.test: Fix for bug #30782: Truncated UNSIGNED BIGINT columns only in SELECT w/ CASE, JOIN, and ORDER BY - test case. sql/item_cmpfunc.cc: Fix for bug #30782: Truncated UNSIGNED BIGINT columns only in SELECT w/ CASE, JOIN, and ORDER BY - accurately calculate Item_func_case::max_length/unsigned_flag/decimals. sql/item_cmpfunc.h: Fix for bug #30782: Truncated UNSIGNED BIGINT columns only in SELECT w/ CASE, JOIN, and ORDER BY - accurately calculate Item_func_case::max_length/unsigned_flag/decimals. --- sql/item_cmpfunc.cc | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'sql/item_cmpfunc.cc') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 86eb10d50b0..8cbbc115922 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2530,6 +2530,23 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref) } +void Item_func_case::agg_str_lengths(Item* arg) +{ + set_if_bigger(max_length, arg->max_length); + set_if_bigger(decimals, arg->decimals); + unsigned_flag= unsigned_flag && arg->unsigned_flag; +} + + +void Item_func_case::agg_num_lengths(Item *arg) +{ + uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals, + arg->unsigned_flag) - arg->decimals; + set_if_bigger(max_length, len); + set_if_bigger(decimals, arg->decimals); + unsigned_flag= unsigned_flag && arg->unsigned_flag; +} + void Item_func_case::fix_length_and_dec() { @@ -2579,15 +2596,22 @@ void Item_func_case::fix_length_and_dec() max_length=0; decimals=0; - for (uint i=0 ; i < ncases ; i+=2) + unsigned_flag= TRUE; + if (cached_result_type == STRING_RESULT) { - set_if_bigger(max_length,args[i+1]->max_length); - set_if_bigger(decimals,args[i+1]->decimals); + for (uint i= 0; i < ncases; i+= 2) + agg_str_lengths(args[i + 1]); + if (else_expr_num != -1) + agg_str_lengths(args[else_expr_num]); } - if (else_expr_num != -1) + else { - set_if_bigger(max_length,args[else_expr_num]->max_length); - set_if_bigger(decimals,args[else_expr_num]->decimals); + for (uint i= 0; i < ncases; i+= 2) + agg_num_lengths(args[i + 1]); + if (else_expr_num != -1) + agg_num_lengths(args[else_expr_num]); + max_length= my_decimal_precision_to_length(max_length + decimals, decimals, + unsigned_flag); } } -- cgit v1.2.1