diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 4eaf1eb4793..9f720019303 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -4168,3 +4168,19 @@ a a b 2 2 30 DROP VIEW v2; DROP TABLE t1,t2; +# +# Bug#794038: crash with INSERT/UPDATE/DELETE +# over a non-updatable view +# +CREATE TABLE t1 (a int); +CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT * FROM t1; +CREATE ALGORITHM = MERGE VIEW v2 AS SELECT * FROM v1; +CREATE ALGORITHM = TEMPTABLE VIEW v3 AS SELECT * FROM v2; +INSERT INTO v3 VALUES (1); +ERROR HY000: The target table v3 of the INSERT is not insertable-into +UPDATE v3 SET a=0; +ERROR HY000: The target table v3 of the UPDATE is not updatable +DELETE FROM v3; +ERROR HY000: The target table v3 of the DELETE is not updatable +DROP VIEW v1,v2,v3; +DROP TABLE t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index b2032d5d6ba..626cc506e78 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -4114,3 +4114,23 @@ SELECT * FROM t1,v2 DROP VIEW v2; DROP TABLE t1,t2; + +--echo # +--echo # Bug#794038: crash with INSERT/UPDATE/DELETE +--echo # over a non-updatable view +--echo # + +CREATE TABLE t1 (a int); +CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT * FROM t1; +CREATE ALGORITHM = MERGE VIEW v2 AS SELECT * FROM v1; +CREATE ALGORITHM = TEMPTABLE VIEW v3 AS SELECT * FROM v2; + +-- error ER_NON_INSERTABLE_TABLE +INSERT INTO v3 VALUES (1); +-- error ER_NON_UPDATABLE_TABLE +UPDATE v3 SET a=0; +-- error ER_NON_UPDATABLE_TABLE +DELETE FROM v3; + +DROP VIEW v1,v2,v3; +DROP TABLE t1; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index ca56f0fa0a6..9bfa49c5f2d 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -467,6 +467,12 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) if (derived->merged_for_insert) return FALSE; + /* It's a target view for an INSERT, create field translation only. */ + if (!derived->updatable || derived->is_materialized_derived()) + { + bool res= derived->create_field_translation(thd); + return res; + } if (!derived->is_multitable()) { TABLE_LIST *tl=((TABLE_LIST*)dt_select->table_list.first); @@ -603,16 +609,9 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) bool res= FALSE; // Skip already prepared views/DT - if (!unit || unit->prepared) + if (!unit || unit->prepared || derived->merged_for_insert) DBUG_RETURN(FALSE); - /* It's a target view for an INSERT, create field translation only. */ - if (derived->merged_for_insert) - { - res= derived->create_field_translation(thd); - DBUG_RETURN(res); - } - Query_arena *arena= thd->stmt_arena, backup; if (arena->is_conventional()) arena= 0; // For easier test diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f891d307e9b..165a898910d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2697,9 +2697,6 @@ mysql_execute_command(THD *thd) } } } - if (mysql_handle_single_derived(thd->lex, create_table, - DT_MERGE_FOR_INSERT)) - DBUG_RETURN(1); /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */ if (create_info.options & HA_LEX_CREATE_TMP_TABLE)