1
0
mirror of https://github.com/MariaDB/server.git synced 2026-01-06 05:22:24 +03:00

Fixed bug with GROUP BY on NULL fields.

(Merge of code from 4.0)
This commit is contained in:
monty@mashka.mysql.fi
2002-08-05 18:10:53 +03:00
parent 8a38deea44
commit 621b5da80e
9 changed files with 83 additions and 27 deletions

View File

@@ -46928,6 +46928,9 @@ not yet 100% confident in this code.
@appendixsubsec Changes in release 3.23.52
@itemize @bullet
@item
Fixed problem with @code{GROUP BY} on result with expression that created a
@code{BLOB} field.
@item
Fixed problem with privilege tables when downgrading from 4.0.2 to 3.23.
@item
Fixed thread bug in @code{SLAVE START} and @code{SLAVE STOP}.

View File

@@ -134,6 +134,7 @@ enum ha_base_keytype {
#define HA_BINARY_PACK_KEY 32 /* Packing of all keys to prev key */
#define HA_FULLTEXT 128 /* SerG: for full-text search */
#define HA_UNIQUE_CHECK 256 /* Check the key for uniqueness */
#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
/* Automatic bits in key-flag */
@@ -235,6 +236,7 @@ enum ha_base_keytype {
#define SEARCH_UPDATE 64
#define SEARCH_PREFIX 128
#define SEARCH_LAST 256
#define SEARCH_NULL_ARE_EQUAL 32768 /* NULL in keys are equal */
/* bits in opt_flag */
#define QUICK_USED 1

View File

@@ -110,6 +110,9 @@ typedef struct st_vio Vio;
#endif
#endif
#define MAX_CHAR_WIDTH 255 /* Max length for a CHAR colum */
#define MAX_BLOB_WIDTH 8192 /* Default width for blob */
typedef struct st_net {
Vio* vio;
my_socket fd; /* For Perl DBI/dbd */

View File

@@ -107,8 +107,9 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
}
else
{
if (nextflag & SEARCH_FIND && (!(keyinfo->flag & HA_NOSAME)
|| key_len) && nod_flag)
if ((nextflag & SEARCH_FIND) && nod_flag &&
((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME ||
key_len))
{
if ((error=_mi_search(info,keyinfo,key,key_len,SEARCH_FIND,
_mi_kpos(nod_flag,keypos))) >= 0 ||

View File

@@ -263,7 +263,11 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (keyinfo->flag & HA_SORT_ALLOWS_SAME)
comp_flag=SEARCH_BIGGER; /* Put after same key */
else if (keyinfo->flag & HA_NOSAME)
{
comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */
if (keyinfo->flag & HA_NULL_ARE_EQUAL)
comp_flag|= SEARCH_NULL_ARE_EQUAL;
}
else
comp_flag=SEARCH_SAME; /* Keys in rec-pos order */

View File

@@ -68,3 +68,19 @@ One Two sum(Four)
1 1 16
1 2 16
1 3 16
xID xID1
1 1
2 2
2 2
3 134
3 134
3 134
4 185
4 185
4 185
4 185
xID xID1 Level
1 1 *
2 2 **
3 134 ***
4 185 ****

View File

@@ -259,3 +259,14 @@ insert into t1 values (1,3,3,4);
insert into t1 values (1,3,4,4);
select One, Two, sum(Four) from t1 group by One,Two;
drop table if exists t1;
#
# The GROUP BY returned rows in wrong order in 3.23.51
#
CREATE TABLE t1 (ID1 int, ID2 int, ID int NOT NULL AUTO_INCREMENT,PRIMARY KEY(ID
));
insert into t1 values (1,244,NULL),(2,243,NULL),(134,223,NULL),(185,186,NULL);
select S.ID as xID, S.ID1 as xID1 from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2;
select S.ID as xID, S.ID1 as xID1, repeat('*',count(distinct yS.ID)) as Level from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2 group by xID order by xID1;
drop table t1;

View File

@@ -2222,18 +2222,18 @@ int setup_ftfuncs(THD *thd)
return 0;
}
int init_ftfuncs(THD *thd, bool no_order)
{
List_iterator<Item_func_match> li(thd->lex.ftfunc_list);
Item_func_match *ifm;
DBUG_PRINT("info",("Performing FULLTEXT search"));
thd->proc_info="FULLTEXT initialization";
while ((ifm=li++))
if (thd->lex.ftfunc_list.elements)
{
ifm->init_search(no_order);
}
List_iterator<Item_func_match> li(thd->lex.ftfunc_list);
Item_func_match *ifm;
DBUG_PRINT("info",("Performing FULLTEXT search"));
thd->proc_info="FULLTEXT initialization";
while ((ifm=li++))
ifm->init_search(no_order);
}
return 0;
}

View File

@@ -153,7 +153,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
uint select_options,select_result *result)
{
TABLE *tmp_table;
int error,tmp;
int error, tmp_error;
bool need_tmp,hidden_group_fields;
bool simple_order,simple_group,no_order;
Item::cond_result cond_value;
@@ -380,9 +380,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
thd->fatal_error)
goto err;
thd->proc_info="preparing";
if ((tmp=join_read_const_tables(&join)) > 0)
if ((tmp_error=join_read_const_tables(&join)) > 0)
goto err;
if (tmp && !(select_options & SELECT_DESCRIBE))
if (tmp_error && !(select_options & SELECT_DESCRIBE))
{
error=return_zero_rows(result,tables,fields,
join.tmp_table_param.sum_func_count != 0 &&
@@ -701,9 +701,11 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
group=0;
}
thd->proc_info="Copying to group table";
tmp_error= -1;
if (make_sum_func_list(&join,all_fields) ||
do_select(&join,(List<Item> *) 0,tmp_table2,0))
(tmp_error=do_select(&join,(List<Item> *) 0,tmp_table2,0)))
{
error=tmp_error;
free_tmp_table(thd,tmp_table2);
goto err; /* purecov: inspected */
}
@@ -3347,7 +3349,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!param->quick_group)
group=0; // Can't use group key
else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
{
(*tmp->item)->marker=4; // Store null in key
if ((*tmp->item)->max_length >= MAX_CHAR_WIDTH)
using_unique_constraint=1;
}
if (param->group_length >= MAX_BLOB_WIDTH)
using_unique_constraint=1;
if (group)
@@ -3477,7 +3483,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
field_count= (uint) (reg_field - table->field);
/* If result table is small; use a heap */
if (blob_count || using_unique_constraint ||
if (blob_count || using_unique_constraint || group_null_items ||
(select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
OPTION_BIG_TABLES)
{
@@ -3499,7 +3505,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (blob_count == 0)
{
/* We need to ensure that first byte is not 0 for the delete link */
if (hidden_null_count)
if (param->hidden_field_count)
hidden_null_count++;
else
null_count++;
@@ -3633,14 +3639,17 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (maybe_null)
{
/*
To be able to group on NULL, we move the null bit to be
just before the column and extend the key to cover the null bit
To be able to group on NULL, we reserve place in group_buff
for the NULL flag just before the column.
The field data is after this flag.
The NULL flag is updated by 'end_update()' and 'end_write()'
*/
*group_buff= 0; // Init null byte
key_part_info->offset--;
key_part_info->length++;
group->field->move_field((char*) group_buff+1, (uchar*) group_buff,
1);
keyinfo->flags|= HA_NULL_ARE_EQUAL; // def. that NULL == NULL
key_part_info->null_bit=field->null_bit;
key_part_info->null_offset= (uint) (field->null_ptr -
(uchar*) table->record[0]);
group->field->move_field((char*) ++group->buff);
group_buff++;
}
else
group->field->move_field((char*) group_buff);
@@ -3820,11 +3829,17 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
keyinfo->key_part[i].length > 4)
seg->flag|=HA_SPACE_PACK;
}
if (using_unique_constraint &&
!(field->flags & NOT_NULL_FLAG))
if (!(field->flags & NOT_NULL_FLAG))
{
seg->null_bit= field->null_bit;
seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]);
/*
We are using a GROUP BY on something that contains NULL
In this case we have to tell MyISAM that two NULL should
on INSERT be compared as equal
*/
if (!using_unique_constraint)
keydef.flag|= HA_NULL_ARE_EQUAL;
}
}
}
@@ -4797,8 +4812,9 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
Item *item= *group->item;
item->save_org_in_field(group->field);
/* Store in the used key if the field was 0 */
if (item->maybe_null)
group->buff[0]=item->null_value ? 0: 1; // Save reversed value
group->buff[-1]=item->null_value ? 1 : 0;
}
// table->file->index_init(0);
if (!table->file->index_read(table->record[1],