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) | bar | 29 May |