1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Fixed a bug in key optimizing handling where the expression

WHERE column_name = key_column_name was calculated as true
for NULL values.


Docs/manual.texi:
  Changelog
mysql-test/r/distinct.result:
  Updated results caused by bug fix.
mysql-test/r/null_key.result:
  New tests
mysql-test/t/null_key.test:
  New tests
sql/sql_select.cc:
  Additional change for previous changeset for using BLOB in GROUP BY
This commit is contained in:
unknown
2002-10-14 17:04:12 +03:00
parent 61632073ac
commit a86c172f58
6 changed files with 79 additions and 5 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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,
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,
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,
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,
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,
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,
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)
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();

View File

@ -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