From 0b54001b21e56ceb04d80eeeadbb62a04b04d34f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Apr 2007 23:21:37 +0500 Subject: [PATCH] Bug#5507: TRUNCATE does not work with views. Support of views wasn't implemented for the TRUNCATE statement. Now TRUNCATE on views has the same semantics as DELETE FROM view: mysql_truncate() checks whether the table is a view and falls back to delete if so. In order to initialize properly the LEX::updatable for a view st_lex::can_use_merged() now allows usage of merged views for the TRUNCATE statement. mysql-test/r/truncate.result: Added a test case for the Bug#5507: TRUNCATE does not work with views. mysql-test/t/truncate.test: Added a test case for the Bug#5507: TRUNCATE does not work with views. sql/sql_lex.cc: Bug#5507: TRUNCATE does not work with views. can_use_merged() was denying of usage of merged views for a TRUNCATE statement. This results in improper initialization of view LEX::updatable. Fixed. sql/sql_delete.cc: Bug#5507: TRUNCATE does not work with views. 1.mysql_truncate() was lacking of check whether the table is view. Added. 2.mysql_truncate() calls mysql_delete(), but mysql_delete() always reports errors as "DELETE" errors. Fixed. mysql-test/t/view.test: Updated test case for Bug#14540: OPTIMIZE, ANALYZE, REPAIR applied to not a view. mysql-test/r/view.result: Updated test case for Bug#14540: OPTIMIZE, ANALYZE, REPAIR applied to not a view. --- mysql-test/r/truncate.result | 27 +++++++++++++++++++++++++++ mysql-test/r/view.result | 10 ++++++++++ mysql-test/t/truncate.test | 32 ++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 2 ++ sql/sql_delete.cc | 9 ++++++--- sql/sql_lex.cc | 1 + 6 files changed, 78 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/truncate.result b/mysql-test/r/truncate.result index 74a6cb72cc6..6c21db0e2b8 100644 --- a/mysql-test/r/truncate.result +++ b/mysql-test/r/truncate.result @@ -53,3 +53,30 @@ a 3 4 drop table t1; +create table t1 (s1 int); +insert into t1 (s1) values (1), (2), (3), (4), (5); +create view v1 as select * from t1; +truncate table v1; +select count(*) from t1; +count(*) +0 +insert into t1 (s1) values (1), (2), (3), (4), (5); +create view v2 as select * from t1 where s1 > 3; +truncate table v2; +select * from t1; +s1 +1 +2 +3 +select * from v2; +s1 +delete from t1; +create table t2 (s1 int, s2 int); +create view v3 as select a.s1, b.s2 from t1 a join t2 b on a.s1 = b.s1 where a.s1 > 3; +truncate table v3; +ERROR HY000: Can not delete from join view 'test.v3' +create view v4 as select * from t1 limit 1,1; +truncate table v4; +ERROR HY000: The target table v4 of the TRUNCATE is not updatable +drop view v1, v2, v3, v4; +drop table t1, t2; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index dc87f97b322..71d743f37b9 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2395,6 +2395,16 @@ Table Op Msg_type Msg_text test.v1 optimize error 'test.v1' is not BASE TABLE Warnings: Error 1347 'test.v1' is not BASE TABLE +ANALYZE TABLE v1; +Table Op Msg_type Msg_text +test.v1 analyze error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE +REPAIR TABLE v1; +Table Op Msg_type Msg_text +test.v1 repair error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE DROP VIEW v1; create definer = current_user() sql security invoker view v1 as select 1; show create view v1; diff --git a/mysql-test/t/truncate.test b/mysql-test/t/truncate.test index f806bd8ec17..c52260124cb 100644 --- a/mysql-test/t/truncate.test +++ b/mysql-test/t/truncate.test @@ -52,3 +52,35 @@ SELECT * from t1; drop table t1; # End of 4.1 tests + +# Test for Bug#5507 "TRUNCATE should work with views" + +create table t1 (s1 int); + +insert into t1 (s1) values (1), (2), (3), (4), (5); +create view v1 as select * from t1; +truncate table v1; +select count(*) from t1; + +insert into t1 (s1) values (1), (2), (3), (4), (5); +create view v2 as select * from t1 where s1 > 3; +truncate table v2; +select * from t1; +select * from v2; +delete from t1; + +# The following should fail +create table t2 (s1 int, s2 int); +create view v3 as select a.s1, b.s2 from t1 a join t2 b on a.s1 = b.s1 where a.s1 > 3; +--error 1395 +truncate table v3; + +# The following should fail +create view v4 as select * from t1 limit 1,1; +--error 1288 +truncate table v4; + +drop view v1, v2, v3, v4; +drop table t1, t2; + +# End of 5.0 tests diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 1b229298896..920fcee3b24 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2228,6 +2228,8 @@ REPAIR TABLE v1; DROP TABLE t1; OPTIMIZE TABLE v1; +ANALYZE TABLE v1; +REPAIR TABLE v1; DROP VIEW v1; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 19f3135c594..6956e5cfe91 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -369,6 +369,8 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) { Item *fake_conds= 0; SELECT_LEX *select_lex= &thd->lex->select_lex; + const char *operation = thd->lex->sql_command == SQLCOM_TRUNCATE ? + "TRUNCATE" : "DELETE"; DBUG_ENTER("mysql_prepare_delete"); List all_fields; @@ -383,14 +385,14 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) DBUG_RETURN(TRUE); if (!table_list->updatable || check_key_in_view(thd, table_list)) { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE"); + my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, operation); DBUG_RETURN(TRUE); } { TABLE_LIST *duplicate; if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0))) { - update_non_unique_table_error(table_list, "DELETE", duplicate); + update_non_unique_table_error(table_list, operation, duplicate); DBUG_RETURN(TRUE); } } @@ -895,7 +897,8 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) if (!dont_send_ok) { db_type table_type; - mysql_frm_type(thd, path, &table_type); + if (mysql_frm_type(thd, path, &table_type) == FRMTYPE_VIEW) + goto trunc_by_del; if (table_type == DB_TYPE_UNKNOWN) { my_error(ER_NO_SUCH_TABLE, MYF(0), diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 3be844b6761..4be0aca3ea7 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1834,6 +1834,7 @@ bool st_lex::can_use_merged() case SQLCOM_UPDATE_MULTI: case SQLCOM_DELETE: case SQLCOM_DELETE_MULTI: + case SQLCOM_TRUNCATE: case SQLCOM_INSERT: case SQLCOM_INSERT_SELECT: case SQLCOM_REPLACE: