Commit 68963e91 authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

Fixed a bug in key optimizing handling where the expression

WHERE column_name = key_column_name was calculated as true
for NULL values.
parent 00e86fb5
...@@ -46935,6 +46935,13 @@ Fixed reference to freed memory when doing complicated @code{GROUP BY ...@@ -46935,6 +46935,13 @@ Fixed reference to freed memory when doing complicated @code{GROUP BY
@code{send_fields}. @code{send_fields}.
@item @item
Allocate heap rows in smaller blocks to get better memory usage. Allocate heap rows in smaller blocks to get better memory usage.
@item
Fixed memory allocation bug when storing BLOB values in internal
temporary tables used for some (unlikely) @code{GROUP BY} queries.
@item
Fixed a bug in key optimizing handling where the expression
@code{WHERE column_name = key_column_name} was calculated as true
for @code{NULL} values.
@end itemize @end itemize
@node News-3.23.53, News-3.23.52, News-3.23.54, News-3.23.x @node News-3.23.53, News-3.23.52, News-3.23.54, News-3.23.x
...@@ -128,7 +128,7 @@ a ...@@ -128,7 +128,7 @@ a
1 1
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 index PRIMARY PRIMARY 4 NULL 2 Using index; Using temporary t1 index PRIMARY PRIMARY 4 NULL 2 Using index; Using temporary
t3 ref a a 5 t1.a 10 Using index; Distinct t3 ref a a 5 t1.a 10 where used; Using index; Distinct
a a
1 1
2 2
......
...@@ -120,3 +120,9 @@ id uniq_id ...@@ -120,3 +120,9 @@ id uniq_id
4 2 4 2
7 3 7 3
8 4 8 4
order_id product_id product_type
order_id product_id product_type
3d7ce39b5d4b3e3d22aaafe9b633de51 1206029 3
3d7ce39b5d4b3e3d22aaafe9b633de51 5880836 3
id id
id id
...@@ -91,3 +91,47 @@ DELETE FROM t2 WHERE uniq_id IS NULL; ...@@ -91,3 +91,47 @@ DELETE FROM t2 WHERE uniq_id IS NULL;
SELECT * FROM t1 ORDER BY uniq_id, id; SELECT * FROM t1 ORDER BY uniq_id, id;
SELECT * FROM t2 ORDER BY uniq_id, id; SELECT * FROM t2 ORDER BY uniq_id, id;
DROP table t1,t2; DROP table t1,t2;
#
# This crashed MySQL 3.23.47
#
CREATE TABLE `t1` (
`order_id` char(32) NOT NULL default '',
`product_id` char(32) NOT NULL default '',
`product_type` int(11) NOT NULL default '0',
PRIMARY KEY (`order_id`,`product_id`,`product_type`)
) TYPE=MyISAM;
CREATE TABLE `t2` (
`order_id` char(32) NOT NULL default '',
`product_id` char(32) NOT NULL default '',
`product_type` int(11) NOT NULL default '0',
PRIMARY KEY (`order_id`,`product_id`,`product_type`)
) TYPE=MyISAM;
INSERT INTO t1 (order_id, product_id, product_type) VALUES
('3d7ce39b5d4b3e3d22aaafe9b633de51',1206029, 3),
('3d7ce39b5d4b3e3d22aaafe9b633de51',5880836, 3),
('9d9aad7764b5b2c53004348ef8d34500',2315652, 3);
INSERT INTO t2 (order_id, product_id, product_type) VALUES
('9d9aad7764b5b2c53004348ef8d34500',2315652, 3);
select t1.* from t1
left join t2 using(order_id, product_id, product_type)
where t2.order_id=NULL;
select t1.* from t1
left join t2 using(order_id, product_id, product_type)
where t2.order_id is NULL;
drop table t1,t2;
#
# The last select returned wrong results in 3.23.52
#
create table t1 (id int);
insert into t1 values (null), (0);
create table t2 (id int);
insert into t2 values (null);
select * from t1, t2 where t1.id = t2.id;
alter table t1 add key id (id);
select * from t1, t2 where t1.id = t2.id;
drop table t1,t2;
...@@ -3319,7 +3319,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -3319,7 +3319,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
char *tmpname,path[FN_REFLEN]; char *tmpname,path[FN_REFLEN];
byte *pos,*group_buff; byte *pos,*group_buff;
uchar *null_flags; uchar *null_flags;
Field **reg_field,**from_field; Field **reg_field, **from_field, **blob_field;
Copy_field *copy=0; Copy_field *copy=0;
KEY *keyinfo; KEY *keyinfo;
KEY_PART_INFO *key_part_info; KEY_PART_INFO *key_part_info;
...@@ -3364,8 +3364,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -3364,8 +3364,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
hidden_field_count=param->hidden_field_count; hidden_field_count=param->hidden_field_count;
if (!my_multi_malloc(MYF(MY_WME), if (!my_multi_malloc(MYF(MY_WME),
&table,sizeof(*table), &table,sizeof(*table),
&reg_field,sizeof(Field*)*(field_count+1), &reg_field, sizeof(Field*)*(field_count+1),
&from_field,sizeof(Field*)*field_count, &blob_field, sizeof(Field*)*(field_count+1),
&from_field, sizeof(Field*)*field_count,
&copy_func,sizeof(*copy_func)*(param->func_count+1), &copy_func,sizeof(*copy_func)*(param->func_count+1),
&param->keyinfo,sizeof(*param->keyinfo), &param->keyinfo,sizeof(*param->keyinfo),
&key_part_info, &key_part_info,
...@@ -3394,6 +3395,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -3394,6 +3395,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
bzero((char*) reg_field,sizeof(Field*)*(field_count+1)); bzero((char*) reg_field,sizeof(Field*)*(field_count+1));
bzero((char*) from_field,sizeof(Field*)*field_count); bzero((char*) from_field,sizeof(Field*)*field_count);
table->field=reg_field; table->field=reg_field;
table->blob_field= (Field_blob**) blob_field;
table->real_name=table->path=tmpname; table->real_name=table->path=tmpname;
/* /*
This must be "" as field may refer to it after tempory table is dropped This must be "" as field may refer to it after tempory table is dropped
...@@ -3406,7 +3408,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -3406,7 +3408,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table->tmp_table= TMP_TABLE; table->tmp_table= TMP_TABLE;
table->db_low_byte_first=1; // True for HEAP and MyISAM table->db_low_byte_first=1; // True for HEAP and MyISAM
table->temp_pool_slot = temp_pool_slot; table->temp_pool_slot = temp_pool_slot;
table->copy_blobs= 1;
/* Calculate which type of fields we will store in the temporary table */ /* Calculate which type of fields we will store in the temporary table */
...@@ -3450,7 +3452,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -3450,7 +3452,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!(new_field->flags & NOT_NULL_FLAG)) if (!(new_field->flags & NOT_NULL_FLAG))
null_count++; null_count++;
if (new_field->flags & BLOB_FLAG) if (new_field->flags & BLOB_FLAG)
{
*blob_field++= new_field;
blob_count++; blob_count++;
}
((Item_sum*) item)->args[i]= new Item_field(new_field); ((Item_sum*) item)->args[i]= new Item_field(new_field);
} }
} }
...@@ -3472,7 +3477,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -3472,7 +3477,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!(new_field->flags & NOT_NULL_FLAG)) if (!(new_field->flags & NOT_NULL_FLAG))
null_count++; null_count++;
if (new_field->flags & BLOB_FLAG) if (new_field->flags & BLOB_FLAG)
{
*blob_field++= new_field;
blob_count++; blob_count++;
}
if (item->marker == 4 && item->maybe_null) if (item->marker == 4 && item->maybe_null)
{ {
group_null_items++; group_null_items++;
...@@ -3484,6 +3492,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -3484,6 +3492,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
hidden_null_count=null_count; hidden_null_count=null_count;
} }
field_count= (uint) (reg_field - table->field); field_count= (uint) (reg_field - table->field);
*blob_field= 0; // End marker
/* If result table is small; use a heap */ /* If result table is small; use a heap */
if (blob_count || using_unique_constraint || group_null_items || if (blob_count || using_unique_constraint || group_null_items ||
...@@ -3882,6 +3891,7 @@ free_tmp_table(THD *thd, TABLE *entry) ...@@ -3882,6 +3891,7 @@ free_tmp_table(THD *thd, TABLE *entry)
save_proc_info=thd->proc_info; save_proc_info=thd->proc_info;
thd->proc_info="removing tmp table"; thd->proc_info="removing tmp table";
free_blobs(entry);
if (entry->db_stat && entry->file) if (entry->db_stat && entry->file)
{ {
(void) entry->file->close(); (void) entry->file->close();
......
...@@ -455,6 +455,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ...@@ -455,6 +455,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
field->field_length=key_part->length; field->field_length=key_part->length;
} }
} }
/*
If the field can be NULL, don't optimize away the test
key_part_column = expression from the WHERE clause
as we need to test for NULL = NULL.
*/
if (field->real_maybe_null())
key_part->key_part_flag|= HA_PART_KEY;
} }
else else
{ // Error: shorten key { // Error: shorten key
......
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