From: Date: August 17 2007 4:30pm Subject: bk commit into 5.0 tree (evgen:1.2495) BUG#30245 List-Archive: http://lists.mysql.com/commits/32699 X-Bug: 30245 Message-Id: <20070817143046.AD12322CC51@moonbone.moonbone.local> Below is the list of changes that have just been committed into a local 5.0 repository of evgen. When evgen does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-08-17 18:30:41+04:00, evgen@stripped +3 -0 Bug#30245: A wrong type of a BIT field is reported when grouped by it. HEAP tables can't index BIT fields. Due to this when grouping by such fields is needed they are converted to a fields of the LONG type when temporary table is being created. But a side effect of this is that a wrong type of BIT fields is returned to a client. Now the JOIN::prepare and the create_distinct_group functions are create additional hidden copy of BIT fields to preserve original fields untouched. New hidden fields are used for grouping instead. mysql-test/r/type_bit.result@stripped, 2007-08-17 18:29:10+04:00, evgen@stripped +15 -0 Added a test case for the bug#30245: A wrong type of a BIT field is reported when grouped by it. mysql-test/t/type_bit.test@stripped, 2007-08-17 18:28:48+04:00, evgen@stripped +13 -0 Added a test case for the bug#30245: A wrong type of a BIT field is reported when grouped by it. sql/sql_select.cc@stripped, 2007-08-17 18:29:30+04:00, evgen@stripped +53 -9 Bug#30245: A wrong type of a BIT field is reported when grouped by it. Now the JOIN::prepare and the create_distinct_group functions are create additional hidden copy of BIT fields to preserve original fields untouched. New hidden fields are used for grouping instead. diff -Nrup a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result --- a/mysql-test/r/type_bit.result 2007-08-06 12:01:16 +04:00 +++ b/mysql-test/r/type_bit.result 2007-08-17 18:29:10 +04:00 @@ -642,4 +642,19 @@ b+0 COUNT(DISTINCT a) 1 1 3 2 DROP TABLE t1; +CREATE TABLE t1 (b BIT); +INSERT INTO t1 (b) VALUES (1), (0); +SELECT DISTINCT b FROM t1; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 t1 b b 16 1 1 Y 32 0 63 +b +# +# +SELECT b FROM t1 GROUP BY b; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 t1 b b 16 1 1 Y 32 0 63 +b +# +# +DROP TABLE t1; End of 5.0 tests diff -Nrup a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test --- a/mysql-test/t/type_bit.test 2007-08-06 12:01:17 +04:00 +++ b/mysql-test/t/type_bit.test 2007-08-17 18:28:48 +04:00 @@ -291,4 +291,17 @@ INSERT INTO t1 (b, a) VALUES (1, 1), (3, SELECT b+0, COUNT(DISTINCT a) FROM t1 GROUP BY b; DROP TABLE t1; +# +# Bug#30245: A wrong type of a BIT field is reported when grouped by it. +# +CREATE TABLE t1 (b BIT); +INSERT INTO t1 (b) VALUES (1), (0); +--enable_metadata +--replace_column 1 # +SELECT DISTINCT b FROM t1; +--replace_column 1 # +SELECT b FROM t1 GROUP BY b; +--disable_metadata +DROP TABLE t1; + --echo End of 5.0 tests diff -Nrup a/sql/sql_select.cc b/sql/sql_select.cc --- a/sql/sql_select.cc 2007-07-31 15:24:13 +04:00 +++ b/sql/sql_select.cc 2007-08-17 18:29:30 +04:00 @@ -189,6 +189,7 @@ static bool setup_new_fields(THD *thd, L List &all_fields, ORDER *new_order); static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array, ORDER *order, List &fields, + List &all_fields, bool *all_order_by_fields_used); static bool test_if_subpart(ORDER *a,ORDER *b); static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables); @@ -537,6 +538,28 @@ JOIN::prepare(Item ***rref_pointer_array fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array)) DBUG_RETURN(-1); + if (group) + { + /* + Because HEAP tables can't index BIT fields we need to use an + additional hidden field for grouping because later it will be + converted to a LONG field. Original field will remain of the + BIT type and will be returned to a client. + */ + for (ORDER *ord= group_list; ord; ord= ord->next) + { + if ((*ord->item)->type() == Item::FIELD_ITEM && + (*ord->item)->field_type() == MYSQL_TYPE_BIT) + { + Item_field *field= new Item_field(thd, *(Item_field**)ord->item); + int el= all_fields.elements; + ref_pointer_array[el]= field; + all_fields.push_front(field); + ord->item= ref_pointer_array + el; + } + } + } + if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */ DBUG_RETURN(-1); @@ -1068,12 +1091,13 @@ JOIN::optimize() if (order) skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1); if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array, - order, fields_list, + order, fields_list, all_fields, &all_order_fields_used))) { bool skip_group= (skip_sort_order && test_if_skip_sort_order(tab, group_list, select_limit, 1) != 0); + count_field_types(select_lex, &tmp_table_param, all_fields, 0); if ((skip_group && all_order_fields_used) || select_limit == HA_POS_ERROR || (order && !skip_sort_order)) @@ -13646,11 +13670,12 @@ setup_new_fields(THD *thd, List &f static ORDER * create_distinct_group(THD *thd, Item **ref_pointer_array, - ORDER *order_list, List &fields, + ORDER *order_list, List &fields, + List &all_fields, bool *all_order_by_fields_used) { List_iterator li(fields); - Item *item; + Item *item, **orig_ref_pointer_array= ref_pointer_array; ORDER *order,*group,**prev; *all_order_by_fields_used= 1; @@ -13690,12 +13715,31 @@ create_distinct_group(THD *thd, Item **r ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER)); if (!ord) return 0; - /* - We have here only field_list (not all_field_list), so we can use - simple indexing of ref_pointer_array (order in the array and in the - list are same) - */ - ord->item= ref_pointer_array; + + if (item->type() == Item::FIELD_ITEM && + item->field_type() == MYSQL_TYPE_BIT) + { + /* + Because HEAP tables can't index BIT fields we need to use an + additional hidden field for grouping because later it will be + converted to a LONG field. Original field will remain of the + BIT type and will be returned to a client. + */ + Item_field *new_item= new Item_field(thd, (Item_field*)item); + int el= all_fields.elements; + orig_ref_pointer_array[el]= new_item; + all_fields.push_front(new_item); + ord->item= orig_ref_pointer_array + el; + } + else + { + /* + We have here only field_list (not all_field_list), so we can use + simple indexing of ref_pointer_array (order in the array and in the + list are same) + */ + ord->item= ref_pointer_array; + } ord->asc=1; *prev=ord; prev= &ord->next;