List:Commits« Previous MessageNext Message »
From:mhansson Date:April 29 2008 4:08pm
Subject:bk commit into 5.1 tree (mhansson:1.2569) BUG#34921
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of mhansson.  When mhansson 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, 2008-04-29 18:07:26+02:00, mhansson@riffraff.(none) +3 -0
  Bug#34921: comparisons with Information schema tables don't 
  honor collation
  
  The bug introduced by WL 3732 is that the file system's
  open function is used as an index when searching for tables
  with a given table name and database name. The problem is
  that we support a diversity of file systems treating e.g.
  letter case differently. In general the file system cannot
  be trusted to implement the correct collation.
  Fixed by using the search key to prune database names from
  the result set before scanning the databases, as opposed to
  opening files by name.

  mysql-test/r/information_schema.result@stripped, 2008-04-29 18:07:23+02:00, mhansson@riffraff.(none) +92 -0
    Bug#34921: Test result

  mysql-test/t/information_schema.test@stripped, 2008-04-29 18:07:24+02:00, mhansson@riffraff.(none) +67 -0
    Bug#34921: Test case

  sql/sql_show.cc@stripped, 2008-04-29 18:07:24+02:00, mhansson@riffraff.(none) +56 -54
    Bug#34921: The fix. Most notably we do not use the lookup
    values to open files, and we use wild_case_compare
    instead of wild_compare. The former respects collation.

diff -Nrup a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
--- a/mysql-test/r/information_schema.result	2008-03-27 12:54:42 +01:00
+++ b/mysql-test/r/information_schema.result	2008-04-29 18:07:23 +02:00
@@ -1646,4 +1646,96 @@ drop table t1;
 drop function f1;
 select * from information_schema.tables where 1=sleep(100000);
 select * from information_schema.columns where 1=sleep(100000);
+CREATE TABLE t1( a INT );
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE TABLE mysqltest1.t1( a INT );
+USE information_schema;
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'mysqltest1';
+table_name
+t1
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'MySQLTest1';
+table_name
+t1
+EXPLAIN
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'mysqltest1';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	columns	ALL	NULL	TABLE_SCHEMA	NULL	NULL	NULL	Using where; Open_frm_only; Scanned 1 database
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'test'
+AND   table_name = 't1';
+table_name
+t1
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'test'
+AND   table_name = 'T1';
+table_name
+t1
+CREATE FUNCTION test.f1() RETURNS CHAR(2) RETURN 't1';
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'test'
+AND   table_name = test.f1();
+table_name
+t1
+CREATE FUNCTION test.f2() RETURNS CHAR(2) RETURN 'T1';
+SELECT table_name
+FROM columns
+WHERE table_schema = 'test'
+AND   table_name = test.f2();
+table_name
+t1
+SHOW TABLES FROM information_schema LIKE 'T%';
+Tables_in_information_schema (T%)
+TABLES
+TABLE_CONSTRAINTS
+TABLE_PRIVILEGES
+TRIGGERS
+SHOW TABLES FROM information_schema LIKE 't%';
+Tables_in_information_schema (t%)
+TABLES
+TABLE_CONSTRAINTS
+TABLE_PRIVILEGES
+TRIGGERS
+USE test;
+SHOW TABLES FROM mysql;
+Tables_in_mysql
+columns_priv
+db
+event
+func
+general_log
+help_category
+help_keyword
+help_relation
+help_topic
+host
+ndb_binlog_index
+plugin
+proc
+procs_priv
+servers
+slow_log
+tables_priv
+time_zone
+time_zone_leap_second
+time_zone_name
+time_zone_transition
+time_zone_transition_type
+user
+DROP TABLE t1;
+DROP DATABASE mysqltest1;
+SHOW TABLES FROM mysqltest1;
+ERROR 42000: Unknown database 'mysqltest1'
+DROP DATABASE mysqltest2;
+DROP FUNCTION f1;
+DROP FUNCTION f2;
 End of 5.1 tests.
diff -Nrup a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
--- a/mysql-test/t/information_schema.test	2008-03-27 12:54:42 +01:00
+++ b/mysql-test/t/information_schema.test	2008-04-29 18:07:24 +02:00
@@ -1338,4 +1338,71 @@ where state='User sleep' and
 info='select * from information_schema.columns where 1=sleep(100000)';
 --source include/wait_condition.inc
 
+#
+# Bug#25630: INFORMATION_SCHEMA collation wrong for filesystems with case 
+# sensitive filenames
+#
+CREATE TABLE t1( a INT );
+
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+
+CREATE TABLE mysqltest1.t1( a INT );
+
+USE information_schema;
+
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'mysqltest1';
+
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'MySQLTest1';
+
+EXPLAIN
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'mysqltest1';
+
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'test'
+AND   table_name = 't1';
+
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'test'
+AND   table_name = 'T1';
+
+CREATE FUNCTION test.f1() RETURNS CHAR(2) RETURN 't1';
+
+SELECT table_name
+FROM  columns
+WHERE table_schema = 'test'
+AND   table_name = test.f1();
+
+CREATE FUNCTION test.f2() RETURNS CHAR(2) RETURN 'T1';
+
+SELECT table_name
+FROM columns
+WHERE table_schema = 'test'
+AND   table_name = test.f2();
+
+SHOW TABLES FROM information_schema LIKE 'T%';
+SHOW TABLES FROM information_schema LIKE 't%';
+
+USE test;
+
+SHOW TABLES FROM mysql;
+
+DROP TABLE t1;
+
+DROP DATABASE mysqltest1;
+--error ER_BAD_DB_ERROR
+SHOW TABLES FROM mysqltest1;
+DROP DATABASE mysqltest2;
+
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+
 --echo End of 5.1 tests.
