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#34921 | mhansson | 29 Apr |