[Commits] Rev 3680: MDEV-4817: Optimizer fails to optimize expression of the form 'FOO' IS NULL in file:///home/bell/maria/bzr/work-maria-10.0-base-merge-5.5/

sanja at montyprogram.com sanja at montyprogram.com
Mon Aug 19 12:59:33 EEST 2013


At file:///home/bell/maria/bzr/work-maria-10.0-base-merge-5.5/

------------------------------------------------------------
revno: 3680
revision-id: psergey at askmonty.org-20130731132452-5c22rbgiixvgjvqe
parent: psergey at askmonty.org-20130731093701-8qn9ow5yz3480mqu
author: Sergey Petrunya <psergey at askmonty.org>
committer: sanja at montyprogram.com
branch nick: 5.5
timestamp: Wed 2013-07-31 17:24:52 +0400
message:
  MDEV-4817: Optimizer fails to optimize expression of the form 'FOO' IS NULL
  - Modify the way Item_cond::fix_fields() and Item_cond::eval_not_null_tables() 
    calculate bitmap for Item_cond_or::not_null_tables():
    if they see a "... OR inexpensive_const_false_item OR ..." then the item can
    be ignored.
  - Updated test results. There can be more warnings produced since parts of WHERE 
    are evaluated more times.
-------------- next part --------------
=== modified file 'mysql-test/r/func_group.result'
--- a/mysql-test/r/func_group.result	2013-05-20 10:36:30 +0000
+++ b/mysql-test/r/func_group.result	2013-07-31 13:24:52 +0000
@@ -1971,6 +1971,7 @@ MIN(t2.pk)
 NULL
 Warnings:
 Warning	1292	Truncated incorrect INTEGER value: 'j'
+Warning	1292	Truncated incorrect INTEGER value: 'j'
 
 EXPLAIN
 SELECT MIN(t2.pk)
@@ -1984,6 +1985,7 @@ id	select_type	table	type	possible_keys
 2	MATERIALIZED	t2	ALL	NULL	NULL	NULL	NULL	2	
 Warnings:
 Warning	1292	Truncated incorrect INTEGER value: 'j'
+Warning	1292	Truncated incorrect INTEGER value: 'j'
 
 #
 # 2) Test that subquery materialization is setup for query with

=== modified file 'mysql-test/r/insert.result'
--- a/mysql-test/r/insert.result	2012-09-18 12:14:19 +0000
+++ b/mysql-test/r/insert.result	2013-07-31 13:24:52 +0000
@@ -663,9 +663,10 @@ Warning	1365	Division by 0
 Warning	1048	Column 'data' cannot be null
 update t1 set data='envelope' where 1/0 or 1;
 affected rows: 2
-info: Rows matched: 2  Changed: 2  Warnings: 3
+info: Rows matched: 2  Changed: 2  Warnings: 4
 Warnings:
 Warning	1365	Division by 0
+Warning	1365	Division by 0
 Warning	1265	Data truncated for column 'data' at row 1
 Warning	1265	Data truncated for column 'data' at row 2
 insert t1 (data) values (default), (1/0), ('dead beef');

=== modified file 'mysql-test/r/join_outer.result'
--- a/mysql-test/r/join_outer.result	2013-05-07 11:05:09 +0000
+++ b/mysql-test/r/join_outer.result	2013-07-31 13:24:52 +0000
@@ -2117,4 +2117,25 @@ SELECT a.* FROM t1 a LEFT JOIN t1 b ON a
 WHERE a.modified > b.modified or b.modified IS NULL;
 id	modified
 DROP TABLE t1;
+#
+# MDEV-4817: Optimizer fails to optimize expression of the form 'FOO' IS NULL
+#
+create table t0 (a int not null);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+alter table t0 add person_id varchar(255) not null;
+create table t1 (pk int not null primary key);
+insert into t1 select A.a + 10*B.a from t0 A, t0 B;
+explain select * from t1 left join t0 on t0.a=t1.pk where t0.person_id='fooo' or 'xyz' IS NULL;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t0.a	1	Using index
+explain select * from t1 left join t0 on t0.a=t1.pk where t0.person_id='fooo';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t0.a	1	Using index
+explain select * from t1 left join t0 on t0.a=t1.pk where t0.person_id='fooo' or t0.person_id='bar';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t0.a	1	Using index
+drop table t0, t1;
 SET optimizer_switch=@save_optimizer_switch;

