Bug #34289 Incorrect NAME_CONST substitution in stored procedures breaks replication
Submitted: 4 Feb 17:58 Modified: 29 Mar 18:10
Reporter: Matt Nathan
Status: Closed
Category:Server: Replication Severity:S2 (Serious)
Version:5.0.45, 5.0, 5.1, 6.0 BK OS:Any (Linux)
Assigned to: Sergey Vojtovich Target Version:5.0+,5.1.24
Tags: binary log, stored procedure, replication, name_const
Triage: D2 (Serious)

[4 Feb 17:58] Matt Nathan
Description:
The automatic substitution of variable names for NAME_CONST('varName', varVal) in the
binary logging of stored procedures is incorrect under certain conditions. 

The two cases which have caused us problems are listed below:

1) replication of collation casting

a procedure like this
create procedure collationCast()
begin
 declare var char(10) default 'the value';
 update t1 set v = 'updated' where q = var collate latin1_general_cs;
end//

This gets logged in the binary log as:
  update t1 set v = 'updated' where q = NAME_CONST('var',_latin1'the value') collate
latin1_general_cs
Which is invalid and throws an exception stating:
  COLLATION 'latin1_general_cs' is not valid for CHARACTER SET 'binary'
I would guess that this is because it it trying to collate a binary result set
(NAME_CONST) instead of a character variable.

2) replication using reserved words

While this is less important as it is easy to work around it does cause some problems when
it cannot be avoided. Stored procedures like this:
create procedure reservedWord()
begin
  declare `order` int default 1;
  insert into t2 values(`order`);
end//

places the following into the binary log:
  insert into t2 values(` NAME_CONST('order',1)`)
which gives the error:
  Unknown column ' NAME_CONST('order',1)' in 'field list'

Work arounds

For problem 1 you cab use a user variable instead of a SP variable, something like this:
create procedure collateCastFix()
begin
  declare var char(10) default 'the value';
  set @varTmp = var;
  update t1 set v = 'update fix' where q = @varTmp collate latin1_general_cs;
end//

For problem 2 it should be possible to change the name of the SP variable to something
that is not a reserved word allowing you to exclude the `` when defining it.

How to repeat:
drop database if exists testdb;
create database testdb;
use testdb;

-- for error 1
create table t1 (v char(10), q char(10)) character set latin1 collate latin1_general_ci;
insert into t1 values ('original', 'the value');
delimiter //
create procedure collationCast()
begin
 declare var char(10) default 'the value';
 update t1 set v = 'updated' where q = var collate latin1_general_cs;
end//
delimiter ;

-- for error 2
create table t2 (`order` int);
delimiter //
create procedure reservedWord()
begin
  declare `order` int default 1;
  insert into t2 values(`order`);
end//
delimiter ;

-- enable the binary log then run the following:
call collationCast();
call reservedWord();

-- the binary log should now show two invalid queries.
[4 Feb 18:51] Valeriy Kravchuk
Thank you for a problem report. Please, try to repeat with a newer version, 5.0.51a, and
inform about the results.
[5 Feb 13:42] Matt Nathan
Having tested on the latest 5.0.51a community server the first problem (collation casting)
still breaks, the second problem (variable escaping) has been fixed.

The variable escaping now produces binary log entries like:
  insert into t2 values( NAME_CONST('order',1))
instead of:
  insert into t2 values(` NAME_CONST('order',1)`)

The collation casting still produces binary log entries like:
  update t1 set v = 'updated' where q =  NAME_CONST('var',_latin1'the value') collate
latin1_general_cs
[6 Feb 1:42] Miguel Solorzano
Thank you for the feedback. It is the below error are you reporting?

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: localhost
                  Master_User: miguel
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: windows-bin.000009
          Read_Master_Log_Pos: 106
               Relay_Log_File: amanhecer-relay-bin.000023
                Relay_Log_Pos: 253
        Relay_Master_Log_File: windows-bin.000009
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 106
              Relay_Log_Space: 559
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
1 row in set (0.00 sec)

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: localhost
                  Master_User: miguel
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: windows-bin.000009
          Read_Master_Log_Pos: 1385
               Relay_Log_File: amanhecer-relay-bin.000023
                Relay_Log_Pos: 1240
        Relay_Master_Log_File: windows-bin.000009
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 1253
                   Last_Error: Error 'COLLATION 'latin1_general_cs' is not valid for
CHARACTER SET 'binary'' on query. Default database: 'testdb'. Que
ry: 'update t1 set v = 'updated' where q =  NAME_CONST('var',_latin1'the value') collate
latin1_general_cs'
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1093
              Relay_Log_Space: 1838
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 1253
               Last_SQL_Error: Error 'COLLATION 'latin1_general_cs' is not valid for
CHARACTER SET 'binary'' on query. Default database: 'testdb'. Que
ry: 'update t1 set v = 'updated' where q =  NAME_CONST('var',_latin1'the value') collate
latin1_general_cs'
1 row in set (0.00 sec)

mysql>

Thanks in advance.
[6 Feb 10:11] Matt Nathan
Yes, this is the error we are getting.
[6 Feb 15:00] Sveta Smirnova
Thank you for the report.

Verified as described.
[19 Feb 15:18] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/42555

ChangeSet@1.2575, 2008-02-19 18:16:17+04:00, svoj@mysql.com +3 -0
  BUG#34289 - Incorrect NAME_CONST substitution in stored procedures
              breaks replication
  
  NAME_CONST() didn't replicate constant character set and collation
  correctly.
  
  With this fix NAME_CONST() inherits collation from the value argument.
[19 Feb 15:35] Alexander Barkov
The patch http://lists.mysql.com/commits/42555 is ok to push.
[27 Mar 12:18] Bugs System
Pushed into 5.1.24-rc
[27 Mar 12:21] Bugs System
Pushed into 5.0.60
[27 Mar 18:49] Bugs System
Pushed into 6.0.5-alpha
[29 Mar 18:10] Jon Stephens
Bugfix documented in the 5.0.60, 5.1.24, and 6.0.5 changelogs as follows:

        The character sets and collations used for constant identifiers in
        stored procedures were not replicated correctly.
[2 Apr 21:40] Jon Stephens
Also noted in the 5.1.23-ndb-6.3.11 changelog.