Commit 892760d9 authored by Praveenkumar Hulakund's avatar Praveenkumar Hulakund

Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES IGNORED AND BREAKS REPLICATION

Analysis:
========================
sql_mode "NO_BACKSLASH_ESCAPES": When user want to use backslash as character input,
instead of escape character in a string literal then sql_mode can be set to 
"NO_BACKSLASH_ESCAPES". With this mode enabled, backslash becomes an ordinary 
character like any other. 

SQL_MODE set applies to the current client session. And while creating the stored 
procedure, MySQL stores the current sql_mode and always executes the stored 
procedure in sql_mode stored with the Procedure, regardless of the server SQL 
mode in effect when the routine is invoked.  

In the scenario (for which bug is reported), the routine is created with 
sql_mode=NO_BACKSLASH_ESCAPES. And routine is executed with the invoker sql_mode
is "" (NOT SET) by executing statement "call testp('Axel\'s')".
Since invoker sql_mode is "" (NOT_SET), the '\' in 'Axel\'s'(argument to function)
is considered as escape character and column "a" (of table "t1") values are 
updated with "Axel's". The binary log generated for above update operation is as below,

  set sql_mode=XXXXXX (for no_backslash_escapes)
  update test.t1 set a= NAME_CONST('var',_latin1'Axel\'s' COLLATE 'latin1_swedish_ci');

