Commit c4a9dc4f authored by konstantin@mysql.com's avatar konstantin@mysql.com

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.
parent 707e7e89
......@@ -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)
......
......@@ -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;
......
......@@ -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; }
};
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment