List:Commits« Previous MessageNext Message »
From:bar Date:July 18 2006 9:46am
Subject:bk commit into 5.0 tree (bar:1.2224) BUG#19443
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of bar. When bar 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
  1.2224 06/07/18 12:46:35 bar@stripped +9 -0
  Bug#19443: SHOW TRIGGERS forgets non-latin symbols in column names
  CREATE TRIGGER statement was parsed with wrong character
  set when opening a TRG file, which caused:
  - SHOW TRIGGERS not to work correctly
  - INSERT with a trigger on a column with non-Latin name
  or with a trigger setting column's value to a string
  with non-Latin letter to fail with either error
  "unknown column name", or to insert question marks
  incorrectly.
  This patch:
  - adds "charsets" parameter into TRG file,
  - adds CHARSET_INFO* members into relevant classes
  - adds CHARSET_INFO* parameter to some functions

  sql/sql_trigger.h
    1.21 06/07/18 12:46:23 bar@stripped +3 -0
    - New parameter tp get_trigger_info(), to get trigger body character set.
    - New member into Table_triggers_list - character sets list.

  sql/sql_trigger.cc
    1.53 06/07/18 12:46:23 bar@stripped +41 -2
    Adding code to write trigger body character set into TRG file,
    and restore correct character set on loading.
    

  sql/sql_show.cc
    1.324 06/07/18 12:46:23 bar@stripped +5 -1
    Adding a new parameter to store_trigger(), to pass
    trigger body character set.

  sql/sp_head.h
    1.86 06/07/18 12:46:23 bar@stripped +1 -0
    New class member to remember body character set.

  sql/sp_head.cc
    1.219 06/07/18 12:46:23 bar@stripped +2 -0
    Remember body character set.

  mysql-test/t/trigger.test
    1.50 06/07/18 12:46:23 bar@stripped +49 -0
    Adding test case

  mysql-test/t/mysqldump.test
    1.97 06/07/18 12:46:23 bar@stripped +18 -0
    Adding test case

  mysql-test/r/trigger.result
    1.44 06/07/18 12:46:23 bar@stripped +50 -0
    Adding test case

  mysql-test/r/mysqldump.result
    1.102 06/07/18 12:46:23 bar@stripped +53 -0
    Adding test case

# 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:	bar
# Host:	bar.intranet.mysql.r18.ru
# Root:	/usr/home/bar/mysql-5.0.b19443v2

--- 1.323/sql/sql_show.cc	2006-07-03 13:19:07 +05:00
+++ 1.324/sql/sql_show.cc	2006-07-18 12:46:23 +05:00
@@ -3259,6 +3259,7 @@ static bool store_trigger(THD *thd, TABL
                           enum trg_event_type event,
                           enum trg_action_time_type timing,
                           LEX_STRING *trigger_stmt,
+                          CHARSET_INFO *stmt_cs,
                           ulong sql_mode,
                           LEX_STRING *definer_buffer)
 {
@@ -3273,7 +3274,7 @@ static bool store_trigger(THD *thd, TABL
                          trg_event_type_names[event].length, cs);
   table->field[5]->store(db, strlen(db), cs);
   table->field[6]->store(tname, strlen(tname), cs);
-  table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs);
+  table->field[9]->store(trigger_stmt->str, trigger_stmt->length, stmt_cs);
   table->field[10]->store(STRING_WITH_LEN("ROW"), cs);
   table->field[11]->store(trg_action_time_type_names[timing].str,
                           trg_action_time_type_names[timing].length, cs);
