mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Fixed LP bug #794038.
INSERT/UPDATE/DELETE statement that used a temptable view v1 could lead to a crash if v1 was defined as a select from a mergeable view v2 that selected rows from a temptable view v3. When INSERT/UPDATE/DELETE uses a view that is not updatable then field translation for the view should be created before the prepare phase.
This commit is contained in:
@@ -4168,3 +4168,19 @@ a a b
|
|||||||
2 2 30
|
2 2 30
|
||||||
DROP VIEW v2;
|
DROP VIEW v2;
|
||||||
DROP TABLE t1,t2;
|
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;
|
||||||
|
@@ -4114,3 +4114,23 @@ SELECT * FROM t1,v2
|
|||||||
|
|
||||||
DROP VIEW v2;
|
DROP VIEW v2;
|
||||||
DROP TABLE t1,t2;
|
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;
|
||||||
|
@@ -467,6 +467,12 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||||||
|
|
||||||
if (derived->merged_for_insert)
|
if (derived->merged_for_insert)
|
||||||
return FALSE;
|
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())
|
if (!derived->is_multitable())
|
||||||
{
|
{
|
||||||
TABLE_LIST *tl=((TABLE_LIST*)dt_select->table_list.first);
|
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;
|
bool res= FALSE;
|
||||||
|
|
||||||
// Skip already prepared views/DT
|
// Skip already prepared views/DT
|
||||||
if (!unit || unit->prepared)
|
if (!unit || unit->prepared || derived->merged_for_insert)
|
||||||
DBUG_RETURN(FALSE);
|
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;
|
Query_arena *arena= thd->stmt_arena, backup;
|
||||||
if (arena->is_conventional())
|
if (arena->is_conventional())
|
||||||
arena= 0; // For easier test
|
arena= 0; // For easier test
|
||||||
|
@@ -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 */
|
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
|
||||||
if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
|
if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
|
||||||
|
Reference in New Issue
Block a user