From 7091b7852d27e6c8a1875b2acc0d1adbfb29984f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 8 Oct 2015 19:19:21 +0400 Subject: MDEV-8918 Wrong result for CAST(AVG(bigint_column) AS SIGNED) - Moving Item_xxx_field declarations after Item_sum_xxx declarations, so Item_xxx_field constructors can be defined directly in item_sum.h rather than item_sum.cc. This removes some duplicate code, e.g. initialization of the following members at constructor time: name, decimals, max_length, unsigned_flag, field, maybe_null. - Adding Item_sum_field as a common parent for Item_avg_field and Item_variance_field - Deriving Item_sum_field directly from Item rather that Item_result_field, as Item_sum_field descendants do not need anything from Item_result_field. - Removing hybrid infrastructure from Item_avg_field, adding Item_avg_field_decimal and Item_avg_field_double instead, as desired result type is already known at constructor time (not only at fix_fields time). This simplifies the code. - Changing Item_avg_field_decimal::val_int() to call val_int_from_decimal() instead of doing { return (longlong) rint(val_real()); } This is the fix itself. --- sql/item_sum.cc | 69 +++++---------------------------------------------------- 1 file changed, 6 insertions(+), 63 deletions(-) (limited to 'sql/item_sum.cc') diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 8836b7638f3..5d471557892 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2502,7 +2502,10 @@ void Item_sum_avg::update_field() Item *Item_sum_avg::result_item(THD *thd, Field *field) { - return new (thd->mem_root) Item_avg_field(thd, hybrid_type, this); + return + hybrid_type == DECIMAL_RESULT ? + (Item_avg_field*) new (thd->mem_root) Item_avg_field_decimal(thd, this) : + (Item_avg_field*) new (thd->mem_root) Item_avg_field_double(thd, this); } @@ -2620,36 +2623,13 @@ Item_sum_hybrid::min_max_update_decimal_field() } -Item_avg_field::Item_avg_field(THD *thd, Item_result res_type, - Item_sum_avg *item): - Item_result_field(thd) -{ - name=item->name; - decimals=item->decimals; - max_length= item->max_length; - unsigned_flag= item->unsigned_flag; - field=item->result_field; - maybe_null=1; - hybrid_type= res_type; - prec_increment= item->prec_increment; - if (hybrid_type == DECIMAL_RESULT) - { - f_scale= item->f_scale; - f_precision= item->f_precision; - dec_bin_size= item->dec_bin_size; - } -} - -double Item_avg_field::val_real() +double Item_avg_field_double::val_real() { // fix_fields() never calls for this Item double nr; longlong count; uchar *res; - if (hybrid_type == DECIMAL_RESULT) - return val_real_from_decimal(); - float8get(nr,field->ptr); res= (field->ptr+sizeof(double)); count= sint8korr(res); @@ -2660,18 +2640,9 @@ double Item_avg_field::val_real() } -longlong Item_avg_field::val_int() -{ - return (longlong) rint(val_real()); -} - - -my_decimal *Item_avg_field::val_decimal(my_decimal *dec_buf) +my_decimal *Item_avg_field_decimal::val_decimal(my_decimal *dec_buf) { // fix_fields() never calls for this Item - if (hybrid_type == REAL_RESULT) - return val_decimal_from_real(dec_buf); - longlong count= sint8korr(field->ptr + dec_bin_size); if ((null_value= !count)) return 0; @@ -2686,21 +2657,6 @@ my_decimal *Item_avg_field::val_decimal(my_decimal *dec_buf) } -String *Item_avg_field::val_str(String *str) -{ - // fix_fields() never calls for this Item - if (hybrid_type == DECIMAL_RESULT) - return val_string_from_decimal(str); - return val_string_from_real(str); -} - - -Item_std_field::Item_std_field(THD *thd, Item_sum_std *item): - Item_variance_field(thd, item) -{ -} - - double Item_std_field::val_real() { double nr; @@ -2711,19 +2667,6 @@ double Item_std_field::val_real() } -Item_variance_field::Item_variance_field(THD *thd, Item_sum_variance *item): - Item_result_field(thd) -{ - name=item->name; - decimals=item->decimals; - max_length=item->max_length; - unsigned_flag= item->unsigned_flag; - field=item->result_field; - maybe_null=1; - sample= item->sample; -} - - double Item_variance_field::val_real() { // fix_fields() never calls for this Item -- cgit v1.2.1