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#19443 | bar | 18 Jul |