diff -Nrup a/sql/sql_show.cc b/sql/sql_show.cc
--- a/sql/sql_show.cc	2008-03-28 11:03:04 +01:00
+++ b/sql/sql_show.cc	2008-04-29 18:07:24 +02:00
@@ -524,16 +524,8 @@ find_files(THD *thd, List<LEX_STRING> *f
         continue;
       *ext=0;
       file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
-      if (wild)
-      {
-	if (lower_case_table_names)
-	{
-	  if (wild_case_compare(files_charset_info, uname, wild))
-	    continue;
-	}
-	else if (wild_compare(uname, wild, 0))
-	  continue;
-      }
+      if (wild && wild_case_compare(files_charset_info, uname, wild))
+          continue;
     }
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
     /* Don't show tables where we don't have any privileges */
@@ -2563,6 +2555,41 @@ enum enum_schema_tables get_schema_table
 }
 
 
+/**
+   @brief Filter a list of strings, add the filter itself if nothing matches.
+
+   @details This function will remove all strings from the list that are not
+   equal to the filter under the collation inside @c ci. The list will later
+   be used for opening the files, raising an error if the file is not found.
+   Hence we have to add the lookup key to this list if it is not present,
+   otherwise the error won't be raised.
+
+   @param files  The list of strings to be searched.
+   @param filter The filter string which all strings must equal.
+   @param ci     The CHARSET_INFO whose collation we will use for equality 
+                 testing.
+   @return       - 0 ok.
+                 - 1 fatal error.
+ */
+int adjust_files_list(List<LEX_STRING> *files, LEX_STRING *filter, 
+                      CHARSET_INFO *ci)
+{
+  List_iterator<LEX_STRING> li(*files);
+  bool found= FALSE;
+  while (LEX_STRING *file= li++)
+    if (ci->coll->strnncoll(ci, 
+                            (const uchar*)file->str,   file->length, 
+                            (const uchar*)filter->str, filter->length, FALSE))
+      li.remove();
+    else
+      found= TRUE;
+  if (!found)
+    if (files->push_back(filter))
+      return 1;
+  return 0;
+}
+
+
 /*
   Create db names list. Information schema name always is first in list
 
@@ -2623,22 +2650,27 @@ int make_db_list(THD *thd, List<LEX_STRI
       *with_i_schema= 1;
       if (files->push_back(i_s_name_copy))
         return 1;
-      return 0;
     }
-    if (files->push_back(&lookup_field_vals->db_value))
-      return 1;
-    return 0;
   }
-
+  else
+  {
   /*
     Create list of existing databases. It is used in case
     of select from information schema table
   */
-  if (files->push_back(i_s_name_copy))
-    return 1;
-  *with_i_schema= 1;
-  return (find_files(thd, files, NullS,
-                     mysql_data_home, NullS, 1) != FIND_FILES_OK);
+    if (files->push_back(i_s_name_copy))
+      return 1;
+    *with_i_schema= 1;
+  }
+  find_files_result res=
+    find_files(thd, files, NullS, mysql_data_home, NullS, 1);
+  if (res != FIND_FILES_OK)
+    return res;
+
+  if (lookup_field_vals->db_value.str)
+    return adjust_files_list(files, &lookup_field_vals->db_value, 
+                             system_charset_info);
+  return res;
 }
 
 
@@ -2696,14 +2728,9 @@ int schema_tables_add(THD *thd, List<LEX
       continue;
     if (wild)
     {
-      if (lower_case_table_names)
-      {
-        if (wild_case_compare(files_charset_info,
-                              tmp_schema_table->table_name,
-                              wild))
-          continue;
-      }
-      else if (wild_compare(tmp_schema_table->table_name, wild, 0))
+      if (wild_case_compare(files_charset_info,
+                            tmp_schema_table->table_name,
+                            wild))
         continue;
     }
     if ((file_name= 
@@ -2731,7 +2758,7 @@ int schema_tables_add(THD *thd, List<LEX
                   database
 
   @param[in]      thd                   thread handler
-  @param[in]      table_names           List of table names in database
+  @param[out]     table_names           List of table names in database
   @param[in]      lex                   pointer to LEX struct
   @param[in]      lookup_field_vals     pointer to LOOKUP_FIELD_VALUE struct
   @param[in]      with_i_schema         TRUE means that we add I_S tables to list
@@ -2750,31 +2777,6 @@ make_table_name_list(THD *thd, List<LEX_
 {
   char path[FN_REFLEN];
   build_table_filename(path, sizeof(path), db_name->str, "", "", 0);
-  if (!lookup_field_vals->wild_table_value &&
-      lookup_field_vals->table_value.str)
-  {
-    if (with_i_schema)
-    {
-      if (find_schema_table(thd, lookup_field_vals->table_value.str))
-      {
-        if (table_names->push_back(&lookup_field_vals->table_value))
-          return 1;
-      }
-    }
-    else
-    {    
-      if (table_names->push_back(&lookup_field_vals->table_value))
-        return 1;
-      /*
-        Check that table is relevant in current transaction.
-        (used for ndb engine, see ndbcluster_find_files(), ha_ndbcluster.cc)
-      */
-      VOID(ha_find_files(thd, db_name->str, path,
-                         lookup_field_vals->table_value.str, 0,
-                         table_names));
-    }
-    return 0;
-  }
 
   /*
     This call will add all matching the wildcards (if specified) IS tables
Thread
bk commit into 5.1 tree (mhansson:1.2569) BUG#34921mhansson29 Apr