While logging stored procedure statements, the local variables (params) used in
statements are replaced with the NAME_CONST(var_name, var_value) (Internal function) 
(http://dev.mysql.com/doc/refman/5.6/en/miscellaneous-functions.html#function_name-const)

On slave, these logs are applied. NAME_CONST is parsed to get the variable and its
value. Since, stored procedure is created with sql_mode="NO_BACKSLASH_ESCAPES", the sql_mode
is also logged in. So that at slave this sql_mode is set before executing the statements
of routine.  So at slave, sql_mode is set to "NO_BACKSLASH_ESCAPES" and then while
parsing NAME_CONST of string variable, '\' is considered as NON ESCAPE character
and parsing reported error for "'" (as we have only one "'" no backslash). 

At slave, parsing was proper with sql_mode "NO_BACKSLASH_ESCAPES".
But above error reported while writing bin log, "'" (of Axel's) is escaped with
"\" character. Actually, all special characters (n, r, ', ", \, 0...) are escaped
while writing NAME_CONST for string variable(param, local variable) in bin log 
irrespective of "NO_BACKSLASH_ESCAPES" sql_mode. So, basically, the problem is 
that logging string parameter does not take into account sql_mode value.

Fix:
========================
So when sql_mode is set to "NO_BACKSLASH_ESCAPES", escaping  characters as 
(n, r, ', ", \, 0...) should be avoided. To do so, added a check to not to
escape such characters while writing NAME_CONST for string variables in bin 
log. 
And when sql_mode is set to NO_BACKSLASH_ESCAPES, quote character "'" is
represented as ''.
http://dev.mysql.com/doc/refman/5.6/en/string-literals.html (There are several 
ways to include quote characters within a string: )
parents 26ed79ec 9af695fb
...@@ -527,3 +527,207 @@ SELECT * FROM mysql.columns_priv WHERE Host = 'localhost' AND User LIKE 'user_%P ...@@ -527,3 +527,207 @@ SELECT * FROM mysql.columns_priv WHERE Host = 'localhost' AND User LIKE 'user_%P
Host Db User Table_name Column_name Timestamp Column_priv Host Db User Table_name Column_name Timestamp Column_priv
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
#
# Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES
# IGNORED AND BREAKS REPLICATION
#
DROP TABLE IF EXISTS test_table;
DROP FUNCTION IF EXISTS test_function;
CREATE TABLE test_table (c1 CHAR(50));
SET @org_mode=@@sql_mode;
SET @@sql_mode='';
PREPARE insert_stmt FROM 'INSERT INTO test_table VALUES (?)';
PREPARE update_stmt FROM 'UPDATE test_table SET c1= ? WHERE c1= ?';
CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50)
BEGIN
DECLARE char_val CHAR(50);
SELECT c1 INTO char_val FROM test_table WHERE c1=var;
RETURN char_val;
END
$
SET @var1='abcd\'ef';
SET @var2='abcd\"ef';
SET @var3='abcd\bef';
SET @var4='abcd\nef';
SET @var5='abcd\ref';
SET @var6='abcd\tef';
SET @var7='abcd\\ef';
SET @var8='abcd\%ef';
SET @var9='abcd\_ef';
SET @to_var1='wxyz\'ef';
SET @to_var2='wxyz\"ef';
SET @to_var3='wxyz\bef';
SET @to_var4='wxyz\nef';
SET @to_var5='wxyz\ref';
SET @to_var6='wxyz\tef';
SET @to_var7='wxyz\\ef';
SET @to_var8='wxyz\%ef';
SET @to_var9='wxyz\_ef';
# STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT
EXECUTE insert_stmt USING @var1;
EXECUTE insert_stmt USING @var2;
EXECUTE insert_stmt USING @var3;
EXECUTE insert_stmt USING @var4;
EXECUTE insert_stmt USING @var5;
EXECUTE insert_stmt USING @var6;
EXECUTE insert_stmt USING @var7;
EXECUTE insert_stmt USING @var8;
EXECUTE insert_stmt USING @var9;
SELECT * FROM test_table;
c1
abcd'ef
abcd"ef
abcdef
abcd
ef
abcd ef
abcd ef
abcd\ef
abcd\%ef
abcd\_ef
EXECUTE update_stmt USING @to_var1, @var1;
EXECUTE update_stmt USING @to_var2, @var2;
EXECUTE update_stmt USING @to_var3, @var3;
EXECUTE update_stmt USING @to_var4, @var4;
EXECUTE update_stmt USING @to_var5, @var5;
EXECUTE update_stmt USING @to_var6, @var6;
EXECUTE update_stmt USING @to_var7, @var7;
EXECUTE update_stmt USING @to_var8, @var8;
EXECUTE update_stmt USING @to_var9, @var9;
SELECT * FROM test_table;
c1
wxyz'ef
wxyz"ef
wxyzef
wxyz
ef
wxyz ef
wxyz ef
wxyz\ef
wxyz\%ef
wxyz\_ef
# END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT
# STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING
select test_function(@to_var1);
test_function(@to_var1)
wxyz'ef
SELECT test_function(@to_var2);
test_function(@to_var2)
wxyz"ef
SELECT test_function(@to_var3);
test_function(@to_var3)
wxyzef
SELECT test_function(@to_var4);
test_function(@to_var4)
wxyz
ef
SELECT test_function(@to_var5);
test_function(@to_var5)
wxyz ef
SELECT test_function(@to_var6);
test_function(@to_var6)
wxyz ef
SELECT test_function(@to_var7);
test_function(@to_var7)
wxyz\ef
SELECT test_function(@to_var8);
test_function(@to_var8)
wxyz\%ef
SELECT test_function(@to_var9);
test_function(@to_var9)
wxyz\_ef
# END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING
DELETE FROM test_table;
DROP FUNCTION test_function;
SET @@sql_mode='NO_BACKSLASH_ESCAPES';
CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50)
BEGIN
DECLARE char_val CHAR(50);
SELECT c1 INTO char_val FROM test_table WHERE c1=var;
RETURN char_val;
END
$
# STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT
EXECUTE insert_stmt USING @var1;
EXECUTE insert_stmt USING @var2;
EXECUTE insert_stmt USING @var3;
EXECUTE insert_stmt USING @var4;
EXECUTE insert_stmt USING @var5;
EXECUTE insert_stmt USING @var6;
EXECUTE insert_stmt USING @var7;
EXECUTE insert_stmt USING @var8;
EXECUTE insert_stmt USING @var9;
SELECT * FROM test_table;
c1
abcd'ef
abcd"ef
abcdef
abcd
ef
abcd ef
abcd ef
abcd\ef
abcd\%ef
abcd\_ef
EXECUTE update_stmt USING @to_var1, @var1;
EXECUTE update_stmt USING @to_var2, @var2;
EXECUTE update_stmt USING @to_var3, @var3;
EXECUTE update_stmt USING @to_var4, @var4;
EXECUTE update_stmt USING @to_var5, @var5;
EXECUTE update_stmt USING @to_var6, @var6;
EXECUTE update_stmt USING @to_var7, @var7;
EXECUTE update_stmt USING @to_var8, @var8;
EXECUTE update_stmt USING @to_var9, @var9;
SELECT * FROM test_table;
c1
wxyz'ef
wxyz"ef
wxyzef
wxyz
ef
wxyz ef
wxyz ef
wxyz\ef
wxyz\%ef
wxyz\_ef
# END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT
# STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING
select test_function(@to_var1);
test_function(@to_var1)
wxyz'ef
SELECT test_function(@to_var2);
test_function(@to_var2)
wxyz"ef
SELECT test_function(@to_var3);
test_function(@to_var3)
wxyzef
SELECT test_function(@to_var4);
test_function(@to_var4)
wxyz
ef
SELECT test_function(@to_var5);
test_function(@to_var5)
wxyz ef
SELECT test_function(@to_var6);
test_function(@to_var6)
wxyz ef
SELECT test_function(@to_var7);
test_function(@to_var7)
wxyz\ef
SELECT test_function(@to_var8);
test_function(@to_var8)
wxyz\%ef
SELECT test_function(@to_var9);
test_function(@to_var9)
wxyz\_ef
# END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING
DROP TABLE test_table;
DROP FUNCTION test_function;
SET @@sql_mode= @org_mode;
#End of Test for Bug#12601974
......
...@@ -38,3 +38,114 @@ DROP VIEW testView; ...@@ -38,3 +38,114 @@ DROP VIEW testView;
DROP TABLE t1; DROP TABLE t1;
SET @@global.sql_mode= @old_sql_mode; SET @@global.sql_mode= @old_sql_mode;
SET @@session.binlog_format=@old_binlog_format; SET @@session.binlog_format=@old_binlog_format;
#
# Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES
# IGNORED AND BREAKS REPLICATION
#
DROP DATABASE IF EXISTS mysqltest_db;
DROP TABLE IF EXISTS test_table;
CREATE DATABASE mysqltest_db;
USE mysqltest_db;
CREATE TABLE test_table (c1 CHAR(50));
SET @org_mode=@@sql_mode;
SET @@sql_mode='';
CREATE PROCEDURE proc_without_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50))
BEGIN
DECLARE var1 CHAR(50) DEFAULT param1;
DECLARE var2 CHAR(50) DEFAULT param2;
DECLARE var3 CHAR(50) DEFAULT 'abcd\bef';
DECLARE var4 CHAR(50) DEFAULT 'abcd\nef';
DECLARE var5 CHAR(50) DEFAULT 'abcd\ref';
DECLARE var6 CHAR(50) DEFAULT 'abcd\tef';
DECLARE var7 CHAR(50) DEFAULT 'abcd\\ef';
DECLARE var8 CHAR(50) DEFAULT 'abcd\%ef';
DECLARE var9 CHAR(50) DEFAULT 'abcd\_ef';
INSERT INTO test_table VALUES (var1);
INSERT INTO test_table VALUES (var2);
INSERT INTO test_table VALUES (var3);
INSERT INTO test_table VALUES (var4);
INSERT INTO test_table VALUES (var5);
INSERT INTO test_table VALUES (var6);
INSERT INTO test_table VALUES (var7);
INSERT INTO test_table VALUES (var8);
INSERT INTO test_table VALUES (var9);
END
$
SET @@sql_mode='NO_BACKSLASH_ESCAPES'$
CREATE PROCEDURE proc_with_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50))
BEGIN
DECLARE var1 CHAR(50) DEFAULT param1;
DECLARE var2 CHAR(50) DEFAULT param2;
DECLARE var3 CHAR(50) DEFAULT 'wxyz\bef';
DECLARE var4 CHAR(50) DEFAULT 'wxyz\nef';
DECLARE var5 CHAR(50) DEFAULT 'wxyz\ref';
DECLARE var6 CHAR(50) DEFAULT 'wxyz\tef';
DECLARE var7 CHAR(50) DEFAULT 'wxyz\\ef';
DECLARE var8 CHAR(50) DEFAULT 'wxyz\%ef';
DECLARE var9 CHAR(50) DEFAULT 'wxyz\_ef';
INSERT INTO test_table VALUES (var1);
INSERT INTO test_table VALUES (var2);
INSERT INTO test_table VALUES (var3);
INSERT INTO test_table VALUES (var4);
INSERT INTO test_table VALUES (var5);
INSERT INTO test_table VALUES (var6);
INSERT INTO test_table VALUES (var7);
INSERT INTO test_table VALUES (var8);
INSERT INTO test_table VALUES (var9);
END
$
SET @@sql_mode='';
CALL proc_without_sql_mode('abcd\'ef', 'abcd\"ef');
CALL proc_with_sql_mode('wxyz\'ef', 'wxyz\"ef');
SELECT * FROM test_table;
c1
abcd'ef
abcd"ef
abcdef
abcd
ef
abcd ef
abcd ef
abcd\ef
abcd\%ef
abcd\_ef
wxyz'ef
wxyz"ef
wxyz\bef
wxyz\nef
wxyz\ref
wxyz\tef
wxyz\\ef
wxyz\%ef
wxyz\_ef
"Dropping table test_table"
DROP TABLE test_table;
#"test_table" content after replaying the binlog
SELECT * FROM test_table;
c1
abcd'ef
abcd"ef
abcdef
abcd
ef
abcd ef
abcd ef
abcd\ef
abcd\%ef
abcd\_ef
wxyz'ef
wxyz"ef
wxyz\bef
wxyz\nef
wxyz\ref
wxyz\tef
wxyz\\ef
wxyz\%ef
wxyz\_ef
#Clean up
DROP DATABASE mysqltest_db;
SET @@sql_mode= @org_mode;
use test;
#End of Test for Bug#12601974
......
...@@ -73,3 +73,99 @@ DROP TABLE t1; ...@@ -73,3 +73,99 @@ DROP TABLE t1;
SET @@global.sql_mode= @old_sql_mode; SET @@global.sql_mode= @old_sql_mode;
SET @@session.binlog_format=@old_binlog_format; SET @@session.binlog_format=@old_binlog_format;
--echo
--echo #
--echo # Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES
--echo # IGNORED AND BREAKS REPLICATION
--echo #
--disable_warnings
DROP DATABASE IF EXISTS mysqltest_db;
DROP TABLE IF EXISTS test_table;
--enable_warnings
CREATE DATABASE mysqltest_db;
USE mysqltest_db;
CREATE TABLE test_table (c1 CHAR(50));
SET @org_mode=@@sql_mode;
SET @@sql_mode='';
DELIMITER $;
CREATE PROCEDURE proc_without_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50))
BEGIN
DECLARE var1 CHAR(50) DEFAULT param1;
DECLARE var2 CHAR(50) DEFAULT param2;
DECLARE var3 CHAR(50) DEFAULT 'abcd\bef';
DECLARE var4 CHAR(50) DEFAULT 'abcd\nef';
DECLARE var5 CHAR(50) DEFAULT 'abcd\ref';
DECLARE var6 CHAR(50) DEFAULT 'abcd\tef';
DECLARE var7 CHAR(50) DEFAULT 'abcd\\ef';
DECLARE var8 CHAR(50) DEFAULT 'abcd\%ef';
DECLARE var9 CHAR(50) DEFAULT 'abcd\_ef';
INSERT INTO test_table VALUES (var1);
INSERT INTO test_table VALUES (var2);
INSERT INTO test_table VALUES (var3);
INSERT INTO test_table VALUES (var4);
INSERT INTO test_table VALUES (var5);
INSERT INTO test_table VALUES (var6);
INSERT INTO test_table VALUES (var7);
INSERT INTO test_table VALUES (var8);
INSERT INTO test_table VALUES (var9);
END
$
SET @@sql_mode='NO_BACKSLASH_ESCAPES'$
CREATE PROCEDURE proc_with_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50))
BEGIN
DECLARE var1 CHAR(50) DEFAULT param1;
DECLARE var2 CHAR(50) DEFAULT param2;
DECLARE var3 CHAR(50) DEFAULT 'wxyz\bef';
DECLARE var4 CHAR(50) DEFAULT 'wxyz\nef';
DECLARE var5 CHAR(50) DEFAULT 'wxyz\ref';
DECLARE var6 CHAR(50) DEFAULT 'wxyz\tef';
DECLARE var7 CHAR(50) DEFAULT 'wxyz\\ef';
DECLARE var8 CHAR(50) DEFAULT 'wxyz\%ef';
DECLARE var9 CHAR(50) DEFAULT 'wxyz\_ef';
INSERT INTO test_table VALUES (var1);
INSERT INTO test_table VALUES (var2);
INSERT INTO test_table VALUES (var3);
INSERT INTO test_table VALUES (var4);
INSERT INTO test_table VALUES (var5);
INSERT INTO test_table VALUES (var6);
INSERT INTO test_table VALUES (var7);
INSERT INTO test_table VALUES (var8);
INSERT INTO test_table VALUES (var9);
END
$
DELIMITER ;$
SET @@sql_mode='';
CALL proc_without_sql_mode('abcd\'ef', 'abcd\"ef');
CALL proc_with_sql_mode('wxyz\'ef', 'wxyz\"ef');
SELECT * FROM test_table;
let $MYSQLD_DATADIR= `select @@datadir`;
--exec $MYSQL_BINLOG --force-if-open -d mysqltest_db $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog
--echo "Dropping table test_table"
DROP TABLE test_table;
--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog"
--echo #"test_table" content after replaying the binlog
SELECT * FROM test_table;
--echo #Clean up
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog
DROP DATABASE mysqltest_db;
SET @@sql_mode= @org_mode;
use test;
--echo
--echo #End of Test for Bug#12601974
...@@ -344,3 +344,157 @@ SELECT * FROM mysql.columns_priv WHERE Host = 'localhost' AND User LIKE 'user_%P ...@@ -344,3 +344,157 @@ SELECT * FROM mysql.columns_priv WHERE Host = 'localhost' AND User LIKE 'user_%P
# Cleanup # Cleanup
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
--echo
--echo #
--echo # Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES
--echo # IGNORED AND BREAKS REPLICATION
--echo #
--disable_warnings
DROP TABLE IF EXISTS test_table;
DROP FUNCTION IF EXISTS test_function;
--enable_warnings
CREATE TABLE test_table (c1 CHAR(50));
SET @org_mode=@@sql_mode;
SET @@sql_mode='';
PREPARE insert_stmt FROM 'INSERT INTO test_table VALUES (?)';
PREPARE update_stmt FROM 'UPDATE test_table SET c1= ? WHERE c1= ?';
DELIMITER $;
CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50)
BEGIN
DECLARE char_val CHAR(50);
SELECT c1 INTO char_val FROM test_table WHERE c1=var;
RETURN char_val;
END
$
DELIMITER ;$
SET @var1='abcd\'ef';
SET @var2='abcd\"ef';
SET @var3='abcd\bef';
SET @var4='abcd\nef';
SET @var5='abcd\ref';
SET @var6='abcd\tef';
SET @var7='abcd\\ef';
SET @var8='abcd\%ef';
SET @var9='abcd\_ef';
SET @to_var1='wxyz\'ef';
SET @to_var2='wxyz\"ef';
SET @to_var3='wxyz\bef';
SET @to_var4='wxyz\nef';
SET @to_var5='wxyz\ref';
SET @to_var6='wxyz\tef';
SET @to_var7='wxyz\\ef';
SET @to_var8='wxyz\%ef';
SET @to_var9='wxyz\_ef';
--echo # STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT
EXECUTE insert_stmt USING @var1;
EXECUTE insert_stmt USING @var2;
EXECUTE insert_stmt USING @var3;
EXECUTE insert_stmt USING @var4;
EXECUTE insert_stmt USING @var5;
EXECUTE insert_stmt USING @var6;
EXECUTE insert_stmt USING @var7;
EXECUTE insert_stmt USING @var8;
EXECUTE insert_stmt USING @var9;
SELECT * FROM test_table;
EXECUTE update_stmt USING @to_var1, @var1;
EXECUTE update_stmt USING @to_var2, @var2;
EXECUTE update_stmt USING @to_var3, @var3;
EXECUTE update_stmt USING @to_var4, @var4;
EXECUTE update_stmt USING @to_var5, @var5;
EXECUTE update_stmt USING @to_var6, @var6;
EXECUTE update_stmt USING @to_var7, @var7;
EXECUTE update_stmt USING @to_var8, @var8;
EXECUTE update_stmt USING @to_var9, @var9;
SELECT * FROM test_table;
--echo
--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT
--echo # STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING
select test_function(@to_var1);
SELECT test_function(@to_var2);
SELECT test_function(@to_var3);
SELECT test_function(@to_var4);
SELECT test_function(@to_var5);
SELECT test_function(@to_var6);
SELECT test_function(@to_var7);
SELECT test_function(@to_var8);
SELECT test_function(@to_var9);
--echo
--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING
DELETE FROM test_table;
DROP FUNCTION test_function;
SET @@sql_mode='NO_BACKSLASH_ESCAPES';
DELIMITER $;
CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50)
BEGIN
DECLARE char_val CHAR(50);
SELECT c1 INTO char_val FROM test_table WHERE c1=var;
RETURN char_val;
END
$
DELIMITER ;$
--echo # STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT
EXECUTE insert_stmt USING @var1;
EXECUTE insert_stmt USING @var2;
EXECUTE insert_stmt USING @var3;
EXECUTE insert_stmt USING @var4;
EXECUTE insert_stmt USING @var5;
EXECUTE insert_stmt USING @var6;
EXECUTE insert_stmt USING @var7;
EXECUTE insert_stmt USING @var8;
EXECUTE insert_stmt USING @var9;
SELECT * FROM test_table;
EXECUTE update_stmt USING @to_var1, @var1;
EXECUTE update_stmt USING @to_var2, @var2;
EXECUTE update_stmt USING @to_var3, @var3;
EXECUTE update_stmt USING @to_var4, @var4;
EXECUTE update_stmt USING @to_var5, @var5;
EXECUTE update_stmt USING @to_var6, @var6;
EXECUTE update_stmt USING @to_var7, @var7;
EXECUTE update_stmt USING @to_var8, @var8;
EXECUTE update_stmt USING @to_var9, @var9;
SELECT * FROM test_table;
--echo
--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT
--echo # STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING
select test_function(@to_var1);
SELECT test_function(@to_var2);
SELECT test_function(@to_var3);
SELECT test_function(@to_var4);
SELECT test_function(@to_var5);
SELECT test_function(@to_var6);
SELECT test_function(@to_var7);
SELECT test_function(@to_var8);
SELECT test_function(@to_var9);
--echo
--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING
DROP TABLE test_table;
DROP FUNCTION test_function;
SET @@sql_mode= @org_mode;
--echo
--echo #End of Test for Bug#12601974
...@@ -3085,7 +3085,7 @@ String *Item_param::val_str(String* str) ...@@ -3085,7 +3085,7 @@ String *Item_param::val_str(String* str)
that binary log contains wrong statement that binary log contains wrong statement
*/ */
const String *Item_param::query_val_str(String* str) const const String *Item_param::query_val_str(THD *thd, String* str) const
{ {
switch (state) { switch (state) {
case INT_VALUE: case INT_VALUE:
...@@ -3123,7 +3123,8 @@ const String *Item_param::query_val_str(String* str) const ...@@ -3123,7 +3123,8 @@ const String *Item_param::query_val_str(String* str) const
case LONG_DATA_VALUE: case LONG_DATA_VALUE:
{ {
str->length(0); str->length(0);
append_query_string(value.cs_info.character_set_client, &str_value, str); append_query_string(thd, value.cs_info.character_set_client, &str_value,
str);
break; break;
} }
case NULL_VALUE: case NULL_VALUE:
...@@ -3256,7 +3257,7 @@ void Item_param::print(String *str, enum_query_type query_type) ...@@ -3256,7 +3257,7 @@ void Item_param::print(String *str, enum_query_type query_type)
char buffer[STRING_BUFFER_USUAL_SIZE]; char buffer[STRING_BUFFER_USUAL_SIZE];
String tmp(buffer, sizeof(buffer), &my_charset_bin); String tmp(buffer, sizeof(buffer), &my_charset_bin);
const String *res; const String *res;
res= query_val_str(&tmp); res= query_val_str(current_thd, &tmp);
str->append(*res); str->append(*res);
} }
} }
......
...@@ -1703,7 +1703,7 @@ public: ...@@ -1703,7 +1703,7 @@ public:
*/ */
void (*set_param_func)(Item_param *param, uchar **pos, ulong len); void (*set_param_func)(Item_param *param, uchar **pos, ulong len);
const String *query_val_str(String *str) const; const String *query_val_str(THD *thd, String *str) const;
bool convert_str_value(THD *thd); bool convert_str_value(THD *thd);
......
...@@ -572,7 +572,7 @@ char *str_to_hex(char *to, const char *from, uint len) ...@@ -572,7 +572,7 @@ char *str_to_hex(char *to, const char *from, uint len)
*/ */
int int
append_query_string(CHARSET_INFO *csinfo, append_query_string(THD *thd, CHARSET_INFO *csinfo,
String const *from, String *to) String const *from, String *to)
{ {
char *beg, *ptr; char *beg, *ptr;
...@@ -587,9 +587,26 @@ append_query_string(CHARSET_INFO *csinfo, ...@@ -587,9 +587,26 @@ append_query_string(CHARSET_INFO *csinfo,
else else
{ {
*ptr++= '\''; *ptr++= '\'';
if (!(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
{
ptr+= escape_string_for_mysql(csinfo, ptr, 0, ptr+= escape_string_for_mysql(csinfo, ptr, 0,
from->ptr(), from->length()); from->ptr(), from->length());
*ptr++='\''; }
else
{
const char *frm_str= from->ptr();
for (; frm_str < (from->ptr() + from->length()); frm_str++)
{
/* Using '' way to represent "'" */
if (*frm_str == '\'')
*ptr++= *frm_str;
*ptr++= *frm_str;
}
}
*ptr++= '\'';
} }
to->length(orig_len + ptr - beg); to->length(orig_len + ptr - beg);
return 0; return 0;
......
...@@ -799,7 +799,7 @@ bool delete_precheck(THD *thd, TABLE_LIST *tables); ...@@ -799,7 +799,7 @@ bool delete_precheck(THD *thd, TABLE_LIST *tables);
bool insert_precheck(THD *thd, TABLE_LIST *tables); bool insert_precheck(THD *thd, TABLE_LIST *tables);
bool create_table_precheck(THD *thd, TABLE_LIST *tables, bool create_table_precheck(THD *thd, TABLE_LIST *tables,
TABLE_LIST *create_table); TABLE_LIST *create_table);
int append_query_string(CHARSET_INFO *csinfo, int append_query_string(THD *thd, CHARSET_INFO *csinfo,
String const *from, String *to); String const *from, String *to);
void get_default_definer(THD *thd, LEX_USER *definer); void get_default_definer(THD *thd, LEX_USER *definer);
......
...@@ -157,7 +157,7 @@ sp_get_item_value(THD *thd, Item *item, String *str) ...@@ -157,7 +157,7 @@ sp_get_item_value(THD *thd, Item *item, String *str)
buf.append(result->charset()->csname); buf.append(result->charset()->csname);
if (cs->escape_with_backslash_is_dangerous) if (cs->escape_with_backslash_is_dangerous)
buf.append(' '); buf.append(' ');
append_query_string(cs, result, &buf); append_query_string(thd, cs, result, &buf);
buf.append(" COLLATE '"); buf.append(" COLLATE '");
buf.append(item->collation.collation->name); buf.append(item->collation.collation->name);
buf.append('\''); buf.append('\'');
......
...@@ -795,7 +795,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, ...@@ -795,7 +795,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array,
*/ */
else if (! is_param_long_data_type(param)) else if (! is_param_long_data_type(param))
DBUG_RETURN(1); DBUG_RETURN(1);
res= param->query_val_str(&str); res= param->query_val_str(thd, &str);
if (param->convert_str_value(thd)) if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */ DBUG_RETURN(1); /* out of memory */
...@@ -969,7 +969,7 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt, ...@@ -969,7 +969,7 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt,
DBUG_RETURN(1); DBUG_RETURN(1);
} }
} }
res= param->query_val_str(&str); res= param->query_val_str(thd, &str);
if (param->convert_str_value(thd)) if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */ DBUG_RETURN(1); /* out of memory */
...@@ -1115,7 +1115,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, ...@@ -1115,7 +1115,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
setup_one_conversion_function(thd, param, param->param_type); setup_one_conversion_function(thd, param, param->param_type);
if (param->set_from_user_var(thd, entry)) if (param->set_from_user_var(thd, entry))
DBUG_RETURN(1); DBUG_RETURN(1);
val= param->query_val_str(&buf); val= param->query_val_str(thd, &buf);
if (param->convert_str_value(thd)) if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */ DBUG_RETURN(1); /* out of memory */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment