From 7fde72db9e1574ca1fa1075de279df4d331093d5 Mon Sep 17 00:00:00 2001 From: Rex Johnston Date: Sat, 6 Dec 2025 07:03:22 +1200 Subject: [PATCH] MDEV-38258 No error thrown when CTE columns updated in updates set clause CTE's are read only i.e It cannot have their columns updated in updates set clause. Attempting to do so , should throw error ERROR 1288 (HY000): The target table cte of the UPDATE is not updatable with cte as (select * from t1 where c < 5) update cte set cte.a =(select a from cte); Here, conversion from a single table to a multi table update bypasses the normal check by setting the TABLE_LIST object representing cte to be merge derived. This is incorrect, so we prohibit this conversion in TABLE_LIST::init_derived. --- mysql-test/main/cte_update_delete.result | 18 ++++++++++++++++++ mysql-test/main/cte_update_delete.test | 22 ++++++++++++++++++++++ sql/table.cc | 3 +++ 3 files changed, 43 insertions(+) diff --git a/mysql-test/main/cte_update_delete.result b/mysql-test/main/cte_update_delete.result index fac0c7e2a68a7..c2cdfc61a0e07 100644 --- a/mysql-test/main/cte_update_delete.result +++ b/mysql-test/main/cte_update_delete.result @@ -1325,5 +1325,23 @@ insert into t3 values (1, 1, 'iron'),(2,2,'wood'),(0,NULL, 'gold'), (3, 3, 'silver'), (4, 4, 'lead'), (5, 5, 'tin'), (6, 6, 'platinum'), (7, 7, 'aluminium'); drop prepare s; +# +# MDEV-38258 No error thrown when CTE columns updated in updates set clause +# +with cte as (select * from t1 where c < 1) +update cte set cte.a =(select a from cte); +ERROR HY000: The target table cte of the UPDATE is not updatable +with cte as (select a from t1) +update cte set cte.a=(select a from cte limit 1); +ERROR HY000: The target table cte of the UPDATE is not updatable +with cte as (select a from t1), +cte2 as (select a from t3) +update t2, cte set cte.a=(select a from cte limit 1); +ERROR HY000: The target table cte of the UPDATE is not updatable +with cte as (select a from t1), +cte2 as (select a from t3) +update cte +set cte.a=(select a from cte where cte.a in (select a from cte2) limit 1); +ERROR HY000: The target table cte of the UPDATE is not updatable drop table t1, t2, t3, t4, t5; # End of 12.2 tests diff --git a/mysql-test/main/cte_update_delete.test b/mysql-test/main/cte_update_delete.test index 2fef3b6722a1e..93666dd24baeb 100644 --- a/mysql-test/main/cte_update_delete.test +++ b/mysql-test/main/cte_update_delete.test @@ -511,6 +511,28 @@ eval $empty_t3; eval $fill_t3; drop prepare s; +--echo # +--echo # MDEV-38258 No error thrown when CTE columns updated in updates set clause +--echo # + +--error ER_NON_UPDATABLE_TABLE +with cte as (select * from t1 where c < 1) + update cte set cte.a =(select a from cte); + +--error ER_NON_UPDATABLE_TABLE +with cte as (select a from t1) + update cte set cte.a=(select a from cte limit 1); + +--error ER_NON_UPDATABLE_TABLE +with cte as (select a from t1), + cte2 as (select a from t3) + update t2, cte set cte.a=(select a from cte limit 1); + +--error ER_NON_UPDATABLE_TABLE +with cte as (select a from t1), + cte2 as (select a from t3) + update cte + set cte.a=(select a from cte where cte.a in (select a from cte2) limit 1); drop table t1, t2, t3, t4, t5; diff --git a/sql/table.cc b/sql/table.cc index 8f9c6398f07af..e8d4588e3de75 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -10163,6 +10163,9 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view) belong_to_view ? belong_to_view->updating : !unit->outer_select()->outer_select(); + if (with && updating) + set_materialized_derived(); + /* In the case where a table merge operation moves a derived table from one select to another, table hints may be adjusted already.