From 4891d514b6e4920bee5efb965edba7d4f1596a36 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sun, 6 May 2018 16:10:49 +0400 Subject: [PATCH] MDEV-16095 Oracle-style placeholder inside GROUP BY..WITH ROLLUP breaks replication --- .../compat/oracle/r/binlog_stm_ps.result | 31 +++++++++++++++++++ .../suite/compat/oracle/t/binlog_stm_ps.test | 20 ++++++++++++ sql/sql_lex.cc | 13 +++++--- sql/sql_lex.h | 4 +-- sql/sql_yacc_ora.yy | 8 ++--- 5 files changed, 65 insertions(+), 11 deletions(-) diff --git a/mysql-test/suite/compat/oracle/r/binlog_stm_ps.result b/mysql-test/suite/compat/oracle/r/binlog_stm_ps.result index c60e3493b3f..01fe3be3a04 100644 --- a/mysql-test/suite/compat/oracle/r/binlog_stm_ps.result +++ b/mysql-test/suite/compat/oracle/r/binlog_stm_ps.result @@ -65,3 +65,34 @@ master-bin.000001 # Gtid # # BEGIN GTID #-#-# master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10,20) master-bin.000001 # Query # # COMMIT DROP TABLE t1; +# +# MDEV-16095 Oracle-style placeholder inside GROUP BY..WITH ROLLUP breaks replication +# +FLUSH LOGS; +CREATE TABLE t1 (d DATE); +INSERT INTO t1 VALUES ('1985-05-13'),('1989-12-24'); +CREATE TABLE t2 (d DATE, c BIGINT); +BEGIN +EXECUTE IMMEDIATE 'INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, :param' USING 1; +EXECUTE IMMEDIATE 'INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, :param WITH ROLLUP' USING 1; +END; +$$ +DROP TABLE t1,t2; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Binlog_checkpoint # # master-bin.000002 +master-bin.000002 # Gtid # # GTID #-#-# +master-bin.000002 # Query # # use `test`; CREATE TABLE t1 (d DATE) +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES ('1985-05-13'),('1989-12-24') +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # GTID #-#-# +master-bin.000002 # Query # # use `test`; CREATE TABLE t2 (d DATE, c BIGINT) +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, 1 +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # BEGIN GTID #-#-# +master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, 1 WITH ROLLUP +master-bin.000002 # Query # # COMMIT +master-bin.000002 # Gtid # # GTID #-#-# +master-bin.000002 # Query # # use `test`; DROP TABLE "t1","t2" /* generated by server */ diff --git a/mysql-test/suite/compat/oracle/t/binlog_stm_ps.test b/mysql-test/suite/compat/oracle/t/binlog_stm_ps.test index 996ef574413..f305f611bd2 100644 --- a/mysql-test/suite/compat/oracle/t/binlog_stm_ps.test +++ b/mysql-test/suite/compat/oracle/t/binlog_stm_ps.test @@ -35,3 +35,23 @@ SELECT * FROM t1; --let $binlog_file = LAST source include/show_binlog_events.inc; DROP TABLE t1; + + +--echo # +--echo # MDEV-16095 Oracle-style placeholder inside GROUP BY..WITH ROLLUP breaks replication +--echo # + +FLUSH LOGS; +CREATE TABLE t1 (d DATE); +INSERT INTO t1 VALUES ('1985-05-13'),('1989-12-24'); +CREATE TABLE t2 (d DATE, c BIGINT); +DELIMITER $$; +BEGIN + EXECUTE IMMEDIATE 'INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, :param' USING 1; + EXECUTE IMMEDIATE 'INSERT INTO t2 SELECT d, COUNT(*) FROM t1 GROUP BY d, :param WITH ROLLUP' USING 1; +END; +$$ +DELIMITER ;$$ +DROP TABLE t1,t2; +--let $binlog_file = LAST +source include/show_binlog_events.inc; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 2c8c4f4bec0..82943751ea0 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -6600,16 +6600,19 @@ Item *LEX::create_and_link_Item_trigger_field(THD *thd, Item *LEX::make_item_colon_ident_ident(THD *thd, - const Lex_ident_sys_st *a, - const Lex_ident_sys_st *b) + const Lex_ident_cli_st *ca, + const Lex_ident_cli_st *cb) { - if (!is_trigger_new_or_old_reference(a)) + Lex_ident_sys a(thd, ca), b(thd, cb); + if (a.is_null() || b.is_null()) + return NULL; // OEM + if (!is_trigger_new_or_old_reference(&a)) { thd->parse_error(); return NULL; } - bool new_row= (a->str[0] == 'N' || a->str[0] == 'n'); - return create_and_link_Item_trigger_field(thd, b, new_row); + bool new_row= (a.str[0] == 'N' || a.str[0] == 'n'); + return create_and_link_Item_trigger_field(thd, &b, new_row); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3fc6798e3ff..40bd8986773 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3577,8 +3577,8 @@ public: bool new_row); // For syntax with colon, e.g. :NEW.a or :OLD.a Item *make_item_colon_ident_ident(THD *thd, - const Lex_ident_sys_st *a, - const Lex_ident_sys_st *b); + const Lex_ident_cli_st *a, + const Lex_ident_cli_st *b); void sp_block_init(THD *thd, const LEX_CSTRING *label); void sp_block_init(THD *thd) { diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index e84bf4fe5a2..2d2bd79fe1f 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -14415,10 +14415,10 @@ param_marker: YYLIP->get_tok_start() + 1))) MYSQL_YYABORT; } - | colon_with_pos ident + | colon_with_pos ident_cli { if (!($$= Lex->add_placeholder(thd, &null_clex_str, - $1, YYLIP->get_tok_end()))) + $1, $2.end()))) MYSQL_YYABORT; } | colon_with_pos NUM @@ -14727,7 +14727,7 @@ simple_ident: if (!($$= Lex->create_item_ident(thd, &$1, &$3, &$5))) MYSQL_YYABORT; } - | colon_with_pos ident '.' ident + | colon_with_pos ident_cli '.' ident_cli { if (!($$= Lex->make_item_colon_ident_ident(thd, &$2, &$4))) MYSQL_YYABORT; @@ -14745,7 +14745,7 @@ simple_ident_nospvar: if (!($$= Lex->create_item_ident_nospvar(thd, &$1, &$3))) MYSQL_YYABORT; } - | colon_with_pos ident '.' ident + | colon_with_pos ident_cli '.' ident_cli { if (!($$= Lex->make_item_colon_ident_ident(thd, &$2, &$4))) MYSQL_YYABORT;