@@ -3321,10 +3322,12 @@ static int get_schema_triggers_record(TH
         ulong sql_mode;
         char definer_holder[USER_HOST_BUFF_SIZE];
         LEX_STRING definer_buffer;
+        CHARSET_INFO *stmt_cs;
         definer_buffer.str= definer_holder;
         if (triggers->get_trigger_info(thd, (enum trg_event_type) event,
                                        (enum trg_action_time_type)timing,
                                        &trigger_name, &trigger_stmt,
+                                       &stmt_cs,
                                        &sql_mode,
                                        &definer_buffer))
           continue;
@@ -3332,6 +3335,7 @@ static int get_schema_triggers_record(TH
         if (store_trigger(thd, table, base_name, file_name, &trigger_name,
                          (enum trg_event_type) event,
                          (enum trg_action_time_type) timing, &trigger_stmt,
+                         stmt_cs,
                          sql_mode,
                          &definer_buffer))
           DBUG_RETURN(1);

--- 1.43/mysql-test/r/trigger.result	2006-06-29 00:54:10 +05:00
+++ 1.44/mysql-test/r/trigger.result	2006-07-18 12:46:23 +05:00
@@ -973,6 +973,56 @@ select * from t2;
 i	n
 1	150.00
 drop tables t1, t2;
+set names koi8r;
+create table t1 (eng int(1), вег int(1));
+create trigger tr1 before insert on t1
+for each row set NEW.вег=5;
+show triggers;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer
+tr1	INSERT	t1	set NEW.вег=5	BEFORE	NULL		root@localhost
+set names cp1251;
+show triggers;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer
+tr1	INSERT	t1	set NEW.№ѓё=5	BEFORE	NULL		root@localhost
+set names utf8;
+show triggers;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer
+tr1	INSERT	t1	set NEW.б€бƒб=5	BEFORE	NULL		root@localhost
+set names koi8r;
+insert into t1 (eng) values (1);
+set names latin1;
+insert into t1 (eng) values (1);
+set names utf8;
+insert into t1 (eng) values (1);
+set names koi8r;
+select * from t1;
+eng	вег
+1	5
+1	5
+1	5
+drop table t1;
+set names koi8r;
+create table t1 (
+eng varchar(128) character set latin1,
+rus varchar(128) character set koi8r);
+create trigger tr1 before insert on t1
+for each row set NEW.rus='вег';
+show triggers;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer
+tr1	INSERT	t1	set NEW.rus='вег'	BEFORE	NULL		root@localhost
+insert into t1 (eng) values ('eng');
+set names latin1;
+insert into t1 (eng) values ('eng');
+set names utf8;
+insert into t1 (eng) values ('eng');
+set names koi8r;
+select * from t1;
+eng	rus
+eng	вег
+eng	вег
+eng	вег
+drop table t1;
+set names latin1;
 DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 (
 conn_id INT,

--- 1.49/mysql-test/t/trigger.test	2006-06-29 14:45:37 +05:00
+++ 1.50/mysql-test/t/trigger.test	2006-07-18 12:46:23 +05:00
@@ -1134,6 +1134,55 @@ select * from t2;
 drop tables t1, t2;
 
 #
+# Bug#19443: SHOW TRIGGERS forgets non-latin
+# symbols in column names
+#
+set names koi8r;
+create table t1 (eng int(1), вег int(1));
+create trigger tr1 before insert on t1
+for each row set NEW.вег=5;
+show triggers;
+set names cp1251;
+show triggers;
+set names utf8;
+show triggers;
+#
+# Let's also check that the trigger always
+# correctly sets the column with non-latin name,
+# no matter the current client character set is.
+#
+set names koi8r;
+insert into t1 (eng) values (1);
+set names latin1;
+insert into t1 (eng) values (1);
+set names utf8;
+insert into t1 (eng) values (1);
+set names koi8r;
+select * from t1;
+drop table t1;
+#
+# Let's also check that the trigger
+# correctly insert non-latin string constants,
+# independingly from the current client character set.
+#
+set names koi8r;
+create table t1 (
+  eng varchar(128) character set latin1,
+  rus varchar(128) character set koi8r);
+create trigger tr1 before insert on t1
+for each row set NEW.rus='вег';
+show triggers;
+insert into t1 (eng) values ('eng');
+set names latin1;
+insert into t1 (eng) values ('eng');
+set names utf8;
+insert into t1 (eng) values ('eng');
+set names koi8r;
+select * from t1;
+drop table t1;
+set names latin1;
+
+#
 # Test for Bug #16461 connection_id() does not work properly inside trigger
 #
 --disable_warnings

--- 1.52/sql/sql_trigger.cc	2006-07-08 22:43:03 +05:00
+++ 1.53/sql/sql_trigger.cc	2006-07-18 12:46:23 +05:00
@@ -49,6 +49,11 @@ static File_option triggers_file_paramet
     offsetof(class Table_triggers_list, definers_list),
     FILE_OPTIONS_STRLIST
   },
+  {
+    {(char *) STRING_WITH_LEN("charsets") },
+    offsetof(class Table_triggers_list, charsets_list),
+    FILE_OPTIONS_STRLIST
+  },
   { { 0, 0 }, 0, FILE_OPTIONS_STRING }
 };
 
@@ -360,7 +365,7 @@ bool Table_triggers_list::create_trigger
   LEX_STRING *trg_def, *name;
   ulonglong *trg_sql_mode;
   char trg_definer_holder[USER_HOST_BUFF_SIZE];
-  LEX_STRING *trg_definer;
+  LEX_STRING *trg_definer, *trg_charset;
   Item_trigger_field *trg_field;
   struct st_trigname trigname;
 
@@ -502,12 +507,18 @@ bool Table_triggers_list::create_trigger
       definition_modes_list.push_back(trg_sql_mode, &table->mem_root) ||
       !(trg_definer= (LEX_STRING*) alloc_root(&table->mem_root,
                                               sizeof(LEX_STRING))) ||
-      definers_list.push_back(trg_definer, &table->mem_root))
+      definers_list.push_back(trg_definer, &table->mem_root) ||
+      !(trg_charset= (LEX_STRING*) alloc_root(&table->mem_root,
+                                              sizeof(LEX_STRING))) ||
+      charsets_list.push_back(trg_charset, &table->mem_root))
+
     goto err_with_cleanup;
 
   trg_def->str= thd->query;
   trg_def->length= thd->query_length;
   *trg_sql_mode= thd->variables.sql_mode;
+  trg_charset->str= (char*) thd->variables.character_set_client->csname;
+  trg_charset->length= strlen(trg_charset->str);
 
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   if (lex->definer && !is_acl_user(lex->definer->host.str,
@@ -839,6 +850,7 @@ bool Table_triggers_list::check_n_load(T
       */
       triggers->definition_modes_list.empty();
       triggers->definers_list.empty();
+      triggers->charsets_list.empty();
 
       if (parser->parse((gptr)triggers, &table->mem_root,
                         triggers_file_parameters,
@@ -935,10 +947,13 @@ bool Table_triggers_list::check_n_load(T
 
       List_iterator_fast<ulonglong> itm(triggers->definition_modes_list);
       List_iterator_fast<LEX_STRING> it_definer(triggers->definers_list);
+      List_iterator_fast<LEX_STRING> it_charset(triggers->charsets_list);
       LEX *old_lex= thd->lex, lex;
       sp_rcontext *save_spcont= thd->spcont;
       ulong save_sql_mode= thd->variables.sql_mode;
       LEX_STRING *on_table_name;
+      CHARSET_INFO *save_charset_client= thd->variables.character_set_client;
+      CHARSET_INFO *save_coll_connection= thd->variables.collation_connection;
 
       thd->lex= &lex;
 
@@ -949,8 +964,23 @@ bool Table_triggers_list::check_n_load(T
       {
         trg_sql_mode= itm++;
         LEX_STRING *trg_definer= it_definer++;
+        LEX_STRING *trg_charset= it_charset++;
+        char csname[128];
+        uint csname_length= min(sizeof(csname)-1, trg_charset->length);
+        CHARSET_INFO *cs;
+
+        memcpy(csname, trg_charset->str, csname_length);
+        csname[csname_length]= '\0';
+        if (!(cs= get_charset_by_csname(csname, MY_CS_PRIMARY, MYF(0))))
+        {
+          my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), csname);
+          DBUG_RETURN(1);
+        }
 
         thd->variables.sql_mode= (ulong)*trg_sql_mode;
+        thd->variables.character_set_client= cs;
+        thd->variables.collation_connection= cs;
+        thd->update_charset();
         lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
 
 	thd->spcont= 0;
@@ -1057,6 +1087,9 @@ bool Table_triggers_list::check_n_load(T
       thd->lex= old_lex;
       thd->spcont= save_spcont;
       thd->variables.sql_mode= save_sql_mode;
+      thd->variables.character_set_client= save_charset_client;
+      thd->variables.collation_connection= save_coll_connection;
+      thd->update_charset();
 
       DBUG_RETURN(0);
 
@@ -1066,6 +1099,9 @@ err_with_lex_cleanup:
       thd->lex= old_lex;
       thd->spcont= save_spcont;
       thd->variables.sql_mode= save_sql_mode;
+      thd->variables.character_set_client= save_charset_client;
+      thd->variables.collation_connection= save_coll_connection;
+      thd->update_charset();
       thd->reset_db(save_db.str, save_db.length);
       DBUG_RETURN(1);
     }
@@ -1093,6 +1129,7 @@ err_with_lex_cleanup:
       time_type - trigger action time
       name      - returns name of trigger
       stmt      - returns statement of trigger
+      stmt_charset - charset of stmt
       sql_mode  - returns sql_mode of trigger
       definer_user - returns definer/creator of trigger. The caller is
                   responsible to allocate enough space for storing definer
@@ -1107,6 +1144,7 @@ bool Table_triggers_list::get_trigger_in
                                            trg_action_time_type time_type,
                                            LEX_STRING *trigger_name,
                                            LEX_STRING *trigger_stmt,
+                                           CHARSET_INFO **stmt_charset,
                                            ulong *sql_mode,
                                            LEX_STRING *definer)
 {
@@ -1116,6 +1154,7 @@ bool Table_triggers_list::get_trigger_in
   {
     *trigger_name= body->m_name;
     *trigger_stmt= body->m_body;
+    *stmt_charset= body->m_body_charset;
     *sql_mode= body->m_sql_mode;
 
     if (body->m_chistics->suid == SP_IS_NOT_SUID)

--- 1.20/sql/sql_trigger.h	2006-07-02 02:51:02 +05:00
+++ 1.21/sql/sql_trigger.h	2006-07-18 12:46:23 +05:00
@@ -83,6 +83,8 @@ public:
 
   List<LEX_STRING>  definers_list;
 
+  List<LEX_STRING>  charsets_list;
+
   Table_triggers_list(TABLE *table_arg):
     record1_field(0), table(table_arg)
   {
@@ -102,6 +104,7 @@ public:
   bool get_trigger_info(THD *thd, trg_event_type event,
                         trg_action_time_type time_type,
                         LEX_STRING *trigger_name, LEX_STRING *trigger_stmt,
+                        CHARSET_INFO **stmt_charset,
                         ulong *sql_mode,
                         LEX_STRING *definer);
 

--- 1.218/sql/sp_head.cc	2006-06-30 01:21:49 +05:00
+++ 1.219/sql/sp_head.cc	2006-07-18 12:46:23 +05:00
@@ -475,6 +475,7 @@ sp_head::init(LEX *lex)
   m_qname.length= m_db.length= m_name.length= m_params.length=
     m_body.length= m_defstr.length= 0;
   m_return_field_def.charset= NULL;
+  m_body_charset= NULL;
   DBUG_VOID_RETURN;
 }
 
@@ -521,6 +522,7 @@ sp_head::init_strings(THD *thd, LEX *lex
 
   m_body.length= endp - m_body_begin;
   m_body.str= strmake_root(root, (char *)m_body_begin, m_body.length);
+  m_body_charset= thd->variables.character_set_client;
   m_defstr.length= endp - lex->buf;
   m_defstr.str= strmake_root(root, (char *)lex->buf, m_defstr.length);
   DBUG_VOID_RETURN;

--- 1.85/sql/sp_head.h	2006-06-27 01:47:47 +05:00
+++ 1.86/sql/sp_head.h	2006-07-18 12:46:23 +05:00
@@ -128,6 +128,7 @@ public:
   uint m_old_cmq;		// Old CLIENT_MULTI_QUERIES value
   st_sp_chistics *m_chistics;
   ulong m_sql_mode;		// For SHOW CREATE and execution
+  CHARSET_INFO *m_body_charset;
   LEX_STRING m_qname;		// db.name
   LEX_STRING m_db;
   LEX_STRING m_name;

--- 1.101/mysql-test/r/mysqldump.result	2006-07-14 04:25:06 +05:00
+++ 1.102/mysql-test/r/mysqldump.result	2006-07-18 12:46:23 +05:00
@@ -2158,6 +2158,59 @@ set @fired:= "No";
 end if;
 end	BEFORE	#	STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER	root@localhost
 DROP TABLE t1, t2;
+set names koi8r;
+create table t1 (eng int(1), вег char(10));
+create trigger tr1 before insert on t1
+for each row set NEW.вег='вег';
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+  `eng` int(1) default NULL,
+  `б€бƒб` char(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+
+/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;
+DELIMITER ;;
+/*!50003 SET SESSION SQL_MODE="" */;;
+/*!50003 CREATE */ /*!50017 DEFINER=`root`@`localhost` */ /*!50003 TRIGGER `tr1` BEFORE
INSERT ON `t1` FOR EACH ROW set NEW.б€бƒб='б€бƒб' */;;
+
+DELIMITER ;
+/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+drop table t1;
+show tables;
+Tables_in_test
+t1
+show triggers;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer
+tr1	INSERT	t1	set NEW.вег='вег'	BEFORE	#		root@localhost
+drop table t1;
+set names latin1;
 --port=1234
 --port=1234
 DROP TABLE IF EXISTS `test1`;

--- 1.96/mysql-test/t/mysqldump.test	2006-07-14 04:25:06 +05:00
+++ 1.97/mysql-test/t/mysqldump.test	2006-07-18 12:46:23 +05:00
@@ -864,6 +864,24 @@ show triggers;
 DROP TABLE t1, t2;
 
 #
+# Test for dumping triggers with non-Latin letters
+#
+set names koi8r;
+create table t1 (eng int(1), вег char(10));
+create trigger tr1 before insert on t1
+for each row set NEW.вег='вег';
+--exec $MYSQL_DUMP --skip-comments test
+# dump and reload
+--exec $MYSQL_DUMP --skip-comments test > $MYSQLTEST_VARDIR/tmp/mysqldump.sql
+drop table t1;
+--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqldump.sql
+show tables;
+--replace_column 6 #
+show triggers;
+drop table t1;
+set names latin1;
+
+#
 # Bugs #9136, #12917: problems with --defaults-extra-file option
 #
 
Thread
bk commit into 5.0 tree (bar:1.2224) BUG#19443bar18 Jul