Commit ddd90017 authored by Georgi Kodinov's avatar Georgi Kodinov

Bug #42760: Select doesn't return desired results when we have null

 values
 
 We should re-set the access method functions when changing the access
 method when switching to another index to avoid sorting.
 
 Fixed by doing a little re-engineering : encapsulating all the function
 assignment into a special function and calling it when flipping the 
 indexes.
parent 58ee6c80
...@@ -1092,3 +1092,24 @@ FROM t3; ...@@ -1092,3 +1092,24 @@ FROM t3;
2 2
NULL NULL
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
#
# Bug #42760: Select doesn't return desired results when we have null
# values
#
CREATE TABLE t1 (
a INT,
c INT,
UNIQUE KEY a_c (a,c),
KEY (a));
INSERT INTO t1 VALUES (1, 10), (2, NULL);
# Must use ref-or-null on the a_c index
EXPLAIN
SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref_or_null a_c,a a_c 10 const,const 1 Using where
# Must return 1 row
SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c;
col
1
DROP TABLE t1;
End of 5.0 tests
...@@ -756,3 +756,29 @@ SELECT ...@@ -756,3 +756,29 @@ SELECT
FROM t3; FROM t3;
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
--echo #
--echo # Bug #42760: Select doesn't return desired results when we have null
--echo # values
--echo #
CREATE TABLE t1 (
a INT,
c INT,
UNIQUE KEY a_c (a,c),
KEY (a));
INSERT INTO t1 VALUES (1, 10), (2, NULL);
--echo # Must use ref-or-null on the a_c index
EXPLAIN
SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c;
--echo # Must return 1 row
SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c;
DROP TABLE t1;
--echo End of 5.0 tests
...@@ -6202,6 +6202,56 @@ void rr_unlock_row(st_join_table *tab) ...@@ -6202,6 +6202,56 @@ void rr_unlock_row(st_join_table *tab)
/**
Pick the appropriate access method functions
Sets the functions for the selected table access method
@param tab Table reference to put access method
*/
static void
pick_table_access_method(JOIN_TAB *tab)
{
switch (tab->type)
{
case JT_REF:
tab->read_first_record= join_read_always_key;
tab->read_record.read_record= join_read_next_same;
break;
case JT_REF_OR_NULL:
tab->read_first_record= join_read_always_key_or_null;
tab->read_record.read_record= join_read_next_same_or_null;
break;
case JT_CONST:
tab->read_first_record= join_read_const;
tab->read_record.read_record= join_no_more_records;
break;
case JT_EQ_REF:
tab->read_first_record= join_read_key;
tab->read_record.read_record= join_no_more_records;
break;
case JT_FT:
tab->read_first_record= join_ft_read_first;
tab->read_record.read_record= join_ft_read_next;
break;
case JT_SYSTEM:
tab->read_first_record= join_read_system;
tab->read_record.read_record= join_no_more_records;
break;
/* keep gcc happy */
default:
break;
}
}
static void static void
make_join_readinfo(JOIN *join, ulonglong options) make_join_readinfo(JOIN *join, ulonglong options)
{ {
...@@ -6234,45 +6284,15 @@ make_join_readinfo(JOIN *join, ulonglong options) ...@@ -6234,45 +6284,15 @@ make_join_readinfo(JOIN *join, ulonglong options)
(join->sort_by_table == (TABLE *) 1 && i != join->const_tables))) (join->sort_by_table == (TABLE *) 1 && i != join->const_tables)))
ordered_set= 1; ordered_set= 1;
table->status=STATUS_NO_RECORD;
pick_table_access_method (tab);
switch (tab->type) { switch (tab->type) {
case JT_SYSTEM: // Only happens with left join
table->status=STATUS_NO_RECORD;
tab->read_first_record= join_read_system;
tab->read_record.read_record= join_no_more_records;
break;
case JT_CONST: // Only happens with left join
table->status=STATUS_NO_RECORD;
tab->read_first_record= join_read_const;
tab->read_record.read_record= join_no_more_records;
if (table->used_keys.is_set(tab->ref.key) &&
!table->no_keyread)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
}
break;
case JT_EQ_REF: case JT_EQ_REF:
table->status=STATUS_NO_RECORD;
if (tab->select)
{
delete tab->select->quick;
tab->select->quick=0;
}
delete tab->quick;
tab->quick=0;
tab->read_first_record= join_read_key;
tab->read_record.unlock_row= join_read_key_unlock_row; tab->read_record.unlock_row= join_read_key_unlock_row;
tab->read_record.read_record= join_no_more_records; /* fall through */
if (table->used_keys.is_set(tab->ref.key) &&
!table->no_keyread)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
}
break;
case JT_REF_OR_NULL: case JT_REF_OR_NULL:
case JT_REF: case JT_REF:
table->status=STATUS_NO_RECORD;
if (tab->select) if (tab->select)
{ {
delete tab->select->quick; delete tab->select->quick;
...@@ -6280,34 +6300,20 @@ make_join_readinfo(JOIN *join, ulonglong options) ...@@ -6280,34 +6300,20 @@ make_join_readinfo(JOIN *join, ulonglong options)
} }
delete tab->quick; delete tab->quick;
tab->quick=0; tab->quick=0;
/* fall through */
case JT_CONST: // Only happens with left join
if (table->used_keys.is_set(tab->ref.key) && if (table->used_keys.is_set(tab->ref.key) &&
!table->no_keyread) !table->no_keyread)
{ {
table->key_read=1; table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD); table->file->extra(HA_EXTRA_KEYREAD);
} }
if (tab->type == JT_REF)
{
tab->read_first_record= join_read_always_key;
tab->read_record.read_record= join_read_next_same;
}
else
{
tab->read_first_record= join_read_always_key_or_null;
tab->read_record.read_record= join_read_next_same_or_null;
}
break;
case JT_FT:
table->status=STATUS_NO_RECORD;
tab->read_first_record= join_ft_read_first;
tab->read_record.read_record= join_ft_read_next;
break; break;
case JT_ALL: case JT_ALL:
/* /*
If previous table use cache If previous table use cache
If the incoming data set is already sorted don't use cache. If the incoming data set is already sorted don't use cache.
*/ */
table->status=STATUS_NO_RECORD;
if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) && if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
tab->use_quick != 2 && !tab->first_inner && !ordered_set) tab->use_quick != 2 && !tab->first_inner && !ordered_set)
{ {
...@@ -6381,6 +6387,9 @@ make_join_readinfo(JOIN *join, ulonglong options) ...@@ -6381,6 +6387,9 @@ make_join_readinfo(JOIN *join, ulonglong options)
} }
} }
break; break;
case JT_FT:
case JT_SYSTEM:
break;
default: default:
DBUG_PRINT("error",("Table type %d found",tab->type)); /* purecov: deadcode */ DBUG_PRINT("error",("Table type %d found",tab->type)); /* purecov: deadcode */
break; /* purecov: deadcode */ break; /* purecov: deadcode */
...@@ -12753,6 +12762,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -12753,6 +12762,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if (create_ref_for_key(tab->join, tab, keyuse, if (create_ref_for_key(tab->join, tab, keyuse,
tab->join->const_table_map)) tab->join->const_table_map))
DBUG_RETURN(0); DBUG_RETURN(0);
pick_table_access_method(tab);
} }
else else
{ {
......
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