Commit 0b54001b authored by unknown's avatar unknown
Browse files

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.
parent 2eaf8ac8
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -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;
+10 −0
Original line number Diff line number Diff line
@@ -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;
+32 −0
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -2228,6 +2228,8 @@ REPAIR TABLE v1;

DROP TABLE t1;
OPTIMIZE TABLE v1;
ANALYZE TABLE v1;
REPAIR TABLE v1;

DROP VIEW v1;

+6 −3
Original line number Diff line number Diff line
@@ -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<Item> 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),
Loading