List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:November 22 2008 2:28pm
Subject:bzr commit into mysql-5.0-bugteam branch (kgeorge:2714) Bug#37339
View as plain text  
#At file:///home/kgeorge/mysql/work/B37339-5.0-bugteam/

 2714 Georgi Kodinov	2008-11-22
      Bug #37339: SHOW VARIABLES not working properly with multi-byte datadir
      
      The SHOW VARIABLES LIKE .../SELECT @@/SELECT ... FROM INFORMATION_SCHEMA.VARIABLES
      were assuming that all the system variables are in system charset (UTF-8).
      However the variables that are settable through command line will have a different
      character set (character_set_filesystem).
      Fixed the server to remember the correct character set of basedir, datadir, tmpdir,
      ssl, plugin_dir, slave_load_tmpdir, innodb variables; init_connect and init_slave 
      variables and use it when processing data.
modified:
  sql/mysqld.cc
  sql/set_var.cc
  sql/set_var.h
  sql/sql_show.cc

per-file messages:
  sql/mysqld.cc
    Bug #37339: remember the correct character set for init_slave and init_connect
  sql/set_var.cc
    Bug #37339: 
      - remember the character set of the relevant variables
      - implement storing and using the correct 
        character set
  sql/set_var.h
    Bug #37339: implement storing and using the correct 
    character set
  sql/sql_show.cc
    Bug #37339: implement storing and using the correct 
    character set
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2008-10-09 07:26:19 +0000
+++ b/sql/mysqld.cc	2008-11-22 14:27:59 +0000
@@ -3035,12 +3035,14 @@ static int init_common_variables(const c
     sys_init_connect.value_length= strlen(opt_init_connect);
   else
     sys_init_connect.value=my_strdup("",MYF(0));
+  sys_init_connect.is_os_charset= TRUE;
 
   sys_init_slave.value_length= 0;
   if ((sys_init_slave.value= opt_init_slave))
     sys_init_slave.value_length= strlen(opt_init_slave);
   else
     sys_init_slave.value=my_strdup("",MYF(0));
+  sys_init_slave.is_os_charset= TRUE;
 
   if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
     return 1;

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2008-08-25 12:11:36 +0000
+++ b/sql/set_var.cc	2008-11-22 14:27:59 +0000
@@ -138,7 +138,7 @@ sys_var_thd_ulong	sys_auto_increment_off
 sys_var_bool_ptr	sys_automatic_sp_privileges("automatic_sp_privileges",
 					      &sp_automatic_privileges);
 
-sys_var_const_str       sys_basedir("basedir", mysql_home);
+sys_var_const_os_str    sys_basedir("basedir", mysql_home);
 sys_var_long_ptr	sys_binlog_cache_size("binlog_cache_size",
 					      &binlog_cache_size);
 sys_var_thd_ulong	sys_bulk_insert_buff_size("bulk_insert_buffer_size",
@@ -151,6 +151,8 @@ sys_var_character_set_client  sys_charac
 sys_var_character_set_connection  sys_character_set_connection("character_set_connection");
 sys_var_character_set_results sys_character_set_results("character_set_results");
 sys_var_character_set_filesystem  sys_character_set_filesystem("character_set_filesystem");
+sys_var_const_os_str    sys_character_sets_dir("character_sets_dir", 
+                                               mysql_charsets_dir);
 sys_var_thd_ulong	sys_completion_type("completion_type",
 					 &SV::completion_type,
 					 check_completion_type,
@@ -162,7 +164,7 @@ sys_var_long_ptr	sys_concurrent_insert("
                                               &myisam_concurrent_insert);
 sys_var_long_ptr	sys_connect_timeout("connect_timeout",
 					    &connect_timeout);
-sys_var_const_str       sys_datadir("datadir", mysql_real_data_home);
+sys_var_const_os_str    sys_datadir("datadir", mysql_real_data_home);
 sys_var_enum		sys_delay_key_write("delay_key_write",
 					    &delay_key_write_options,
 					    &delay_key_write_typelib,
@@ -311,6 +313,7 @@ sys_var_thd_ulong       sys_optimizer_pr
                                                   &SV::optimizer_prune_level);
 sys_var_thd_ulong       sys_optimizer_search_depth("optimizer_search_depth",
                                                    &SV::optimizer_search_depth);
+sys_var_const_os_str    sys_plugin_dir("plugin_dir", opt_plugin_dir);
 sys_var_thd_ulong       sys_preload_buff_size("preload_buffer_size",
                                               &SV::preload_buff_size);
 sys_var_thd_ulong	sys_read_buff_size("read_buffer_size",
@@ -338,7 +341,7 @@ sys_var_thd_ulong	sys_query_alloc_block_
 sys_var_thd_ulong	sys_query_prealloc_size("query_prealloc_size",
 						&SV::query_prealloc_size,
 						0, fix_thd_mem_root);
-sys_var_readonly        sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir);
+sys_var_readonly_os     sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir);
 sys_var_thd_ulong	sys_trans_alloc_block_size("transaction_alloc_block_size",
 						   &SV::trans_alloc_block_size,
 						   0, fix_trans_mem_root);
@@ -363,9 +366,11 @@ sys_var_bool_ptr	sys_secure_auth("secure
 sys_var_const_str_ptr   sys_secure_file_priv("secure_file_priv",
                                              &opt_secure_file_priv);
 sys_var_long_ptr	sys_server_id("server_id", &server_id, fix_server_id);
+#ifdef HAVE_REPLICATION
 sys_var_bool_ptr	sys_slave_compressed_protocol("slave_compressed_protocol",
 						      &opt_slave_compressed_protocol);
-#ifdef HAVE_REPLICATION
+sys_var_const_os_str_ptr sys_slave_load_tmpdir("slave_load_tmpdir", 
+                                               &slave_load_tmpdir);
 sys_var_long_ptr	sys_slave_net_timeout("slave_net_timeout",
 					      &slave_net_timeout);
 sys_var_long_ptr	sys_slave_trans_retries("slave_transaction_retries",
@@ -380,17 +385,17 @@ sys_var_thd_sql_mode    sys_sql_mode("sq
 #ifdef HAVE_OPENSSL
 extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher,
             *opt_ssl_key;
-sys_var_const_str_ptr	sys_ssl_ca("ssl_ca", &opt_ssl_ca);
-sys_var_const_str_ptr	sys_ssl_capath("ssl_capath", &opt_ssl_capath);
-sys_var_const_str_ptr	sys_ssl_cert("ssl_cert", &opt_ssl_cert);
-sys_var_const_str_ptr	sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher);
-sys_var_const_str_ptr	sys_ssl_key("ssl_key", &opt_ssl_key);
+sys_var_const_os_str_ptr  sys_ssl_ca("ssl_ca", &opt_ssl_ca);
+sys_var_const_os_str_ptr  sys_ssl_capath("ssl_capath", &opt_ssl_capath);
+sys_var_const_os_str_ptr  sys_ssl_cert("ssl_cert", &opt_ssl_cert);
+sys_var_const_os_str_ptr  sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher);
+sys_var_const_os_str_ptr  sys_ssl_key("ssl_key", &opt_ssl_key);
 #else
-sys_var_const_str	sys_ssl_ca("ssl_ca", NULL);
-sys_var_const_str	sys_ssl_capath("ssl_capath", NULL);
-sys_var_const_str	sys_ssl_cert("ssl_cert", NULL);
-sys_var_const_str	sys_ssl_cipher("ssl_cipher", NULL);
-sys_var_const_str	sys_ssl_key("ssl_key", NULL);
+sys_var_const_os_str	  sys_ssl_ca("ssl_ca", NULL);
+sys_var_const_os_str	  sys_ssl_capath("ssl_capath", NULL);
+sys_var_const_os_str	  sys_ssl_cert("ssl_cert", NULL);
+sys_var_const_os_str	  sys_ssl_cipher("ssl_cipher", NULL);
+sys_var_const_os_str	  sys_ssl_key("ssl_key", NULL);
 #endif
 sys_var_thd_enum
 sys_updatable_views_with_limit("updatable_views_with_limit",
@@ -460,6 +465,14 @@ sys_var_long_ptr  sys_innodb_commit_conc
 sys_var_long_ptr  sys_innodb_flush_log_at_trx_commit(
                                         "innodb_flush_log_at_trx_commit",
                                         &srv_flush_log_at_trx_commit);
+sys_var_const_os_str_ptr sys_innodb_data_file_path("innodb_data_file_path", 
+                                               &innobase_data_file_path);
+sys_var_const_os_str_ptr sys_innodb_data_home_dir("innodb_data_home_dir", 
+                                               &innobase_data_home_dir);
+sys_var_const_os_str_ptr sys_innodb_log_arch_dir("innodb_log_arch_dir", 
+                                               &innobase_log_arch_dir);
+sys_var_const_os_str_ptr sys_innodb_log_group_home_dir("innodb_log_group_home_dir", 
+                                                       &innobase_log_group_home_dir);
 #endif
 
 /* Condition pushdown to storage engine */
@@ -844,7 +857,7 @@ struct show_var_st init_vars[]= {
   {sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS},
   {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS},
   {sys_charset_system.name,   (char*) &sys_charset_system,          SHOW_SYS},
-  {"character_sets_dir",      mysql_charsets_dir,                   SHOW_CHAR},
+  {sys_character_sets_dir.name, (char *) &sys_character_sets_dir,   SHOW_SYS},
   {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS},
   {sys_collation_database.name,(char*) &sys_collation_database,     SHOW_SYS},
   {sys_collation_server.name,(char*) &sys_collation_server,         SHOW_SYS},
@@ -905,8 +918,8 @@ struct show_var_st init_vars[]= {
   {"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL},
   {sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS},
   {sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS},
-  {"innodb_data_file_path", (char*) &innobase_data_file_path,	    SHOW_CHAR_PTR},
-  {"innodb_data_home_dir",  (char*) &innobase_data_home_dir,	    SHOW_CHAR_PTR},
+  {sys_innodb_data_file_path.name, (char*) &sys_innodb_data_file_path, SHOW_SYS},
+  {sys_innodb_data_home_dir.name, (char*) &sys_innodb_data_home_dir, SHOW_SYS},
   {"innodb_adaptive_hash_index", (char*) &innobase_adaptive_hash_index, SHOW_MY_BOOL},
   {"innodb_doublewrite", (char*) &innobase_use_doublewrite, SHOW_MY_BOOL},
   {sys_innodb_fast_shutdown.name,(char*) &sys_innodb_fast_shutdown, SHOW_SYS},
@@ -917,12 +930,12 @@ struct show_var_st init_vars[]= {
   {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG },
   {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG },
   {"innodb_locks_unsafe_for_binlog", (char*) &innobase_locks_unsafe_for_binlog, SHOW_MY_BOOL},
-  {"innodb_log_arch_dir",   (char*) &innobase_log_arch_dir, 	    SHOW_CHAR_PTR},
+  {sys_innodb_log_arch_dir.name, (char*) &sys_innodb_log_arch_dir,  SHOW_SYS},
   {"innodb_log_archive",    (char*) &innobase_log_archive, 	    SHOW_MY_BOOL},
   {"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG },
   {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONGLONG},
   {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group,	SHOW_LONG},
-  {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR},
+  {sys_innodb_log_group_home_dir.name, (char*) &sys_innodb_log_group_home_dir, SHOW_SYS},
   {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS},
   {sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS},
   {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
@@ -1026,7 +1039,7 @@ struct show_var_st init_vars[]= {
   {sys_optimizer_search_depth.name,(char*) &sys_optimizer_search_depth,
    SHOW_SYS},
   {"pid_file",                (char*) pidfile_name,                 SHOW_CHAR},
-  {"plugin_dir",              (char*) opt_plugin_dir,               SHOW_CHAR},
+  {sys_plugin_dir.name,       (char*) &sys_plugin_dir,              SHOW_SYS},
   {"port",                    (char*) &mysqld_port,                  SHOW_INT},
   {sys_preload_buff_size.name, (char*) &sys_preload_buff_size,      SHOW_SYS},
   {"protocol_version",        (char*) &protocol_version,            SHOW_INT},
@@ -1068,7 +1081,7 @@ struct show_var_st init_vars[]= {
 #ifdef HAVE_REPLICATION
   {sys_slave_compressed_protocol.name,
     (char*) &sys_slave_compressed_protocol,           SHOW_SYS},
-  {"slave_load_tmpdir",       (char*) &slave_load_tmpdir,           SHOW_CHAR_PTR},
+  {sys_slave_load_tmpdir.name,(char*) &sys_slave_load_tmpdir,       SHOW_SYS},
   {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout,	    SHOW_SYS},
   {"slave_skip_errors",       (char*) &slave_error_mask,            SHOW_SLAVE_SKIP_ERRORS},
   {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries,   SHOW_SYS},
@@ -1175,6 +1188,7 @@ bool update_sys_var_str(sys_var_str *var
   old_value= var_str->value;
   var_str->value= res;
   var_str->value_length= new_length;
+  var_str->is_os_charset= FALSE;
   rw_unlock(var_mutex);
   my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
   return 0;
@@ -1914,11 +1928,11 @@ Item *sys_var::item(THD *thd, enum_var_t
     char *str= (char*) value_ptr(thd, var_type, base);
     if (str)
       tmp= new Item_string(str, strlen(str),
-                           system_charset_info, DERIVATION_SYSCONST);
+                           charset(thd), DERIVATION_SYSCONST);
     else
     {
       tmp= new Item_null();
-      tmp->collation.set(system_charset_info, DERIVATION_SYSCONST);
+      tmp->collation.set(charset(thd), DERIVATION_SYSCONST);
     }
     pthread_mutex_unlock(&LOCK_global_system_variables);
     return tmp;
@@ -1930,6 +1944,13 @@ Item *sys_var::item(THD *thd, enum_var_t
 }
 
 
+CHARSET_INFO *sys_var::charset(THD *thd)
+{
+  return is_os_charset ? thd->variables.character_set_filesystem : 
+    system_charset_info;
+}
+
+
 bool sys_var_thd_enum::update(THD *thd, set_var *var)
 {
   if (var->type == OPT_GLOBAL)

=== modified file 'sql/set_var.h'
--- a/sql/set_var.h	2008-01-23 15:03:35 +0000
+++ b/sql/set_var.h	2008-11-22 14:27:59 +0000
@@ -46,9 +46,17 @@ public:
   
   sys_after_update_func after_update;
   bool no_support_one_shot;
+  /*
+    true if the value is in character_set_filesystem, 
+    false otherwise.
+    Note that we can't use a pointer to the charset as the system var is 
+    instantiated in global scope and the charset pointers are initialized
+    later.
+  */  
+  bool is_os_charset;
   sys_var(const char *name_arg, sys_after_update_func func= NULL)
     :name(name_arg), after_update(func)
-    , no_support_one_shot(1)
+    , no_support_one_shot(1), is_os_charset(FALSE)
   {}
   virtual ~sys_var() {}
   virtual bool check(THD *thd, set_var *var);
@@ -68,6 +76,7 @@ public:
   Item *item(THD *thd, enum_var_type type, LEX_STRING *base);
   virtual bool is_struct() { return 0; }
   virtual bool is_readonly() const { return 0; }
+  CHARSET_INFO *charset(THD *thd);
 };
 
 
@@ -247,6 +256,17 @@ public:
 };
 
 
+class sys_var_const_os_str: public sys_var_const_str
+{
+public:
+  sys_var_const_os_str(const char *name_arg, const char *value_arg)
+    :sys_var_const_str(name_arg, value_arg)
+  { 
+    is_os_charset= TRUE; 
+  }
+};
+
+
 class sys_var_const_str_ptr :public sys_var
 {
 public:
@@ -276,6 +296,17 @@ public:
 };
 
 
+class sys_var_const_os_str_ptr :public sys_var_const_str_ptr
+{
+public:
+  sys_var_const_os_str_ptr(const char *name_arg, char **value_arg)
+    :sys_var_const_str_ptr(name_arg, value_arg)
+  {
+    is_os_charset= TRUE; 
+  }
+};
+
+
 class sys_var_enum :public sys_var
 {
   uint	*value; 
@@ -791,6 +822,20 @@ public:
   bool is_readonly() const { return 1; }
 };
 
+
+class sys_var_readonly_os: public sys_var_readonly
+{
+public:
+  sys_var_readonly_os(const char *name_arg, enum_var_type type,
+		   SHOW_TYPE show_type_arg,
+		   sys_value_ptr_func value_ptr_func_arg)
+    :sys_var_readonly(name_arg, type, show_type_arg, value_ptr_func_arg)
+  {
+    is_os_charset= TRUE;
+  }
+};
+
+
 class sys_var_thd_time_zone :public sys_var_thd
 {
 public:

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	2008-10-15 10:06:21 +0000
+++ b/sql/sql_show.cc	2008-11-22 14:27:59 +0000
@@ -1441,6 +1441,7 @@ static bool show_status_array(THD *thd, 
   char name_buffer[80];
   int len;
   LEX_STRING null_lex_str;
+  CHARSET_INFO *charset= system_charset_info;
   DBUG_ENTER("show_status_array");
 
   null_lex_str.str= 0;				// For sys_var->value_ptr()
@@ -1469,9 +1470,10 @@ static bool show_status_array(THD *thd, 
         long nr;
         if (show_type == SHOW_SYS)
         {
-          show_type= ((sys_var*) value)->show_type();
-          value=     (char*) ((sys_var*) value)->value_ptr(thd, value_type,
-                                                           &null_lex_str);
+          sys_var *var= ((sys_var *) value);
+          show_type= var->show_type();
+          value= (char*) var->value_ptr(thd, value_type, &null_lex_str);
+          charset= var->charset(thd);
         }
 
         pos= end= buff;
@@ -1794,7 +1796,7 @@ static bool show_status_array(THD *thd, 
         restore_record(table, s->default_values);
         table->field[0]->store(name_buffer, strlen(name_buffer),
                                system_charset_info);
-        table->field[1]->store(pos, (uint32) (end - pos), system_charset_info);
+        table->field[1]->store(pos, (uint32) (end - pos), charset);
         if (schema_table_store_record(thd, table))
           DBUG_RETURN(TRUE);
       }

Thread
bzr commit into mysql-5.0-bugteam branch (kgeorge:2714) Bug#37339Georgi Kodinov22 Nov