MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:gluh Date:December 7 2006 3:25pm
Subject:bk commit into 5.0 tree (gluh:1.2326) BUG#24630
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of gluh. When gluh does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2006-12-07 19:25:21+04:00, gluh@stripped +6 -0
  Bug#24630 Subselect query crashes mysqld
  The crash happens because second filling of the same I_S table happens in
  case of subselect with order by. table->sort.io_cache previously allocated
  in create_sort_index() is deleted during second filling
  (function get_schema_tables_result). There are two places where
  I_S table can be filled: JOIN::exec and create_sort_index().
  To fix the bug we should check if the table was already filled
  in one of these places and skip processing of the table in second.

  mysql-test/r/information_schema.result@stripped, 2006-12-07 19:25:14+04:00, gluh@stripped +37 -0
    test case

  mysql-test/t/information_schema.test@stripped, 2006-12-07 19:25:15+04:00, gluh@stripped +23 -0
    test case

  sql/mysql_priv.h@stripped, 2006-12-07 19:25:15+04:00, gluh@stripped +1 -1
    added new parameter 'exec_level' to function get_schema_tables_result()

  sql/sql_select.cc@stripped, 2006-12-07 19:25:15+04:00, gluh@stripped +2 -2
    added new parameter 'exec_level' to function get_schema_tables_result()

  sql/sql_show.cc@stripped, 2006-12-07 19:25:15+04:00, gluh@stripped +21 -10
    added more accurate check for cases when we need to refresh I_S table

  sql/table.h@stripped, 2006-12-07 19:25:15+04:00, gluh@stripped +7 -1
    'is_schema_table_processed' field is changed to uint

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	gluh
# Host:	gluh.(none)
# Root:	/home/gluh/MySQL/Bugs/5.0.24630

--- 1.424/sql/mysql_priv.h	2006-12-07 19:25:38 +04:00
+++ 1.425/sql/mysql_priv.h	2006-12-07 19:25:38 +04:00
@@ -928,7 +928,7 @@ int fill_schema_user_privileges(THD *thd
 int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
 int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
 int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
-bool get_schema_tables_result(JOIN *join);
+bool get_schema_tables_result(JOIN *join, uint exec_level);
 #define is_schema_db(X) \
   !my_strcasecmp(system_charset_info, information_schema_name.str, (X))
 

--- 1.478/sql/sql_select.cc	2006-12-07 19:25:39 +04:00
+++ 1.479/sql/sql_select.cc	2006-12-07 19:25:39 +04:00
@@ -1472,7 +1472,7 @@ JOIN::exec()
 
   if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) &&
       !thd->lex->describe &&
-      get_schema_tables_result(curr_join))
+      get_schema_tables_result(curr_join, 2))
   {
     DBUG_VOID_RETURN;
   }
@@ -12278,7 +12278,7 @@ create_sort_index(THD *thd, JOIN *join, 
   /* Fill schema tables with data before filesort if it's necessary */
   if ((join->select_lex->options & OPTION_SCHEMA_TABLE) &&
       !thd->lex->describe &&
-      get_schema_tables_result(join))
+      get_schema_tables_result(join, 1))
     goto err;
 
   if (table->s->tmp_table)

