From c4a9dc4f8ba59dac3f8b5dfdf983cbef19bc34df Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Fri, 21 Nov 2003 00:03:04 +0300 Subject: [PATCH] fix for bug #1790: "BIT_AND() result in GROUP BY different when SQL_BIG_RESULT used" return value of BIT_AND changed to BIGINT SIGNED Also the patch fixes another bug: when temporary table is in use and one of values in group is NULL, BIT_AND always returns zero. Fixed it to always skip null values. --- mysql-test/r/func_group.result | 14 ++++++------- sql/item_sum.cc | 36 ++++++++++++---------------------- sql/item_sum.h | 22 ++++++++++++++++----- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 80ccb6c7bb8..a1563271917 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -47,7 +47,7 @@ sum(all a) count(all a) avg(all a) std(all a) bit_or(all a) bit_and(all a) min(a 21 6 3.5000 1.7078 7 0 1 6 E select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp; grp sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c) -NULL NULL 0 NULL NULL 0 0 NULL NULL +NULL NULL 0 NULL NULL 0 -1 NULL NULL 1 1 1 1.0000 0.0000 1 1 1 1 a a 2 5 2 2.5000 0.5000 3 2 2 3 b c 3 15 3 5.0000 0.8165 7 4 4 6 C E @@ -218,8 +218,8 @@ insert into t1 values (1,null); insert into t1 values (2,null); select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) -1 0 NULL NULL NULL NULL NULL 0 0 -2 0 NULL NULL NULL NULL NULL 0 0 +1 0 NULL NULL NULL NULL NULL -1 0 +2 0 NULL NULL NULL NULL NULL -1 0 select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) 1 0 NULL NULL NULL NULL NULL -1 0 @@ -227,8 +227,8 @@ a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) insert into t1 values (2,1); select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) -1 0 NULL NULL NULL NULL NULL 0 0 -2 1 1 1.0000 0.0000 1 1 0 1 +1 0 NULL NULL NULL NULL NULL -1 0 +2 1 1 1.0000 0.0000 1 1 1 1 select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) 1 0 NULL NULL NULL NULL NULL -1 0 @@ -236,8 +236,8 @@ a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) insert into t1 values (3,1); select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) -1 0 NULL NULL NULL NULL NULL 0 0 -2 1 1 1.0000 0.0000 1 1 0 1 +1 0 NULL NULL NULL NULL NULL -1 0 +2 1 1 1.0000 0.0000 1 1 1 1 3 1 1 1.0000 0.0000 1 1 1 1 select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 835278ae262..36a3c6b009b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -614,10 +614,19 @@ void Item_sum_avg::reset_field() } void Item_sum_bit::reset_field() +{ + char *res= result_field->ptr; + bits= reset_bits; + add(); + int8store(res, bits); +} + +void Item_sum_bit::update_field() { char *res=result_field->ptr; - ulonglong nr=(ulonglong) args[0]->val_int(); - int8store(res,nr); + bits= uint8korr(res); + add(); + int8store(res, bits); } /* @@ -756,28 +765,6 @@ Item_sum_hybrid::min_max_update_int_field() } -void Item_sum_or::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr|= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - - -void Item_sum_and::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr&= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - - Item_avg_field::Item_avg_field(Item_sum_avg *item) { name=item->name; @@ -787,6 +774,7 @@ Item_avg_field::Item_avg_field(Item_sum_avg *item) maybe_null=1; } + double Item_avg_field::val() { double nr; diff --git a/sql/item_sum.h b/sql/item_sum.h index 5189566fdfb..c91abbded28 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -55,7 +55,18 @@ public: virtual enum Sumfunctype sum_func () const=0; virtual void reset()=0; virtual bool add()=0; + /* + Called when new group is started and results are being saved in + a temporary table. Similar to reset(), but must also store value in + result_field. Like reset() it is supposed to reset start value to + default. + */ virtual void reset_field()=0; + /* + Called for each new value in the group, when temporary table is in use. + Similar to add(), but uses temporary table field to obtain current value, + Updated value is then saved in the field. + */ virtual void update_field()=0; virtual bool keep_field_type(void) const { return 0; } virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } @@ -360,20 +371,20 @@ class Item_sum_bit :public Item_sum_int void reset(); longlong val_int(); void reset_field(); + void update_field(); unsigned int size_of() { return sizeof(*this);} - void fix_length_and_dec() - { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; class Item_sum_or :public Item_sum_bit { - public: +public: Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} bool add(); - void update_field(); const char *func_name() const { return "bit_or"; } unsigned int size_of() { return sizeof(*this);} + void fix_length_and_dec() + { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; @@ -382,9 +393,10 @@ class Item_sum_and :public Item_sum_bit public: Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ~(ulonglong) LL(0)) {} bool add(); - void update_field(); const char *func_name() const { return "bit_and"; } unsigned int size_of() { return sizeof(*this);} + void fix_length_and_dec() + { decimals=0; max_length=21; unsigned_flag=0; maybe_null=null_value=0; } }; /*