From 8d810e9426573cdcbcc60c7577ffd4f3f29ce391 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 20 Sep 2024 14:58:23 +0200 Subject: [PATCH] MDEV-29537 Creation of view with UNION and SELECT ... FOR UPDATE in definition is failed with error lock_type is writen in the last SELECT of the unit even if it parsed last, so it should be printed last from the last select of the unit. --- mysql-test/main/view.result | 31 +++++++++++++++++++++++++++++++ mysql-test/main/view.test | 32 ++++++++++++++++++++++++++++++++ sql/sql_lex.cc | 18 ++++++++++++++++++ sql/sql_lex.h | 2 ++ sql/sql_select.cc | 17 +++++++++++++---- 5 files changed, 96 insertions(+), 4 deletions(-) diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result index bc319d3c5b7..74f64388b4a 100644 --- a/mysql-test/main/view.result +++ b/mysql-test/main/view.result @@ -6970,3 +6970,34 @@ DROP VIEW v1; DROP VIEW v2; DROP TABLE t; # End of 10.4 tests +# +# MDEV-29537: Creation of view with UNION and SELECT ... FOR UPDATE +# in definition is failed with error +# +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT 1 FROM t1 +UNION +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 +FOR UPDATE; +SELECT * FROM v1; +1 +1 +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` from `t1` union select 1 AS `1` from DUAL where 1 group by 1 having 1 order by 1 for update latin1 latin1_swedish_ci +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT 1 FROM t1 +UNION +(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 +FOR UPDATE); +SELECT * FROM v1; +1 +1 +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` from `t1` union (select 1 AS `1` from DUAL where 1 group by 1 having 1 for update) latin1 latin1_swedish_ci +DROP VIEW v1; +DROP TABLE t1; +# End of 10.5 tests diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test index 6730e7f7111..229fedddb5c 100644 --- a/mysql-test/main/view.test +++ b/mysql-test/main/view.test @@ -6726,3 +6726,35 @@ DROP VIEW v2; DROP TABLE t; --echo # End of 10.4 tests + +--echo # +--echo # MDEV-29537: Creation of view with UNION and SELECT ... FOR UPDATE +--echo # in definition is failed with error +--echo # + +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT 1 FROM t1 +UNION +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + FOR UPDATE; + +SELECT * FROM v1; +SHOW CREATE VIEW v1; + +DROP VIEW v1; +DROP TABLE t1; + + +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT 1 FROM t1 + UNION + (SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + FOR UPDATE); +SELECT * FROM v1; + +SHOW CREATE VIEW v1; + +DROP VIEW v1; +DROP TABLE t1; + +--echo # End of 10.5 tests diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index fc39bd858f8..385131642b0 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3788,6 +3788,8 @@ void st_select_lex_unit::print(String *str, enum_query_type query_type) } else if (saved_fake_select_lex) saved_fake_select_lex->print_limit(thd, str, query_type); + + print_lock_from_the_last_select(str); } @@ -10612,6 +10614,22 @@ bool SELECT_LEX_UNIT::set_lock_to_the_last_select(Lex_select_lock l) return FALSE; } + +void SELECT_LEX_UNIT::print_lock_from_the_last_select(String *str) +{ + SELECT_LEX *sel= first_select(); + while (sel->next_select()) + sel= sel->next_select(); + if(sel->braces) + return; // braces processed in st_select_lex::print + + // lock type + sel->print_lock_type(str); + + return; +} + + /** Generate unique name for generated derived table for this SELECT */ diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e0cb336de5a..1dbd839ac53 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1042,6 +1042,7 @@ public: bool check_parameters(SELECT_LEX *main_select); bool set_lock_to_the_last_select(Lex_select_lock l); + void print_lock_from_the_last_select(String *str); bool can_be_merged(); @@ -1465,6 +1466,7 @@ public: bool setup_ref_array(THD *thd, uint order_group_num); uint get_cardinality_of_ref_ptrs_slice(uint order_group_num_arg); void print(THD *thd, String *str, enum_query_type query_type); + void print_lock_type(String *str); void print_item_list(THD *thd, String *str, enum_query_type query_type); void print_set_clause(THD *thd, String *str, enum_query_type query_type); void print_on_duplicate_key_clause(THD *thd, String *str, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b995beb53e3..e0eb7bec3e4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -28787,6 +28787,16 @@ void st_select_lex::print_on_duplicate_key_clause(THD *thd, String *str, } } + +void st_select_lex::print_lock_type(String *str) +{ + if (lock_type == TL_READ_WITH_SHARED_LOCKS) + str->append(" lock in share mode"); + else if (lock_type == TL_WRITE) + str->append(" for update"); +} + + void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) { DBUG_ASSERT(thd); @@ -29059,10 +29069,9 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) print_limit(thd, str, query_type); // lock type - if (lock_type == TL_READ_WITH_SHARED_LOCKS) - str->append(" lock in share mode"); - else if (lock_type == TL_WRITE) - str->append(" for update"); + if (braces) /* no braces processed in + SELECT_LEX_UNIT::print_lock_from_the_last_select */ + print_lock_type(str); if ((sel_type == INSERT_CMD || sel_type == REPLACE_CMD) && thd->lex->update_list.elements)