List:Commits« Previous MessageNext Message »
From:bar Date:May 29 2006 10:04am
Subject:bk commit into 5.0 tree (bar:1.2143)
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.2143 06/05/29 15:04:04 bar@stripped +7 -0
  MySQL Bugs: #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.20 06/05/29 15:03:54 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.50 06/05/29 15:03:54 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.318 06/05/29 15:03:54 bar@stripped +5 -1
    Adding a new parameter to store_trigger(), to pass
    trigger body character set.

  sql/sp_head.h
    1.85 06/05/29 15:03:53 bar@stripped +1 -0
    New class member to remember body character set.

  sql/sp_head.cc
    1.215 06/05/29 15:03:53 bar@stripped +2 -0
    Remember body character set.

  mysql-test/t/trigger.test
    1.46 06/05/29 15:03:53 bar@stripped +44 -0
    Adding test case

  mysql-test/r/trigger.result
    1.41 06/05/29 15:03:53 bar@stripped +41 -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.b19443

--- 1.317/sql/sql_show.cc	2006-05-23 12:45:19 +05:00
+++ 1.318/sql/sql_show.cc	2006-05-29 15:03:54 +05:00
@@ -3217,6 +3217,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)
 {
@@ -3231,7 +3232,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);
@@ -3279,10 +3280,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;
@@ -3290,6 +3293,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.40/mysql-test/r/trigger.result	2006-05-12 14:55:14 +05:00
+++ 1.41/mysql-test/r/trigger.result	2006-05-29 15:03:53 +05:00
@@ -985,6 +985,47 @@ select * from t2;
 i	n
 1	150.00
 drop tables t1, t2;
+set names koi8r;
+create trigger tr1 before insert on t1
+show triggers;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer
+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;
+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
+show triggers;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer
+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
+drop table t1;
+set names latin1;
 DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 (
 conn_id INT,

--- 1.45/mysql-test/t/trigger.test	2006-05-12 14:55:14 +05:00
+++ 1.46/mysql-test/t/trigger.test	2006-05-29 15:03:53 +05:00
@@ -1140,6 +1140,50 @@ select * from t2;
 drop tables t1, t2;
 
 #
+# Bug#19443: SHOW TRIGGERS forgets non-latin
+# symbols in column names
+#
+set names koi8r;
+create trigger tr1 before insert on t1
+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.
+#
+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
+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.49/sql/sql_trigger.cc	2006-03-28 02:01:48 +05:00
+++ 1.50/sql/sql_trigger.cc	2006-05-29 15:03:54 +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 }
 };
 
@@ -351,7 +356,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;
 
@@ -491,12 +496,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,
@@ -827,6 +838,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,
@@ -923,10 +935,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;
 
@@ -938,8 +953,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;
@@ -1040,6 +1070,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);
 
@@ -1049,6 +1082,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->db= save_db.str;
       thd->db_length= save_db.length;
       DBUG_RETURN(1);
@@ -1077,6 +1113,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
@@ -1091,6 +1128,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)
 {
@@ -1100,6 +1138,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.19/sql/sql_trigger.h	2006-02-26 17:32:52 +04:00
+++ 1.20/sql/sql_trigger.h	2006-05-29 15:03:54 +05:00
@@ -78,6 +78,8 @@ public:
 
   List<LEX_STRING>  definers_list;
 
+  List<LEX_STRING>  charsets_list;
+
   Table_triggers_list(TABLE *table_arg):
     record1_field(0), table(table_arg)
   {
@@ -96,6 +98,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.214/sql/sp_head.cc	2006-05-24 00:00:59 +05:00
+++ 1.215/sql/sp_head.cc	2006-05-29 15:03:53 +05:00
@@ -493,6 +493,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;
 }
 
@@ -546,6 +547,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.84/sql/sp_head.h	2006-05-15 15:01:52 +05:00
+++ 1.85/sql/sp_head.h	2006-05-29 15:03:53 +05:00
@@ -137,6 +137,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;
Thread
bk commit into 5.0 tree (bar:1.2143)bar29 May