[Commits] Rev 4235: MDEV-6289 : Unexpected results when querying information_schema in file:///home/psergey/dev2/5.5/

Sergey Petrunya psergey at askmonty.org
Wed Jul 23 18:54:14 EEST 2014


At file:///home/psergey/dev2/5.5/

------------------------------------------------------------
revno: 4235
revision-id: psergey at askmonty.org-20140723155329-jnadou3d9hvg9viy
parent: bar at mariadb.org-20140723105923-ryhdp1i6hah1p1c9
committer: Sergey Petrunya <psergey at askmonty.org>
branch nick: 5.5
timestamp: Wed 2014-07-23 19:53:29 +0400
message:
  MDEV-6289 : Unexpected results when querying information_schema
  - When traversing JOIN_TABs with first_linear_tab/next_linear_tab(), don't forget
    to enter the semi-join nest when it is the first table in the join order.
    Failure to do so could cause e.g. I_S tables not to be filled.
=== modified file 'mysql-test/r/subselect_mat.result'
--- a/mysql-test/r/subselect_mat.result	2014-03-25 10:09:12 +0000
+++ b/mysql-test/r/subselect_mat.result	2014-07-23 15:53:29 +0000
@@ -2108,6 +2108,43 @@ EXECUTE stmt;
 a
 DROP TABLE t1, t2;
 DROP VIEW v2;
+#
+# MDEV-6289 : Unexpected results when querying information_schema
+#
+CREATE TABLE t1 (
+id int(11) unsigned NOT NULL AUTO_INCREMENT,
+db varchar(254) NOT NULL DEFAULT '',
+PRIMARY KEY (id),
+UNIQUE KEY db (db)
+) DEFAULT CHARSET=utf8;
+INSERT INTO t1 (db) VALUES ('mysqltest1'),('mysqltest2'),('mysqltest3'),('mysqltest4');
+drop database if exists mysqltest1;
+drop database if exists mysqltest2;
+drop database if exists mysqltest3;
+drop database if exists mysqltest4;
+create database mysqltest1;
+create database mysqltest2;
+create database mysqltest3;
+create database mysqltest4;
+SELECT db FROM t1 WHERE db IN (SELECT SCHEMA_NAME FROM information_schema.SCHEMATA) ORDER BY db DESC;
+db
+mysqltest4
+mysqltest3
+mysqltest2
+mysqltest1
+EXPLAIN EXTENDED
+SELECT db FROM t1 WHERE db IN (SELECT SCHEMA_NAME FROM information_schema.SCHEMATA) ORDER BY db DESC;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	<subquery2>	ALL	distinct_key	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+1	PRIMARY	t1	eq_ref	db	db	764	information_schema.SCHEMATA.SCHEMA_NAME	1	100.00	Using where; Using index
+2	MATERIALIZED	SCHEMATA	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+Warnings:
+Note	1003	select `test`.`t1`.`db` AS `db` from `test`.`t1` semi join (`information_schema`.`SCHEMATA`) where (`test`.`t1`.`db` = `information_schema`.`SCHEMATA`.`SCHEMA_NAME`) order by `test`.`t1`.`db` desc
+drop table t1;
+drop database mysqltest1;
+drop database mysqltest2;
+drop database mysqltest3;
+drop database mysqltest4;
 # End of 5.5 tests
 set @subselect_mat_test_optimizer_switch_value=null;
 set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';

=== modified file 'mysql-test/r/subselect_sj_mat.result'
--- a/mysql-test/r/subselect_sj_mat.result	2014-03-25 10:09:12 +0000
+++ b/mysql-test/r/subselect_sj_mat.result	2014-07-23 15:53:29 +0000
@@ -2148,4 +2148,41 @@ EXECUTE stmt;
 a
 DROP TABLE t1, t2;
 DROP VIEW v2;
