diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result index 8d7074cd270..e1bbf5adb79 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -1039,4 +1039,14 @@ count(distinct case when id<=63 then id end) 63 drop table tb; SET @@tmp_table_size= @tmp_table_size_save; +# +# MDEV-14695: Assertion `n < m_size' failed in Bounds_checked_array::operator +# +CREATE TABLE t1 (b1 BIT, b2 BIT, b3 BIT, b4 BIT , b5 BIT, b6 BIT); +INSERT INTO t1 VALUES (1,0,0,1,0,1),(0,1,0,0,1,0); +SELECT DISTINCT b1+'0', b2+'0', b3+'0', b4+'0', b5+'0', b6 +'0' FROM t1; +b1+'0' b2+'0' b3+'0' b4+'0' b5+'0' b6 +'0' +1 0 0 1 0 1 +0 1 0 0 1 0 +DROP TABLE t1; End of 5.5 tests diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test index 7cf3d6810bb..c11f8b501bc 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -790,4 +790,12 @@ drop table tb; SET @@tmp_table_size= @tmp_table_size_save; +--echo # +--echo # MDEV-14695: Assertion `n < m_size' failed in Bounds_checked_array::operator +--echo # + +CREATE TABLE t1 (b1 BIT, b2 BIT, b3 BIT, b4 BIT , b5 BIT, b6 BIT); +INSERT INTO t1 VALUES (1,0,0,1,0,1),(0,1,0,0,1,0); +SELECT DISTINCT b1+'0', b2+'0', b3+'0', b4+'0', b5+'0', b6 +'0' FROM t1; +DROP TABLE t1; --echo End of 5.5 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 95ff41cb6f4..4ba74804a05 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6919,7 +6919,7 @@ static bool setup_natural_join_row_types(THD *thd, int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, List *sum_func_list, - uint wild_num) + uint wild_num, uint *hidden_bit_fields) { if (!wild_num) return(0); @@ -6960,7 +6960,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, else if (insert_fields(thd, ((Item_field*) item)->context, ((Item_field*) item)->db_name, ((Item_field*) item)->table_name, &it, - any_privileges)) + any_privileges, hidden_bit_fields)) { if (arena) thd->restore_active_arena(arena, &backup); @@ -7425,7 +7425,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, bool insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, const char *table_name, List_iterator *it, - bool any_privileges) + bool any_privileges, uint *hidden_bit_fields) { Field_iterator_table_ref field_iterator; bool found; @@ -7545,6 +7545,9 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, else it->after(item); /* Add 'item' to the SELECT list. */ + if (item->type() == Item::FIELD_ITEM && item->field_type() == MYSQL_TYPE_BIT) + (*hidden_bit_fields)++; + #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Set privilege information for the fields of newly created views. diff --git a/sql/sql_base.h b/sql/sql_base.h index d6063f1b771..c59a24e4272 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -154,11 +154,12 @@ bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, enum trg_event_type event); bool insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, const char *table_name, - List_iterator *it, bool any_privileges); + List_iterator *it, bool any_privileges, + uint *hidden_bit_fields); void make_leaves_list(THD *thd, List &list, TABLE_LIST *tables, bool full_table_list, TABLE_LIST *boundary); int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, - List *sum_func_list, uint wild_num); + List *sum_func_list, uint wild_num, uint * hidden_bit_fields); bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, List &item, enum_mark_columns mark_used_columns, List *sum_func_list, List *pre_fix, diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 7b7a7e3f804..48509a46ccb 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -760,7 +760,8 @@ l select_lex->leaf_tables, FALSE, DELETE_ACL, SELECT_ACL, TRUE)) DBUG_RETURN(TRUE); - if ((wild_num && setup_wild(thd, table_list, field_list, NULL, wild_num)) || + if ((wild_num && setup_wild(thd, table_list, field_list, NULL, wild_num, + &select_lex->hidden_bit_fields)) || setup_fields(thd, Ref_ptr_array(), field_list, MARK_COLUMNS_READ, NULL, NULL, 0) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) || diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 3e36cac96b9..1752689b385 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2126,6 +2126,7 @@ void st_select_lex::init_query() select_n_having_items= 0; n_sum_items= 0; n_child_sum_items= 0; + hidden_bit_fields= 0; subquery_in_having= explicit_limit= 0; is_item_list_lookup= 0; first_execution= 1; @@ -2673,6 +2674,10 @@ ulong st_select_lex::get_table_join_options() bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) { + + if (!((options & SELECT_DISTINCT) && !group_list.elements)) + hidden_bit_fields= 0; + // find_order_in_list() may need some extra space, so multiply by two. order_group_num*= 2; @@ -2687,7 +2692,8 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) select_n_reserved + select_n_having_items + select_n_where_fields + - order_group_num) * 5; + order_group_num + + hidden_bit_fields) * 5; if (!ref_pointer_array.is_null()) { /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 6d281930d1f..68e1885f5e9 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -862,6 +862,11 @@ public: uint select_n_where_fields; /* reserved for exists 2 in */ uint select_n_reserved; + /* + it counts the number of bit fields in the SELECT list. These are used when DISTINCT is + converted to a GROUP BY involving BIT fields. + */ + uint hidden_bit_fields; enum_parsing_place parsing_place; /* where we are parsing expression */ enum_parsing_place context_analysis_place; /* where we are in prepare */ bool with_sum_func; /* sum function indicator */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4cd4754596b..1d5abd6a36f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -799,7 +799,9 @@ JOIN::prepare(TABLE_LIST *tables_init, select_lex != select_lex->master_unit()->global_parameters()) real_og_num+= select_lex->order_list.elements; - if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num)) + DBUG_ASSERT(select_lex->hidden_bit_fields == 0); + if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num, + &select_lex->hidden_bit_fields)) DBUG_RETURN(-1); if (select_lex->setup_ref_array(thd, real_og_num)) DBUG_RETURN(-1); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 3fe8a24f8bd..3fe90564000 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1474,6 +1474,7 @@ bool st_select_lex::cleanup() } inner_refs_list.empty(); exclude_from_table_unique_test= FALSE; + hidden_bit_fields= 0; DBUG_RETURN(error); }