Bug#11902767/Bug#60580: Statement improperly replicated crashes slave SQL thread

If LOAD DATA INFILE featured a SET clause, the name=value pairs
would be regenerated using item::print. Unfortunately, that code
is mostly optimized for EXPLAIN EXTENDED output and such, and can
not be relied on to return valid SQL.

We now name each value its original, user-supplied form and use
that to create LOAD DATA INFILE statements for statement-based
replication.

mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result:
  minor change in syntactic sugar
mysql-test/suite/rpl/r/rpl_loaddatalocal.result:
  add test case
mysql-test/suite/rpl/t/rpl_loaddatalocal.test:
  add test case
sql/sql_load.cc:
  Do not try to item::print values in LOAD DATA INFILE's
  SET clause; they might not even be valid SQL at this
  point. Use our saved version instead.
sql/sql_yacc.yy:
  If LOAD DATA INFILE has SET name=val clauses, tag the
  individual val-parts with the user's version so we can
  later replicate that, rather than the smashed pieces
  we'd get from item::print once the optimizer's through
  with our poor values.
parent 7f6ce96d
......@@ -698,7 +698,7 @@ master-bin.000001 # Query # # BEGIN
master-bin.000001 # Intvar # # INSERT_ID=10
master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=#
master-bin.000001 # Intvar # # INSERT_ID=10
master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, @b) SET `b`=((@b) + `bug27417`(2)) ;file_id=#
master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, @b) SET `b`= @b + bug27417(2) ;file_id=#
master-bin.000001 # Query # # ROLLBACK
/* the output must denote there is the query */;
drop trigger trg_del_t2;
......@@ -950,7 +950,7 @@ master-bin.000001 # User var # # @`b`=_latin1 0x3135 COLLATE latin1_swedish_ci
master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=#
master-bin.000001 # Intvar # # INSERT_ID=10
master-bin.000001 # User var # # @`b`=_latin1 0x3135 COLLATE latin1_swedish_ci
master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, @b) SET `b`=((@b) + `bug27417`(2)) ;file_id=#
master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE `t4` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`a`, @b) SET `b`= @b + bug27417(2) ;file_id=#
master-bin.000001 # Query # # ROLLBACK
drop trigger trg_del_t2;
drop table t1,t2,t3,t4,t5;
......
......@@ -78,4 +78,31 @@ LOAD DATA LOCAL INFILE 'MYSQLD_DATADIR/bug43746.sql' INTO TABLE t1;
DROP TABLE t1;
SET SESSION sql_mode=@old_mode;
[slave]
Bug #60580/#11902767:
"statement improperly replicated crashes slave sql thread"
[master]
CREATE TABLE t1(f1 INT, f2 INT);
CREATE TABLE t2(f1 INT, f2 TIMESTAMP);
INSERT INTO t2 VALUES(1, '2011-03-22 21:01:28');
INSERT INTO t2 VALUES(2, '2011-03-21 21:01:28');
INSERT INTO t2 VALUES(3, '2011-03-20 21:01:28');
CREATE TABLE t3 AS SELECT * FROM t2;
CREATE VIEW v1 AS SELECT * FROM t2
WHERE f1 IN (SELECT f1 FROM t3 WHERE (t3.f2 IS NULL));
SELECT 1 INTO OUTFILE 'MYSQLD_DATADIR/bug60580.csv' FROM DUAL;
LOAD DATA LOCAL INFILE 'MYSQLD_DATADIR/bug60580.csv' INTO TABLE t1 (@f1) SET f2 = (SELECT f1 FROM v1 WHERE f1=@f1);
SELECT * FROM t1;
f1 f2
NULL NULL
[slave]
SELECT * FROM t1;
f1 f2
NULL NULL
[master]
DROP VIEW v1;
DROP TABLE t1, t2, t3;
[slave]
include/rpl_end.inc
# End of 5.1 tests
......@@ -163,5 +163,56 @@ SET SESSION sql_mode=@old_mode;
--echo [slave]
sync_slave_with_master;
connection master;
--echo
--echo Bug #60580/#11902767:
--echo "statement improperly replicated crashes slave sql thread"
--echo
--echo [master]
connection master;
let $MYSQLD_DATADIR= `select @@datadir`;
CREATE TABLE t1(f1 INT, f2 INT);
CREATE TABLE t2(f1 INT, f2 TIMESTAMP);
INSERT INTO t2 VALUES(1, '2011-03-22 21:01:28');
INSERT INTO t2 VALUES(2, '2011-03-21 21:01:28');
INSERT INTO t2 VALUES(3, '2011-03-20 21:01:28');
CREATE TABLE t3 AS SELECT * FROM t2;
CREATE VIEW v1 AS SELECT * FROM t2
WHERE f1 IN (SELECT f1 FROM t3 WHERE (t3.f2 IS NULL));
--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
eval SELECT 1 INTO OUTFILE '$MYSQLD_DATADIR/bug60580.csv' FROM DUAL;
--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
eval LOAD DATA LOCAL INFILE '$MYSQLD_DATADIR/bug60580.csv' INTO TABLE t1 (@f1) SET f2 = (SELECT f1 FROM v1 WHERE f1=@f1);
SELECT * FROM t1;
sleep 1;
--echo [slave]
sync_slave_with_master;
SELECT * FROM t1;
--remove_file $MYSQLD_DATADIR/bug60580.csv
--echo [master]
connection master;
DROP VIEW v1;
DROP TABLE t1, t2, t3;
--echo [slave]
sync_slave_with_master;
connection master;
--source include/rpl_end.inc
--echo # End of 5.1 tests
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2000, 2011 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -743,8 +743,7 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
pfields.append("`");
pfields.append(item->name);
pfields.append("`");
pfields.append("=");
val->print(&pfields, QT_ORDINARY);
pfields.append(val->name);
}
}
......
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2000, 2011 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -11587,7 +11587,23 @@ field_or_var:
opt_load_data_set_spec:
/* empty */ {}
| SET insert_update_list {}
| SET load_data_set_list {}
;
load_data_set_list:
load_data_set_list ',' load_data_set_elem
| load_data_set_elem
;
load_data_set_elem:
simple_ident_nospvar equal remember_name expr_or_default remember_end
{
LEX *lex= Lex;
if (lex->update_list.push_back($1) ||
lex->value_list.push_back($4))
MYSQL_YYABORT;
$4->set_name($3, (uint) ($5 - $3), YYTHD->charset());
}
;
/* Common definitions */
......
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