#At file:///home/kgeorge/mysql/work/B42760-5.0-bugteam/ based on revid:alexey.kopytov@stripped
2843 Georgi Kodinov 2009-11-06
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.
modified:
mysql-test/r/order_by.result
mysql-test/t/order_by.test
sql/sql_select.cc
=== modified file 'mysql-test/r/order_by.result'
--- a/mysql-test/r/order_by.result 2008-10-16 16:37:17 +0000
+++ b/mysql-test/r/order_by.result 2009-11-06 13:25:30 +0000
@@ -1092,3 +1092,24 @@ FROM t3;
2
NULL
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
=== modified file 'mysql-test/t/order_by.test'
--- a/mysql-test/t/order_by.test 2008-10-16 16:37:17 +0000
+++ b/mysql-test/t/order_by.test 2009-11-06 13:25:30 +0000
@@ -756,3 +756,29 @@ SELECT
FROM 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
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2009-11-06 06:44:01 +0000
+++ b/sql/sql_select.cc 2009-11-06 13:25:30 +0000
@@ -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
make_join_readinfo(JOIN *join, ulonglong options)
{
@@ -6234,45 +6284,15 @@ make_join_readinfo(JOIN *join, ulonglong
(join->sort_by_table == (TABLE *) 1 && i != join->const_tables)))
ordered_set= 1;
+ table->status=STATUS_NO_RECORD;
+ pick_table_access_method (tab);
+
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:
- 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.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;
+ /* fall through */
case JT_REF_OR_NULL:
case JT_REF:
- table->status=STATUS_NO_RECORD;
if (tab->select)
{
delete tab->select->quick;
@@ -6280,34 +6300,20 @@ make_join_readinfo(JOIN *join, ulonglong
}
delete tab->quick;
tab->quick=0;
+ /* fall through */
+ case JT_CONST: // Only happens with left join
if (table->used_keys.is_set(tab->ref.key) &&
!table->no_keyread)
{
table->key_read=1;
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;
case JT_ALL:
/*
If previous table 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) &&
tab->use_quick != 2 && !tab->first_inner && !ordered_set)
{
@@ -6381,8 +6387,10 @@ make_join_readinfo(JOIN *join, ulonglong
}
}
break;
+ case JT_FT: break;
default:
DBUG_PRINT("error",("Table type %d found",tab->type)); /* purecov: deadcode */
+ DBUG_ASSERT (0);
break; /* purecov: deadcode */
case JT_UNKNOWN:
case JT_MAYBE_REF:
@@ -12753,6 +12761,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
if (create_ref_for_key(tab->join, tab, keyuse,
tab->join->const_table_map))
DBUG_RETURN(0);
+
+ pick_table_access_method(tab);
}
else
{
Attachment: [text/bzr-bundle] bzr/joro@sun.com-20091106132530-7rcwk5sh95fo29jh.bundle
| Thread |
|---|
| • bzr commit into mysql-5.0-bugteam branch (joro:2843) Bug#42760 | Georgi Kodinov | 9 Nov |