+#
+# MDEV-6289 : Unexpected results when querying information_schema
+#
+CREATE TABLE t1 (
+id int(11) unsigned NOT NULL AUTO_INCREMENT,
+db varchar(254) NOT NULL DEFAULT '',
+PRIMARY KEY (id),
+UNIQUE KEY db (db)
+) DEFAULT CHARSET=utf8;
+INSERT INTO t1 (db) VALUES ('mysqltest1'),('mysqltest2'),('mysqltest3'),('mysqltest4');
+drop database if exists mysqltest1;
+drop database if exists mysqltest2;
+drop database if exists mysqltest3;
+drop database if exists mysqltest4;
+create database mysqltest1;
+create database mysqltest2;
+create database mysqltest3;
+create database mysqltest4;
+SELECT db FROM t1 WHERE db IN (SELECT SCHEMA_NAME FROM information_schema.SCHEMATA) ORDER BY db DESC;
+db
+mysqltest4
+mysqltest3
+mysqltest2
+mysqltest1
+EXPLAIN EXTENDED
+SELECT db FROM t1 WHERE db IN (SELECT SCHEMA_NAME FROM information_schema.SCHEMATA) ORDER BY db DESC;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PRIMARY	<subquery2>	ALL	distinct_key	NULL	NULL	NULL	2	100.00	Using temporary; Using filesort
+1	PRIMARY	t1	eq_ref	db	db	764	information_schema.SCHEMATA.SCHEMA_NAME	1	100.00	Using where; Using index
+2	MATERIALIZED	SCHEMATA	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
+Warnings:
+Note	1003	select `test`.`t1`.`db` AS `db` from `test`.`t1` semi join (`information_schema`.`SCHEMATA`) where (`test`.`t1`.`db` = `information_schema`.`SCHEMATA`.`SCHEMA_NAME`) order by `test`.`t1`.`db` desc
+drop table t1;
+drop database mysqltest1;
+drop database mysqltest2;
+drop database mysqltest3;
+drop database mysqltest4;
 # End of 5.5 tests

=== modified file 'mysql-test/t/subselect_sj_mat.test'
--- a/mysql-test/t/subselect_sj_mat.test	2014-03-25 10:09:12 +0000
+++ b/mysql-test/t/subselect_sj_mat.test	2014-07-23 15:53:29 +0000
@@ -1808,5 +1808,38 @@ EXECUTE stmt;
 DROP TABLE t1, t2;
 DROP VIEW v2;
 
+--echo #
+--echo # MDEV-6289 : Unexpected results when querying information_schema
+--echo #
+CREATE TABLE t1 (
+  id int(11) unsigned NOT NULL AUTO_INCREMENT,
+  db varchar(254) NOT NULL DEFAULT '',
+  PRIMARY KEY (id),
+  UNIQUE KEY db (db)
+) DEFAULT CHARSET=utf8;
+INSERT INTO t1 (db) VALUES ('mysqltest1'),('mysqltest2'),('mysqltest3'),('mysqltest4');
+
+--disable_warnings
+drop database if exists mysqltest1;
+drop database if exists mysqltest2;
+drop database if exists mysqltest3;
+drop database if exists mysqltest4;
+--enable_warnings
+create database mysqltest1;
+create database mysqltest2;
+create database mysqltest3;
+create database mysqltest4;
+
+SELECT db FROM t1 WHERE db IN (SELECT SCHEMA_NAME FROM information_schema.SCHEMATA) ORDER BY db DESC;
+
+EXPLAIN EXTENDED
+SELECT db FROM t1 WHERE db IN (SELECT SCHEMA_NAME FROM information_schema.SCHEMATA) ORDER BY db DESC;
+
+drop table t1;
+drop database mysqltest1;
+drop database mysqltest2;
+drop database mysqltest3;
+drop database mysqltest4;
+
 --echo # End of 5.5 tests
 

=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc	2014-03-17 12:04:28 +0000
+++ b/sql/item_subselect.cc	2014-07-23 15:53:29 +0000
@@ -3200,8 +3200,9 @@ int subselect_single_select_engine::exec
         pushed down into the subquery. Those optimizations are ref[_or_null]
         acceses. Change them to be full table scans.
       */
-      for (JOIN_TAB *tab= first_linear_tab(join, WITHOUT_CONST_TABLES); tab;
-           tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
+      JOIN_TAB *tab;
+      for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES);
+           tab; tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
       {
         if (tab && tab->keyuse)
         {

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2013-05-02 20:10:43 +0000
+++ b/sql/sql_delete.cc	2014-07-23 15:53:29 +0000
@@ -673,7 +673,8 @@ multi_delete::initialize_tables(JOIN *jo
 
   walk= delete_tables;
 
-  for (JOIN_TAB *tab= first_linear_tab(join, WITH_CONST_TABLES); 
+  for (JOIN_TAB *tab= first_linear_tab(join, WITHOUT_BUSH_ROOTS, 
+                                       WITH_CONST_TABLES); 
        tab; 
        tab= next_linear_tab(join, tab, WITHOUT_BUSH_ROOTS))
   {

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2014-06-03 07:55:08 +0000
+++ b/sql/sql_select.cc	2014-07-23 15:53:29 +0000
@@ -1332,7 +1332,8 @@ JOIN::optimize()
     Perform the optimization on fields evaluation mentioned above
     for all on expressions.
   */
-  for (JOIN_TAB *tab= first_linear_tab(this, WITHOUT_CONST_TABLES); tab;
+  JOIN_TAB *tab;
+  for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab;
        tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
   {
     if (*tab->on_expr_ref)
@@ -1355,7 +1356,7 @@ JOIN::optimize()
     Perform the optimization on fields evaliation mentioned above
     for all used ref items.
   */
-  for (JOIN_TAB *tab= first_linear_tab(this, WITHOUT_CONST_TABLES); tab;
+  for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab;
        tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
   {
     uint key_copy_index=0;
@@ -1980,7 +1981,8 @@ bool JOIN::setup_subquery_caches()
     if (conds)
       conds= conds->transform(&Item::expr_cache_insert_transformer,
                               (uchar*) thd);
-    for (JOIN_TAB *tab= first_linear_tab(this, WITHOUT_CONST_TABLES); 
+    JOIN_TAB *tab;
+    for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES);
          tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
     {
       if (tab->select_cond)
@@ -2143,7 +2145,8 @@ JOIN::reinit()
   /* need to reset ref access state (see join_read_key) */
   if (join_tab)
   {
-    for (JOIN_TAB *tab= first_linear_tab(this, WITH_CONST_TABLES); tab; 
+    JOIN_TAB *tab;
+    for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITH_CONST_TABLES); tab;
          tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
     {
       tab->ref.key_err= TRUE;
@@ -2907,8 +2910,9 @@ JOIN::destroy()
   {
     if (join_tab != tmp_join->join_tab)
     {
-      for (JOIN_TAB *tab= first_linear_tab(this, WITH_CONST_TABLES); tab; 
-           tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
+      JOIN_TAB *tab;
+      for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITH_CONST_TABLES);
+           tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
       {
 	tab->cleanup();
       }
@@ -7520,14 +7524,24 @@ JOIN_TAB *next_top_level_tab(JOIN *join,
 }
 
 
-JOIN_TAB *first_linear_tab(JOIN *join, enum enum_with_const_tables const_tbls)
+JOIN_TAB *first_linear_tab(JOIN *join,
+                           enum enum_with_bush_roots include_bush_roots,
+                           enum enum_with_const_tables const_tbls)
 {
   JOIN_TAB *first= join->join_tab;
   if (const_tbls == WITHOUT_CONST_TABLES)
     first+= join->const_tables;
-  if (first < join->join_tab + join->top_join_tab_count)
-    return first;
-  return NULL; /* All tables were const tables */
+
+  if (first >= join->join_tab + join->top_join_tab_count)
+    return NULL; /* All are const tables */
+
+  if (first->bush_children && include_bush_roots == WITHOUT_BUSH_ROOTS)
+  {
+    /* This JOIN_TAB is a SJM nest; Start from first table in nest */
+    return first->bush_children->start;
+  }
+
+  return first;
 }
 
 
@@ -8364,9 +8378,10 @@ inline void add_cond_and_fix(THD *thd, I
 
 static void add_not_null_conds(JOIN *join)
 {
+  JOIN_TAB *tab;
   DBUG_ENTER("add_not_null_conds");
   
-  for (JOIN_TAB *tab= first_linear_tab(join, WITHOUT_CONST_TABLES); 
+  for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES);
        tab; 
        tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
   {
@@ -8537,7 +8552,7 @@ make_outerjoin_info(JOIN *join)
     tab->table->pos_in_table_list being set.
   */
   JOIN_TAB *tab;
-  for (tab= first_linear_tab(join, WITHOUT_CONST_TABLES); 
+  for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES);
        tab; 
        tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
   {
@@ -8549,7 +8564,7 @@ make_outerjoin_info(JOIN *join)
     }
   }
 
-  for (JOIN_TAB *tab= first_linear_tab(join, WITHOUT_CONST_TABLES); tab; 
+  for (JOIN_TAB *tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); tab; 
        tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
   {
     TABLE *table= tab->table;
@@ -9309,7 +9324,7 @@ bool generate_derived_keys(DYNAMIC_ARRAY
 void JOIN::drop_unused_derived_keys()
 {
   JOIN_TAB *tab;
-  for (tab= first_linear_tab(this, WITHOUT_CONST_TABLES); 
+  for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); 
        tab; 
        tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
   {
@@ -9997,7 +10012,7 @@ void check_join_cache_usage_for_tables(J
   JOIN_TAB *tab;
   JOIN_TAB *prev_tab;
 
-  for (tab= first_linear_tab(join, WITHOUT_CONST_TABLES); 
+  for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); 
        tab; 
        tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
   {
@@ -10005,7 +10020,7 @@ void check_join_cache_usage_for_tables(J
   }
 
   uint idx= join->const_tables;
-  for (tab= first_linear_tab(join, WITHOUT_CONST_TABLES); 
+  for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); 
        tab; 
        tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
   {
@@ -10099,7 +10114,8 @@ make_join_readinfo(JOIN *join, ulonglong
     tab->partial_join_cardinality= 1; 
 
   JOIN_TAB *prev_tab= NULL;
-  for (tab= first_linear_tab(join, WITHOUT_CONST_TABLES), i= join->const_tables; 
+  i= join->const_tables;
+  for (tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES);
        tab; 
        prev_tab=tab, tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
   {
@@ -10124,7 +10140,7 @@ make_join_readinfo(JOIN *join, ulonglong
   check_join_cache_usage_for_tables(join, options, no_jbuf_after);
   
   JOIN_TAB *first_tab;
-  for (tab= first_tab= first_linear_tab(join, WITHOUT_CONST_TABLES); 
+  for (tab= first_tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES); 
        tab; 
        tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
   {
@@ -10800,7 +10816,8 @@ void JOIN::cleanup(bool full)
     }
     if (full)
     {
-      JOIN_TAB *sort_tab= first_linear_tab(this, WITHOUT_CONST_TABLES);
+      JOIN_TAB *sort_tab= first_linear_tab(this, WITH_BUSH_ROOTS, 
+                                           WITHOUT_CONST_TABLES);
       if (pre_sort_join_tab)
       {
         if (sort_tab && sort_tab->select == pre_sort_join_tab->select)
@@ -10847,7 +10864,7 @@ void JOIN::cleanup(bool full)
     }
     else
     {
-      for (tab= first_linear_tab(this, WITH_CONST_TABLES); tab;
+      for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITH_CONST_TABLES); tab;
            tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
       {
 	if (tab->table)
@@ -11009,7 +11026,9 @@ only_eq_ref_tables(JOIN *join,ORDER *ord
 
 static void update_depend_map(JOIN *join)
 {
-  for (JOIN_TAB *join_tab= first_linear_tab(join, WITH_CONST_TABLES); join_tab;
+  JOIN_TAB *join_tab;
+  for (join_tab= first_linear_tab(join, WITH_BUSH_ROOTS, WITH_CONST_TABLES); 
+       join_tab;
        join_tab= next_linear_tab(join, join_tab, WITH_BUSH_ROOTS))
   {
     TABLE_REF *ref= &join_tab->ref;

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2014-03-17 12:04:28 +0000
+++ b/sql/sql_select.h	2014-07-23 15:53:29 +0000
@@ -1458,7 +1458,9 @@ class JOIN :public Sql_alloc
 enum enum_with_bush_roots { WITH_BUSH_ROOTS, WITHOUT_BUSH_ROOTS};
 enum enum_with_const_tables { WITH_CONST_TABLES, WITHOUT_CONST_TABLES};
 
-JOIN_TAB *first_linear_tab(JOIN *join, enum enum_with_const_tables const_tbls);
+JOIN_TAB *first_linear_tab(JOIN *join, 
+                           enum enum_with_bush_roots include_bush_roots,
+                           enum enum_with_const_tables const_tbls);
 JOIN_TAB *next_linear_tab(JOIN* join, JOIN_TAB* tab, 
                           enum enum_with_bush_roots include_bush_roots);
 

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	2014-06-03 07:55:08 +0000
+++ b/sql/sql_show.cc	2014-07-23 15:53:29 +0000
@@ -7708,8 +7708,9 @@ bool get_schema_tables_result(JOIN *join
   Warnings_only_error_handler err_handler;
   thd->push_internal_handler(&err_handler);
   old_proc_info= thd_proc_info(thd, "Filling schema table");
-
-  for (JOIN_TAB *tab= first_linear_tab(join, WITH_CONST_TABLES); 
+  
+  JOIN_TAB *tab;
+  for (tab= first_linear_tab(join, WITHOUT_BUSH_ROOTS, WITH_CONST_TABLES);
        tab; 
        tab= next_linear_tab(join, tab, WITHOUT_BUSH_ROOTS))
   {



More information about the commits mailing list