--- 1.333/sql/sql_show.cc	2006-12-07 19:25:39 +04:00
+++ 1.334/sql/sql_show.cc	2006-12-07 19:25:39 +04:00
@@ -3939,13 +3939,15 @@ int make_schema_select(THD *thd, SELECT_
   SYNOPSIS
     get_schema_tables_result()
     join  join which use schema tables
-
+    exec_level I_S tables can be filled it two places:
+               1 - in function create_sort_index
+               2 - in JOIN::exec
   RETURN
     FALSE success
     TRUE  error
 */
 
-bool get_schema_tables_result(JOIN *join)
+bool get_schema_tables_result(JOIN *join, uint exec_level)
 {
   JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
   THD *thd= join->thd;
@@ -3965,14 +3967,23 @@ bool get_schema_tables_result(JOIN *join
       bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
                           lex->current_select->master_unit()->item);
       /*
-        The schema table is already processed and 
-        the statement is not a subselect.
-        So we don't need to handle this table again.
+        If schema table is already processed and 
+        the statement is not a subselect then 
+        we don't need to fill this table again.
+        If schema table is already processed and 
+        is_schema_table_processed != exec_level then
+        table is already processed and 
+        we should skip second data processing.
       */
-      if (table_list->is_schema_table_processed && !is_subselect)
+      if (table_list->is_schema_table_processed && 
+          (!is_subselect || table_list->is_schema_table_processed != exec_level))
         continue;
-
-      if (is_subselect) // is subselect
+      /*
+        if table is used in a subselect and 
+        table has been processed earlier with the same 'exec_level' value
+        then we should refresh the table.
+      */
+      if (table_list->is_schema_table_processed && is_subselect)
       {
         table_list->table->file->extra(HA_EXTRA_RESET_STATE);
         table_list->table->file->delete_all_rows();
@@ -3988,10 +3999,10 @@ bool get_schema_tables_result(JOIN *join
       {
         result= 1;
         join->error= 1;
-        table_list->is_schema_table_processed= TRUE;
+        table_list->is_schema_table_processed= exec_level;
         break;
       }
-      table_list->is_schema_table_processed= TRUE;
+      table_list->is_schema_table_processed= exec_level;
     }
   }
   thd->no_warnings_for_error= 0;

--- 1.135/sql/table.h	2006-12-07 19:25:39 +04:00
+++ 1.136/sql/table.h	2006-12-07 19:25:39 +04:00
@@ -530,7 +530,13 @@ typedef struct st_table_list
   st_select_lex_unit *derived;		/* SELECT_LEX_UNIT of derived table */
   ST_SCHEMA_TABLE *schema_table;        /* Information_schema table */
   st_select_lex	*schema_select_lex;
-  bool is_schema_table_processed;
+  /*
+    possible values:
+    0 - I_S table is not processed
+    1 - I_S table is processed in create_sort_order() function
+    2 - I_S table is processed in JOIN::exec
+  */
+  uint is_schema_table_processed;
   /*
     True when the view field translation table is used to convert
     schema table fields for backwards compatibility with SHOW command.

--- 1.116/mysql-test/r/information_schema.result	2006-12-07 19:25:39 +04:00
+++ 1.117/mysql-test/r/information_schema.result	2006-12-07 19:25:39 +04:00
@@ -1269,3 +1269,40 @@ id	select_type	table	type	possible_keys	
 1	PRIMARY	<derived2>	system	NULL	NULL	NULL	NULL	0	const row not found
 2	DERIVED	tables	ALL	NULL	NULL	NULL	NULL	2	
 drop view v1;
+select 1 as f1 from information_schema.tables  where "CHARACTER_SETS"=
+(select cast(table_name as char)  from information_schema.tables
+order by table_name limit 1) limit 1;
+f1
+1
+select t.table_name, group_concat(t.table_schema, '.', t.table_name),
+count(*) as num1
+from information_schema.tables t
+inner join information_schema.columns c1
+on t.table_schema = c1.table_schema AND t.table_name = c1.table_name
+where t.table_schema = 'information_schema' and
+c1.ordinal_position =
+(select isnull(c2.column_type) -
+isnull(group_concat(c2.table_schema, '.', c2.table_name)) +
+count(*) as num
+from information_schema.columns c2 where
+c2.table_schema='information_schema' and
+(c2.column_type = 'varchar(7)' or c2.column_type = 'varchar(20)')
+group by c2.column_type order by num limit 1)
+group by t.table_name order by num1, t.table_name;
+table_name	group_concat(t.table_schema, '.', t.table_name)	num1
+CHARACTER_SETS	information_schema.CHARACTER_SETS	1
+COLLATIONS	information_schema.COLLATIONS	1
+COLLATION_CHARACTER_SET_APPLICABILITY	information_schema.COLLATION_CHARACTER_SET_APPLICABILITY	1
+COLUMNS	information_schema.COLUMNS	1
+COLUMN_PRIVILEGES	information_schema.COLUMN_PRIVILEGES	1
+KEY_COLUMN_USAGE	information_schema.KEY_COLUMN_USAGE	1
+ROUTINES	information_schema.ROUTINES	1
+SCHEMATA	information_schema.SCHEMATA	1
+SCHEMA_PRIVILEGES	information_schema.SCHEMA_PRIVILEGES	1
+STATISTICS	information_schema.STATISTICS	1
+TABLES	information_schema.TABLES	1
+TABLE_CONSTRAINTS	information_schema.TABLE_CONSTRAINTS	1
+TABLE_PRIVILEGES	information_schema.TABLE_PRIVILEGES	1
+TRIGGERS	information_schema.TRIGGERS	1
+USER_PRIVILEGES	information_schema.USER_PRIVILEGES	1
+VIEWS	information_schema.VIEWS	1

--- 1.87/mysql-test/t/information_schema.test	2006-12-07 19:25:39 +04:00
+++ 1.88/mysql-test/t/information_schema.test	2006-12-07 19:25:39 +04:00
@@ -987,4 +987,27 @@ explain select * from v1;
 explain select * from (select table_name from information_schema.tables) as a;
 drop view v1;
 
+#
+# Bug#24630  Subselect query crashes mysqld
+#
+select 1 as f1 from information_schema.tables  where "CHARACTER_SETS"=
+(select cast(table_name as char)  from information_schema.tables
+ order by table_name limit 1) limit 1;
+
+select t.table_name, group_concat(t.table_schema, '.', t.table_name),
+       count(*) as num1
+from information_schema.tables t
+inner join information_schema.columns c1
+on t.table_schema = c1.table_schema AND t.table_name = c1.table_name
+where t.table_schema = 'information_schema' and
+        c1.ordinal_position =
+        (select isnull(c2.column_type) -
+         isnull(group_concat(c2.table_schema, '.', c2.table_name)) +
+         count(*) as num
+         from information_schema.columns c2 where
+         c2.table_schema='information_schema' and
+         (c2.column_type = 'varchar(7)' or c2.column_type = 'varchar(20)')
+          group by c2.column_type order by num limit 1)
+group by t.table_name order by num1, t.table_name;
+
 # End of 5.0 tests.
Thread
bk commit into 5.0 tree (gluh:1.2326) BUG#24630gluh7 Dec