Commit eccc114a authored by unknown's avatar unknown

fix for the bug #2419: order by ignores rows.

null_ref_key moved to TABLE_REF.
new null range created if necessary.


mysql-test/r/order_by.result:
  fix for the bug #2419: order by ignores rows
mysql-test/t/order_by.test:
  fix for the bug #2419: order by ignores rows
sql/item_subselect.cc:
  fix for the bug #2419: order by ignores rows
sql/opt_range.cc:
  fix for the bug #2419: order by ignores rows
sql/sql_select.cc:
  fix for the bug #2419: order by ignores rows
sql/sql_select.h:
  fix for the bug #2419: order by ignores rows
parent 2f26b9c4
...@@ -590,3 +590,24 @@ SELECT id FROM t1 WHERE id <11984 AND menu =2 ORDER BY id DESC LIMIT 1 ; ...@@ -590,3 +590,24 @@ SELECT id FROM t1 WHERE id <11984 AND menu =2 ORDER BY id DESC LIMIT 1 ;
id id
11392 11392
drop table t1; drop table t1;
create table t1(a int, b int, index(b));
insert into t1 values (2, 1), (1, 1), (4, NULL), (3, NULL), (6, 2), (5, 2);
explain select * from t1 where b=1 or b is null order by a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null b b 5 const 3 Using where; Using filesort
select * from t1 where b=1 or b is null order by a;
a b
1 1
2 1
3 NULL
4 NULL
explain select * from t1 where b=2 or b is null order by a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null b b 5 const 4 Using where; Using filesort
select * from t1 where b=2 or b is null order by a;
a b
3 NULL
4 NULL
5 2
6 2
drop table t1;
...@@ -381,3 +381,15 @@ CREATE TABLE t1 ( id smallint(6) unsigned NOT NULL default '0', menu tinyint(4 ...@@ -381,3 +381,15 @@ CREATE TABLE t1 ( id smallint(6) unsigned NOT NULL default '0', menu tinyint(4
INSERT INTO t1 VALUES (11384, 2),(11392, 2); INSERT INTO t1 VALUES (11384, 2),(11392, 2);
SELECT id FROM t1 WHERE id <11984 AND menu =2 ORDER BY id DESC LIMIT 1 ; SELECT id FROM t1 WHERE id <11984 AND menu =2 ORDER BY id DESC LIMIT 1 ;
drop table t1; drop table t1;
#
# REF_OR_NULL optimization + filesort (bug #2419)
#
create table t1(a int, b int, index(b));
insert into t1 values (2, 1), (1, 1), (4, NULL), (3, NULL), (6, 2), (5, 2);
explain select * from t1 where b=1 or b is null order by a;
select * from t1 where b=1 or b is null order by a;
explain select * from t1 where b=2 or b is null order by a;
select * from t1 where b=2 or b is null order by a;
drop table t1;
...@@ -1110,7 +1110,7 @@ int subselect_indexsubquery_engine::exec() ...@@ -1110,7 +1110,7 @@ int subselect_indexsubquery_engine::exec()
if (check_null) if (check_null)
{ {
/* We need to check for NULL if there wasn't a matching value */ /* We need to check for NULL if there wasn't a matching value */
*tab->null_ref_key= 0; // Search first for not null *tab->ref.null_ref_key= 0; // Search first for not null
((Item_in_subselect *) item)->was_null= 0; ((Item_in_subselect *) item)->was_null= 0;
} }
...@@ -1155,7 +1155,7 @@ int subselect_indexsubquery_engine::exec() ...@@ -1155,7 +1155,7 @@ int subselect_indexsubquery_engine::exec()
{ {
if (!check_null || null_finding) if (!check_null || null_finding)
break; /* We don't need to check nulls */ break; /* We don't need to check nulls */
*tab->null_ref_key= 1; *tab->ref.null_ref_key= 1;
null_finding= 1; null_finding= 1;
/* Check if there exists a row with a null value in the index */ /* Check if there exists a row with a null value in the index */
if ((error= (safe_index_read(tab) == 1))) if ((error= (safe_index_read(tab) == 1)))
......
...@@ -2513,8 +2513,25 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref) ...@@ -2513,8 +2513,25 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
key_part->part_length+=HA_KEY_BLOB_LENGTH; key_part->part_length+=HA_KEY_BLOB_LENGTH;
key_part->null_bit= key_info->key_part[part].null_bit; key_part->null_bit= key_info->key_part[part].null_bit;
} }
if (!quick->ranges.push_back(range)) if (quick->ranges.push_back(range))
return quick; goto err;
if (ref->null_ref_key)
{
QUICK_RANGE *null_range;
*ref->null_ref_key= 1; // Set null byte then create a range
if (!(null_range= new QUICK_RANGE(ref->key_buff, ref->key_length,
ref->key_buff, ref->key_length,
EQ_RANGE)))
goto err;
*ref->null_ref_key= 0; // Clear null byte
/* Do we need to do something with key_parts here? Looks like we don't */
if (quick->ranges.push_back(null_range))
goto err;
}
return quick;
err: err:
delete quick; delete quick;
......
...@@ -860,8 +860,10 @@ JOIN::optimize() ...@@ -860,8 +860,10 @@ JOIN::optimize()
as in other cases the join is done before the sort. as in other cases the join is done before the sort.
*/ */
if (const_tables != tables && if (const_tables != tables &&
(order || group_list) && join_tab[const_tables].type != JT_ALL && (order || group_list) &&
join_tab[const_tables].type != JT_ALL &&
join_tab[const_tables].type != JT_FT && join_tab[const_tables].type != JT_FT &&
join_tab[const_tables].type != JT_REF_OR_NULL &&
(order && simple_order || group_list && simple_group)) (order && simple_order || group_list && simple_group))
{ {
if (add_ref_to_table_cond(thd,&join_tab[const_tables])) if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
...@@ -3257,7 +3259,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, ...@@ -3257,7 +3259,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
{ {
/* Must read with repeat */ /* Must read with repeat */
j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF; j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
j->null_ref_key= null_ref_key; j->ref.null_ref_key= null_ref_key;
} }
else if (ref_key == j->ref.key_copy) else if (ref_key == j->ref.key_copy)
{ {
...@@ -6208,12 +6210,12 @@ join_read_always_key_or_null(JOIN_TAB *tab) ...@@ -6208,12 +6210,12 @@ join_read_always_key_or_null(JOIN_TAB *tab)
int res; int res;
/* First read according to key which is NOT NULL */ /* First read according to key which is NOT NULL */
*tab->null_ref_key=0; *tab->ref.null_ref_key= 0; // Clear null byte
if ((res= join_read_always_key(tab)) >= 0) if ((res= join_read_always_key(tab)) >= 0)
return res; return res;
/* Then read key with null value */ /* Then read key with null value */
*tab->null_ref_key= 1; *tab->ref.null_ref_key= 1; // Set null byte
return safe_index_read(tab); return safe_index_read(tab);
} }
...@@ -6227,10 +6229,10 @@ join_read_next_same_or_null(READ_RECORD *info) ...@@ -6227,10 +6229,10 @@ join_read_next_same_or_null(READ_RECORD *info)
JOIN_TAB *tab= info->table->reginfo.join_tab; JOIN_TAB *tab= info->table->reginfo.join_tab;
/* Test if we have already done a read after null key */ /* Test if we have already done a read after null key */
if (*tab->null_ref_key) if (*tab->ref.null_ref_key)
return -1; // All keys read return -1; // All keys read
*tab->null_ref_key= 1; // Read null key *tab->ref.null_ref_key= 1; // Set null byte
return safe_index_read(tab); return safe_index_read(tab); // then read null keys
} }
......
...@@ -46,6 +46,8 @@ typedef struct st_table_ref ...@@ -46,6 +46,8 @@ typedef struct st_table_ref
store_key **key_copy; // store_key **key_copy; //
Item **items; // val()'s for each keypart Item **items; // val()'s for each keypart
table_map depend_map; // Table depends on these tables. table_map depend_map; // Table depends on these tables.
byte *null_ref_key; // null byte position in the key_buf.
// used for REF_OR_NULL optimization.
} TABLE_REF; } TABLE_REF;
/* /*
...@@ -88,7 +90,6 @@ typedef struct st_join_table { ...@@ -88,7 +90,6 @@ typedef struct st_join_table {
QUICK_SELECT *quick; QUICK_SELECT *quick;
Item *on_expr; Item *on_expr;
const char *info; const char *info;
byte *null_ref_key;
int (*read_first_record)(struct st_join_table *tab); int (*read_first_record)(struct st_join_table *tab);
int (*next_select)(JOIN *,struct st_join_table *,bool); int (*next_select)(JOIN *,struct st_join_table *,bool);
READ_RECORD read_record; READ_RECORD read_record;
......
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