=== modified file 'mysql-test/r/join_outer_innodb.result'
--- a/mysql-test/r/join_outer_innodb.result	2013-05-03 21:08:20 +0000
+++ b/mysql-test/r/join_outer_innodb.result	2013-07-31 13:24:52 +0000
@@ -14,8 +14,8 @@ EXPLAIN
 SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id 
 WHERE t1.name LIKE 'A%' OR FALSE;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	index	NULL	fkey	5	NULL	5	Using index
-1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t2.fkey	1	Using where
+1	SIMPLE	t1	index	PRIMARY,name	name	23	NULL	3	Using where; Using index
+1	SIMPLE	t2	ref	fkey	fkey	5	test.t1.id	1	Using index
 DROP TABLE t1,t2;
 #
 # BUG#58456: Assertion 0 in QUICK_INDEX_MERGE_SELECT::need_sorted_output

=== modified file 'mysql-test/r/join_outer_jcl6.result'
--- a/mysql-test/r/join_outer_jcl6.result	2013-05-07 11:05:09 +0000
+++ b/mysql-test/r/join_outer_jcl6.result	2013-07-31 13:24:52 +0000
@@ -2128,6 +2128,27 @@ SELECT a.* FROM t1 a LEFT JOIN t1 b ON a
 WHERE a.modified > b.modified or b.modified IS NULL;
 id	modified
 DROP TABLE t1;
+#
+# MDEV-4817: Optimizer fails to optimize expression of the form 'FOO' IS NULL
+#
+create table t0 (a int not null);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+alter table t0 add person_id varchar(255) not null;
+create table t1 (pk int not null primary key);
+insert into t1 select A.a + 10*B.a from t0 A, t0 B;
+explain select * from t1 left join t0 on t0.a=t1.pk where t0.person_id='fooo' or 'xyz' IS NULL;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t0.a	1	Using index
+explain select * from t1 left join t0 on t0.a=t1.pk where t0.person_id='fooo';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t0.a	1	Using index
+explain select * from t1 left join t0 on t0.a=t1.pk where t0.person_id='fooo' or t0.person_id='bar';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t0.a	1	Using index
+drop table t0, t1;
 SET optimizer_switch=@save_optimizer_switch;
 set join_cache_level=default;
 show variables like 'join_cache_level';

=== modified file 'mysql-test/r/range.result'
--- a/mysql-test/r/range.result	2013-01-28 13:13:39 +0000
+++ b/mysql-test/r/range.result	2013-07-31 13:24:52 +0000
@@ -1590,6 +1590,8 @@ NULL
 Warnings:
 Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
 Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
+Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
+Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
 SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20';
 str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'
 1

=== modified file 'mysql-test/r/range_mrr_icp.result'
--- a/mysql-test/r/range_mrr_icp.result	2013-01-28 13:13:39 +0000
+++ b/mysql-test/r/range_mrr_icp.result	2013-07-31 13:24:52 +0000
@@ -1592,6 +1592,8 @@ NULL
 Warnings:
 Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
 Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
+Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
+Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
 SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20';
 str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'
 1

=== modified file 'mysql-test/r/subselect_cache.result'
--- a/mysql-test/r/subselect_cache.result	2012-05-17 10:46:05 +0000
+++ b/mysql-test/r/subselect_cache.result	2013-07-31 13:24:52 +0000
@@ -3129,6 +3129,7 @@ WHERE table1 .`col_varchar_key` )	field1
 1	NULL	f
 Warnings:
 Warning	1292	Truncated incorrect DOUBLE value: 'f'
