Commit 2dd70946 authored by Sergey Glukhov's avatar Sergey Glukhov

Bug#45806 crash when replacing into a view with a join!

The crash happend because for views which are joins
we have table_list->table == 0 and 
table_list->table->'any method' call leads to crash.
The fix is to perform table_list->table->file->extra()
method for all tables belonging to view.


mysql-test/r/view.result:
  test result
mysql-test/t/view.test:
  test case
sql/sql_insert.cc:
  added prepare_for_positional_update() function
  which updates extra info about primary key for
  tables belonging to view.
parent 15b23550
...@@ -3723,6 +3723,117 @@ DROP TABLE t1; ...@@ -3723,6 +3723,117 @@ DROP TABLE t1;
# -- End of test case for Bug#40825 # -- End of test case for Bug#40825
#
# Bug #45806 crash when replacing into a view with a join!
#
CREATE TABLE t1(a INT UNIQUE);
CREATE VIEW v1 AS SELECT t1.a FROM t1, t1 AS a;
INSERT INTO t1 VALUES (1), (2);
REPLACE INTO v1(a) SELECT 1 FROM t1,t1 AS c;
SELECT * FROM v1;
a
1
2
1
2
REPLACE INTO v1(a) SELECT 3 FROM t1,t1 AS c;
SELECT * FROM v1;
a
1
2
3
1
2
3
1
2
3
DELETE FROM t1 WHERE a=3;
INSERT INTO v1(a) SELECT 1 FROM t1,t1 AS c
ON DUPLICATE KEY UPDATE `v1`.`a`= 1;
SELECT * FROM v1;
a
1
2
1
2
CREATE VIEW v2 AS SELECT t1.a FROM t1, v1 AS a;
REPLACE INTO v2(a) SELECT 1 FROM t1,t1 AS c;
SELECT * FROM v2;
a
1
2
1
2
1
2
1
2
REPLACE INTO v2(a) SELECT 3 FROM t1,t1 AS c;
SELECT * FROM v2;
a
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
INSERT INTO v2(a) SELECT 1 FROM t1,t1 AS c
ON DUPLICATE KEY UPDATE `v2`.`a`= 1;
SELECT * FROM v2;
a
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
DROP VIEW v1;
DROP VIEW v2;
DROP TABLE t1;
# -- End of test case for Bug#45806
# ----------------------------------------------------------------- # -----------------------------------------------------------------
# -- End of 5.0 tests. # -- End of 5.0 tests.
# ----------------------------------------------------------------- # -----------------------------------------------------------------
...@@ -3703,6 +3703,38 @@ DROP TABLE t1; ...@@ -3703,6 +3703,38 @@ DROP TABLE t1;
--echo # -- End of test case for Bug#40825 --echo # -- End of test case for Bug#40825
--echo --echo
--echo #
--echo # Bug #45806 crash when replacing into a view with a join!
--echo #
CREATE TABLE t1(a INT UNIQUE);
CREATE VIEW v1 AS SELECT t1.a FROM t1, t1 AS a;
INSERT INTO t1 VALUES (1), (2);
REPLACE INTO v1(a) SELECT 1 FROM t1,t1 AS c;
SELECT * FROM v1;
REPLACE INTO v1(a) SELECT 3 FROM t1,t1 AS c;
SELECT * FROM v1;
DELETE FROM t1 WHERE a=3;
INSERT INTO v1(a) SELECT 1 FROM t1,t1 AS c
ON DUPLICATE KEY UPDATE `v1`.`a`= 1;
SELECT * FROM v1;
CREATE VIEW v2 AS SELECT t1.a FROM t1, v1 AS a;
REPLACE INTO v2(a) SELECT 1 FROM t1,t1 AS c;
SELECT * FROM v2;
REPLACE INTO v2(a) SELECT 3 FROM t1,t1 AS c;
SELECT * FROM v2;
INSERT INTO v2(a) SELECT 1 FROM t1,t1 AS c
ON DUPLICATE KEY UPDATE `v2`.`a`= 1;
SELECT * FROM v2;
DROP VIEW v1;
DROP VIEW v2;
DROP TABLE t1;
--echo # -- End of test case for Bug#45806
--echo # ----------------------------------------------------------------- --echo # -----------------------------------------------------------------
--echo # -- End of 5.0 tests. --echo # -- End of 5.0 tests.
--echo # ----------------------------------------------------------------- --echo # -----------------------------------------------------------------
...@@ -1148,6 +1148,33 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, ...@@ -1148,6 +1148,33 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
} }
/*
Get extra info for tables we insert into
@param table table(TABLE object) we insert into,
might be NULL in case of view
@param table(TABLE_LIST object) or view we insert into
*/
static void prepare_for_positional_update(TABLE *table, TABLE_LIST *tables)
{
if (table)
{
if(table->reginfo.lock_type != TL_WRITE_DELAYED)
table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
return;
}
DBUG_ASSERT(tables->view);
List_iterator<TABLE_LIST> it(*tables->view_tables);
TABLE_LIST *tbl;
while ((tbl= it++))
prepare_for_positional_update(tbl->table, tbl);
return;
}
/* /*
Prepare items in INSERT statement Prepare items in INSERT statement
...@@ -1298,9 +1325,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, ...@@ -1298,9 +1325,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
Only call extra() handler method if we are not performing a DELAYED Only call extra() handler method if we are not performing a DELAYED
operation. It will instead be executed by delayed insert thread. operation. It will instead be executed by delayed insert thread.
*/ */
if ((duplic == DUP_UPDATE || duplic == DUP_REPLACE) && if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
(table->reginfo.lock_type != TL_WRITE_DELAYED)) prepare_for_positional_update(table, table_list);
table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment