List:Commits« Previous MessageNext Message »
From:gluh Date:February 12 2007 12:06pm
Subject:bk commit into 5.0 tree (gluh:1.2412) 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, 2007-02-12 16:06:14+04:00, gluh@stripped +7 -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, 2007-02-12 16:06:12+04:00, gluh@stripped +37 -0
    test case

  mysql-test/t/information_schema.test@stripped, 2007-02-12 16:06:12+04:00, gluh@stripped +24 -0
    test case

  sql/mysql_priv.h@stripped, 2007-02-12 16:06:12+04:00, gluh@stripped +2 -1
    added new parameter 'executed_place' to function get_schema_tables_result()

  sql/sql_select.cc@stripped, 2007-02-12 16:06:12+04:00, gluh@stripped +2 -2
    added new parameter 'executed_place' to function get_schema_tables_result()

  sql/sql_show.cc@stripped, 2007-02-12 16:06:12+04:00, gluh@stripped +20 -8
    added more accurate check for cases when we need to refresh I_S table

  sql/table.cc@stripped, 2007-02-12 16:06:12+04:00, gluh@stripped +1 -1
    added more accurate check for cases when we need to refresh I_S table

  sql/table.h@stripped, 2007-02-12 16:06:12+04:00, gluh@stripped +7 -1
    added more accurate check for cases when we need to refresh I_S table

# 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:	eagle.(none)
# Root:	/home/gluh/MySQL/Merge/5.0-opt

--- 1.433/sql/mysql_priv.h	2007-02-07 01:45:00 +04:00
+++ 1.434/sql/mysql_priv.h	2007-02-12 16:06:12 +04:00
@@ -932,7 +932,8 @@ 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,
+                              enum enum_schema_table_state executed_place);
 #define is_schema_db(X) \
   !my_strcasecmp(system_charset_info, information_schema_name.str, (X))
 

--- 1.488/sql/sql_select.cc	2007-02-01 12:50:33 +04:00
+++ 1.489/sql/sql_select.cc	2007-02-12 16:06:12 +04:00
@@ -1505,7 +1505,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, PROCESSED_BY_JOIN_EXEC))
   {
     DBUG_VOID_RETURN;
   }
@@ -12372,7 +12372,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, PROCESSED_BY_CREATE_SORT_INDEX))
     goto err;
 
   if (table->s->tmp_table)

--- 1.338/sql/sql_show.cc	2007-02-01 19:12:44 +04:00
+++ 1.339/sql/sql_show.cc	2007-02-12 16:06:12 +04:00
@@ -3938,13 +3938,15 @@ int make_schema_select(THD *thd, SELECT_
   SYNOPSIS
     get_schema_tables_result()
     join  join which use schema tables
+    executed_place place where I_S table processed
 
   RETURN
     FALSE success
     TRUE  error
 */
 
-bool get_schema_tables_result(JOIN *join)
+bool get_schema_tables_result(JOIN *join,
+                              enum enum_schema_table_state executed_place)
 {
   JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
   THD *thd= join->thd;
@@ -3964,14 +3966,24 @@ 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
+        schema_table_state != executed_place then
+        table is already processed and
+        we should skip second data processing.
       */
-      if (table_list->is_schema_table_processed && !is_subselect)
+      if (table_list->schema_table_state &&
+          (!is_subselect || table_list->schema_table_state != executed_place))
         continue;
 
-      if (is_subselect) // is subselect
+      /*
+        if table is used in a subselect and
+        table has been processed earlier with the same
+        'executed_place' value then we should refresh the table.
+      */
+      if (table_list->schema_table_state && is_subselect)
       {
         table_list->table->file->extra(HA_EXTRA_NO_CACHE);
         table_list->table->file->extra(HA_EXTRA_RESET_STATE);
@@ -3988,10 +4000,10 @@ bool get_schema_tables_result(JOIN *join
       {
         result= 1;
         join->error= 1;
-        table_list->is_schema_table_processed= TRUE;
+        table_list->schema_table_state= executed_place;
         break;
       }
-      table_list->is_schema_table_processed= TRUE;
+      table_list->schema_table_state= executed_place;
     }
   }
   thd->no_warnings_for_error= 0;

--- 1.242/sql/table.cc	2007-01-31 18:12:42 +04:00
+++ 1.243/sql/table.cc	2007-02-12 16:06:12 +04:00
@@ -3031,7 +3031,7 @@ void st_table_list::reinit_before_use(TH
   */
   table= 0;
   /* Reset is_schema_table_processed value(needed for I_S tables */
-  is_schema_table_processed= FALSE;
+  schema_table_state= NOT_PROCESSED;
 
   TABLE_LIST *embedded; /* The table at the current level of nesting. */
   TABLE_LIST *embedding= this; /* The parent nested table reference. */

--- 1.137/sql/table.h	2006-12-31 00:02:07 +04:00
+++ 1.138/sql/table.h	2007-02-12 16:06:12 +04:00
@@ -287,6 +287,12 @@ struct st_table {
   void reset_item_list(List<Item> *item_list) const;
 };
 
+enum enum_schema_table_state
+{ 
+  NOT_PROCESSED= 0,
+  PROCESSED_BY_CREATE_SORT_INDEX,
+  PROCESSED_BY_JOIN_EXEC
+};
 
 typedef struct st_foreign_key_info
 {
@@ -529,7 +535,6 @@ 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;
   /*
     True when the view field translation table is used to convert
     schema table fields for backwards compatibility with SHOW command.
@@ -638,6 +643,7 @@ typedef struct st_table_list
   */
   bool          prelocking_placeholder;
 
+  enum enum_schema_table_state schema_table_state;
   void calc_md5(char *buffer);
   void set_underlying_merge();
   int view_check_option(THD *thd, bool ignore_failure);

--- 1.119/mysql-test/r/information_schema.result	2007-02-11 23:50:42 +04:00
+++ 1.120/mysql-test/r/information_schema.result	2007-02-12 16:06:12 +04:00
@@ -1278,3 +1278,40 @@ table_name
 t1
 t2
 drop table t1,t2;
+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.89/mysql-test/t/information_schema.test	2007-02-01 19:12:44 +04:00
+++ 1.90/mysql-test/t/information_schema.test	2007-02-12 16:06:12 +04:00
@@ -999,4 +999,28 @@ where table_schema = 'test' and table_na
  where table_schema = 'test' and column_name = 'f3');
 drop table t1,t2;
 
+
+#
+# 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.2412) BUG#24630gluh12 Feb