+Warning	1292	Truncated incorrect DOUBLE value: 'f'
 SET @@optimizer_switch = 'subquery_cache=on';
 /* cache is on */ SELECT COUNT( DISTINCT table2 .`col_int_key` ) , (
 SELECT SUBQUERY2_t1 .`col_int_key`
@@ -3144,6 +3145,7 @@ WHERE table1 .`col_varchar_key` )	field1
 1	NULL	f
 Warnings:
 Warning	1292	Truncated incorrect DOUBLE value: 'f'
+Warning	1292	Truncated incorrect DOUBLE value: 'f'
 drop table t1,t2,t3,t4;
 set @@optimizer_switch= default;
 #launchpad BUG#611625

=== modified file 'mysql-test/t/join_outer.test'
--- a/mysql-test/t/join_outer.test	2013-05-07 11:05:09 +0000
+++ b/mysql-test/t/join_outer.test	2013-07-31 13:24:52 +0000
@@ -1670,4 +1670,21 @@ SELECT a.* FROM t1 a LEFT JOIN t1 b ON a
 
 DROP TABLE t1;
 
+--echo #
+--echo # MDEV-4817: Optimizer fails to optimize expression of the form 'FOO' IS NULL
+--echo #
+create table t0 (a int not null);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+alter table t0 add person_id varchar(255) not null;
+create table t1 (pk int not null primary key);
+insert into t1 select A.a + 10*B.a from t0 A, t0 B;
+
+explain select * from t1 left join t0 on t0.a=t1.pk where t0.person_id='fooo' or 'xyz' IS NULL;
+explain select * from t1 left join t0 on t0.a=t1.pk where t0.person_id='fooo';
+explain select * from t1 left join t0 on t0.a=t1.pk where t0.person_id='fooo' or t0.person_id='bar';
+
+drop table t0, t1;
+
+
 SET optimizer_switch=@save_optimizer_switch;

=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc	2013-07-17 19:24:29 +0000
+++ b/sql/item_cmpfunc.cc	2013-07-31 13:24:52 +0000
@@ -4341,12 +4341,40 @@ Item_cond::fix_fields(THD *thd, Item **r
       return TRUE; /* purecov: inspected */
     used_tables_cache|=     item->used_tables();
     if (item->const_item())
-      and_tables_cache= (table_map) 0;
+    {
+      if (!item->is_expensive() && item->val_int() == 0)
+      {
+        /* 
+          This is "... OR false_cond OR ..." 
+          In this case, false_cond has no effect on cond_or->not_null_tables()
+        */
+      }
+      else
+      {
+        /* 
+          This is  "... OR const_cond OR ..."
+          In this case, cond_or->not_null_tables()=0, because the condition
+          some_cond_or might be true regardless of what tables are 
+          NULL-complemented.
+        */
+        and_tables_cache= (table_map) 0;
+      }
+    }
     else
     {
-      table_map tmp_table_map= item->not_null_tables();
-      not_null_tables_cache|= tmp_table_map;
-      and_tables_cache&= tmp_table_map;
+      /*
+        If an item is a 
+         - constant
+         - inexpensive 
+         - its value is 0
+        then we don't need to account it in not_null_tables_cache
+      */
+      //if (!(item->const_item() && !item->is_expensive() ))
+      {
+        table_map tmp_table_map= item->not_null_tables();
+        not_null_tables_cache|= tmp_table_map;
+        and_tables_cache&= tmp_table_map;
+      }
       const_item_cache= FALSE;
     } 
   
@@ -4374,7 +4402,25 @@ Item_cond::eval_not_null_tables(uchar *o
   {
     table_map tmp_table_map;
     if (item->const_item())
-      and_tables_cache= (table_map) 0;
+    {
+      if (!item->is_expensive() && item->val_int() == 0)
+      {
+        /* 
+          This is "... OR false_cond OR ..." 
+          In this case, false_cond has no effect on cond_or->not_null_tables()
+        */
+      }
+      else
+      {
+        /* 
+          This is  "... OR const_cond OR ..."
+          In this case, cond_or->not_null_tables()=0, because the condition
+          some_cond_or might be true regardless of what tables are 
+          NULL-complemented.
+        */
+        and_tables_cache= (table_map) 0;
+      }
+    }
     else
     {
       tmp_table_map= item->not_null_tables();



More information about the commits mailing list