List:Commits« Previous MessageNext Message »
From:Roy Lyseng Date:December 6 2010 9:35am
Subject:Re: bzr commit into mysql-5.5-bugteam branch (Georgi.Kodinov:3135)
Bug#57954
View as plain text  
Hi Georgi,

thank you for fixing this problem.

The bug fix is approved.

I have one suggestion for extended test coverage below, one suggestion for an 
improved comment,
and one suggestion to replace the reset_and_add() function with its contents.

All suggestions are optional, though.

On 02.12.10 15.29, Georgi Kodinov wrote:
> #At file:///Users/kgeorge/mysql/work/B57954-5.5-bugteam/ based on
> revid:davi.arnaut@stripped
>
>   3135 Georgi Kodinov	2010-12-02
>        Bug #57954: BIT_AND function returns incorrect results
>         when semijoin=on
>
>        When setting the aggregate function as having no rows to report
>        the function no_rows_in_result() was calling Item_sum::reset().
>        However this function in addition to cleaning up the aggregate
>        value by calling aggregator_clear() was also adding the current
>        value to the aggregate value by calling aggregator_add().
>        Fixed by making no_rows_in_result() to call aggregator_clear()
>        directly.
>        Renamed Item_sum::reset to Item_sum::reset_and_add() to
>        and added a comment to avoid misinterpretation of what the
>        function does.

Small typo "to"
>      modified:
>        mysql-test/r/func_group_innodb.result
>        mysql-test/t/func_group_innodb.test
>        sql/item_sum.cc
>        sql/item_sum.h
>        sql/opt_range.cc
>        sql/opt_sum.cc
>        sql/sql_select.cc
> === modified file 'mysql-test/r/func_group_innodb.result'
> --- a/mysql-test/r/func_group_innodb.result	2007-05-29 12:58:18 +0000
> +++ b/mysql-test/r/func_group_innodb.result	2010-12-02 14:29:45 +0000
> @@ -145,3 +145,31 @@ select count(*), min(7), max(7) from t2m
>   count(*)	min(7)	max(7)
>   0	NULL	NULL
>   drop table t1m, t1i, t2m, t2i;
> +#
> +# Bug #57954: BIT_AND function returns incorrect results when
> +#   semijoin=on
> +CREATE TABLE C (
> +pk INT,
> +col_varchar_key VARCHAR(1),
> +PRIMARY KEY (pk),
> +KEY col_varchar_key (col_varchar_key)
> +) ENGINE=InnoDB;
> +INSERT INTO C VALUES (11,NULL);
> +INSERT INTO C VALUES (16,'c');
> +CREATE TABLE BB (
> +pk INT,
> +col_varchar_key VARCHAR(1),
> +PRIMARY KEY (pk),
> +KEY col_varchar_key (col_varchar_key)
> +) ENGINE=InnoDB;
> +INSERT INTO BB VALUES (10,NULL);
> +SELECT straight_join BIT_AND(c.pk)
> +FROM
> +bb, c
> +WHERE c.col_varchar_key='ABC'
> +ORDER BY c.pk
> +;
> +BIT_AND(c.pk)
> +18446744073709551615
> +DROP TABLE C,BB;
> +End of 5.5 tests
>
> === modified file 'mysql-test/t/func_group_innodb.test'
> --- a/mysql-test/t/func_group_innodb.test	2006-05-22 11:27:58 +0000
> +++ b/mysql-test/t/func_group_innodb.test	2010-12-02 14:29:45 +0000
> @@ -83,3 +83,35 @@ explain select count(*), min(7), max(7)
>   select count(*), min(7), max(7) from t2m, t1i;
>
>   drop table t1m, t1i, t2m, t2i;
> +
> +
> +--echo #
> +--echo # Bug #57954: BIT_AND function returns incorrect results when
> +--echo #   semijoin=on
> +
> +CREATE TABLE C (
> +  pk INT,
> +  col_varchar_key VARCHAR(1),
> +  PRIMARY KEY (pk),
> +  KEY col_varchar_key (col_varchar_key)
> +) ENGINE=InnoDB;
> +INSERT INTO C VALUES (11,NULL);
> +INSERT INTO C VALUES (16,'c');
> +CREATE TABLE BB (
> +  pk INT,
> +  col_varchar_key VARCHAR(1),
> +  PRIMARY KEY (pk),
> +  KEY col_varchar_key (col_varchar_key)
> +) ENGINE=InnoDB;
> +INSERT INTO BB VALUES (10,NULL);
> +
> +SELECT straight_join BIT_AND(c.pk)
> +FROM
> +  bb, c
> +  WHERE c.col_varchar_key='ABC'
> +ORDER BY c.pk
> +;
> +
> +DROP TABLE C,BB;
> +
> +--echo End of 5.5 tests

Can you add tests for BIT_OR() and BIT_XOR() (from bug#58050) as well?

I would also prefer lowercase table names in the CREATE TABLE, DROP TABLE and 
INSERT statements.
> === modified file 'sql/item_sum.cc'
> --- a/sql/item_sum.cc	2010-09-02 13:57:59 +0000
> +++ b/sql/item_sum.cc	2010-12-02 14:29:45 +0000
> @@ -2229,7 +2229,7 @@ void Item_sum_avg::reset_field()
>
>   void Item_sum_bit::reset_field()
>   {
> -  reset();
> +  reset_and_add();
>     int8store(result_field->ptr, bits);
>   }
>
>
> === modified file 'sql/item_sum.h'
> --- a/sql/item_sum.h	2010-08-30 07:36:04 +0000
> +++ b/sql/item_sum.h	2010-12-02 14:29:45 +0000
> @@ -396,13 +396,21 @@ public:
>     Item_sum(THD *thd, Item_sum *item);
>     enum Type type() const { return SUM_FUNC_ITEM; }
>     virtual enum Sumfunctype sum_func () const=0;
> -  inline bool reset() { aggregator_clear(); return aggregator_add(); };
> +  /**
> +    Resets the aggregate to its default value and adds the value
> +    in its attribute(s) to it.
> +  */
> +  inline bool reset_and_add()
> +  {
> +    aggregator_clear();
> +    return aggregator_add();
> +  };

Suggestion:
I am not sure the function reset()/reset_and_add() is really needed. Consider 
this fragment in opt_sum.cc:

         if (!count && !outer_tables)
         {
           item_sum->aggregator_clear();
         }
         else
           item_sum->reset();

If you remove the call to reset(), the logic should be:

         item_sum->aggregator_clear();
         if (count || outer_tables)
           item_sum->aggregator_add();

which IMHO better expresses the logic.

There are a couple of places where you will need to have two function calls 
instead of one, but the logic will again be clearer.

>
>     /*
>       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.
> +    a temporary table. Similar to reset_and_add(), but must also
> +    store value in result_field. Like reset_and_add() it is supposed
> +    to reset start value to default.

I propose that the above section is replaced with (see also Guilhem's comments):

   Initialize the accumulator, aggregate the first value into it, and store the 
resulting value in result_field.
>       This set of methods (reult_field(), reset_field, update_field()) of
>       Item_sum is used only if quick_group is not null. Otherwise
>       copy_or_same() is used to obtain a copy of this item.
> @@ -446,7 +454,7 @@ public:
>         set_aggregator(with_distinct ?
>                        Aggregator::DISTINCT_AGGREGATOR :
>                        Aggregator::SIMPLE_AGGREGATOR);
> -    reset();
> +    aggregator_clear();
>     }
>     virtual void make_unique() { force_copy_fields= TRUE; }
>     Item *get_tmp_table_item(THD *thd);
>
> === modified file 'sql/opt_range.cc'
> --- a/sql/opt_range.cc	2010-11-19 17:15:47 +0000
> +++ b/sql/opt_range.cc	2010-12-02 14:29:45 +0000
> @@ -11391,7 +11391,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::update_
>
>     min_functions_it->rewind();
>     while ((min_func= (*min_functions_it)++))
> -    min_func->reset();
> +    min_func->reset_and_add();
>   }
>
>
> @@ -11423,7 +11423,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::update_
>
>     max_functions_it->rewind();
>     while ((max_func= (*max_functions_it)++))
> -    max_func->reset();
> +    max_func->reset_and_add();
>   }
>
>
>
> === modified file 'sql/opt_sum.cc'
> --- a/sql/opt_sum.cc	2010-06-11 08:15:55 +0000
> +++ b/sql/opt_sum.cc	2010-12-02 14:29:45 +0000
> @@ -424,7 +424,7 @@ int opt_sum_query(TABLE_LIST *tables, Li
>             item_sum->aggregator_clear();
>           }
>           else
> -          item_sum->reset();
> +          item_sum->reset_and_add();
>           item_sum->make_const();
>           recalc_const_item= 1;
>           break;
>
> === modified file 'sql/sql_select.cc'
> --- a/sql/sql_select.cc	2010-11-22 09:13:46 +0000
> +++ b/sql/sql_select.cc	2010-12-02 14:29:45 +0000
> @@ -15838,7 +15838,7 @@ init_sum_functions(Item_sum **func_ptr,
>   {
>     for (; func_ptr != end_ptr ;func_ptr++)
>     {
> -    if ((*func_ptr)->reset())
> +    if ((*func_ptr)->reset_and_add())
>         return 1;
>     }
>     /* If rollup, calculate the upper sum levels */

Thanks,
Roy
Thread
bzr commit into mysql-5.5-bugteam branch (Georgi.Kodinov:3135) Bug#57954Georgi Kodinov2 Dec
  • Re: bzr commit into mysql-5.5-bugteam branch (Georgi.Kodinov:3135)Bug#57954Guilhem Bichot2 Dec
  • Re: bzr commit into mysql-5.5-bugteam branch (Georgi.Kodinov:3135)Bug#57954Roy Lyseng6 Dec