From bfbd0e241b8ece9f212310116a69af20692790a0 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Tue, 5 Jul 2005 13:36:36 +0300 Subject: [PATCH 1/2] added processing of view grants to table grants (BUG#9795) --- mysql-test/r/grant.result | 113 +++++++++++++++++++++++++ mysql-test/r/system_mysql_db.result | 2 +- mysql-test/r/view_grant.result | 2 +- mysql-test/t/grant.test | 67 +++++++++++++++ mysql-test/t/view_grant.test | 2 +- scripts/mysql_create_system_tables.sh | 2 +- scripts/mysql_fix_privilege_tables.sql | 5 ++ sql/sql_acl.h | 11 ++- 8 files changed, 198 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index c8ae8303d99..d84c9317755 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1,4 +1,5 @@ drop table if exists t1; +drop database if exists mysqltest; SET NAMES binary; delete from mysql.user where user='mysqltest_1'; delete from mysql.db where user='mysqltest_1'; @@ -473,3 +474,115 @@ ERROR 42000: INSERT,CREATE command denied to user 'mysqltest_1'@'localhost' for revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; drop database mysqltest; +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT ALL PRIVILEGES ON mysqltest.dummytable TO dummy@localhost; +GRANT ALL PRIVILEGES ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT ALL PRIVILEGES ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT ALL PRIVILEGES ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE +mysqltest dummyview ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT ALL PRIVILEGES ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT ALL PRIVILEGES ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE +mysqltest dummyview ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE +SHOW FIELDS FROM mysql.tables_priv; +Field Type Null Key Default Extra +Host char(60) NO PRI +Db char(64) NO PRI +User char(16) NO PRI +Table_name char(64) NO PRI +Grantor char(77) NO MUL +Timestamp timestamp YES CURRENT_TIMESTAMP +Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') NO +Column_priv set('Select','Insert','Update','References') NO +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT CREATE VIEW ON mysqltest.dummytable TO dummy@localhost; +GRANT CREATE VIEW ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT CREATE VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT CREATE VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable CREATE VIEW +mysqltest dummyview CREATE VIEW +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT CREATE VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT CREATE VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable CREATE VIEW +mysqltest dummyview CREATE VIEW +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT SHOW VIEW ON mysqltest.dummytable TO dummy@localhost; +GRANT SHOW VIEW ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT SHOW VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT SHOW VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable SHOW VIEW +mysqltest dummyview SHOW VIEW +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT SHOW VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT SHOW VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable SHOW VIEW +mysqltest dummyview SHOW VIEW +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index 409c9db9f47..b8f96687a73 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -128,7 +128,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Table_name` char(64) collate utf8_bin NOT NULL default '', `Grantor` char(77) collate utf8_bin NOT NULL default '', `Timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, - `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') character set utf8 NOT NULL default '', + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') character set utf8 NOT NULL default '', `Column_priv` set('Select','Insert','Update','References') character set utf8 NOT NULL default '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index df8e2b04f47..b77ee59b3ff 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -284,7 +284,7 @@ create table mysqltest.v3 (b int); grant select(b) on mysqltest.v3 to mysqltest_1@localhost; drop table mysqltest.v3; create view mysqltest.v3 as select b from mysqltest.t2; -ERROR 42000: CREATE VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v3' +ERROR 42000: create view command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 'v3' create view v4 as select b+1 from mysqltest.t2; ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 't2' grant create view,update,select on test.* to mysqltest_1@localhost; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 34d9a09cba7..e4e0a8b4f1a 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -6,6 +6,7 @@ # Cleanup --disable_warnings drop table if exists t1; +drop database if exists mysqltest; --enable_warnings connect (master,localhost,root,,); @@ -403,3 +404,69 @@ connection root; revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; drop database mysqltest; + +# +# check all new table priveleges +# +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT ALL PRIVILEGES ON mysqltest.dummytable TO dummy@localhost; +GRANT ALL PRIVILEGES ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +SHOW FIELDS FROM mysql.tables_priv; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; +# check view only privileges +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT CREATE VIEW ON mysqltest.dummytable TO dummy@localhost; +GRANT CREATE VIEW ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT SHOW VIEW ON mysqltest.dummytable TO dummy@localhost; +GRANT SHOW VIEW ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index bb603b75daa..6283a1abf11 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -360,7 +360,7 @@ create table mysqltest.v3 (b int); grant select(b) on mysqltest.v3 to mysqltest_1@localhost; drop table mysqltest.v3; connection user1; --- error 1142 +-- error 1143 create view mysqltest.v3 as select b from mysqltest.t2; # Expression need select privileges diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index a8f6c02b057..bc07d857c4b 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -215,7 +215,7 @@ then c_t="$c_t Table_name char(64) binary DEFAULT '' NOT NULL," c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL," c_t="$c_t Timestamp timestamp(14)," - c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL," + c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL," c_t="$c_t Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL," c_t="$c_t PRIMARY KEY (Host,Db,User,Table_name)," c_t="$c_t KEY Grantor (Grantor)" diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index 68b31cf1519..3da2f7504a1 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -260,6 +260,11 @@ ALTER TABLE db ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT ALTER TABLE host ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; ALTER TABLE user ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; +# +# Show/Create views table privileges (v5.0) +# +ALTER TABLE tables_priv MODIFY Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL; + # # Assign create/show view privileges to people who have create provileges # diff --git a/sql/sql_acl.h b/sql/sql_acl.h index f2896889669..eba000a627a 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -106,8 +106,15 @@ (((A) & DB_CHUNK2) >> 6) | \ (((A) & DB_CHUNK3) >> 9) | \ (((A) & DB_CHUNK4) >> 2)) -#define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4)) -#define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4)) +#define TBL_CHUNK0 DB_CHUNK0 +#define TBL_CHUNK1 DB_CHUNK1 +#define TBL_CHUNK2 (CREATE_VIEW_ACL | SHOW_VIEW_ACL) +#define fix_rights_for_table(A) (((A) & TBL_CHUNK0) | \ + (((A) << 4) & TBL_CHUNK1) | \ + (((A) << 11) & TBL_CHUNK2)) +#define get_rights_for_table(A) (((A) & TBL_CHUNK0) | \ + (((A) & TBL_CHUNK1) >> 4) | \ + (((A) & TBL_CHUNK2) >> 11)) #define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8)) #define get_rights_for_column(A) (((A) & 7) | ((A) >> 8)) #define fix_rights_for_procedure(A) ((((A) << 18) & EXECUTE_ACL) | \ From cee0f3f60823ab82ce6ae8981f6deeb776884eb7 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Tue, 5 Jul 2005 13:37:02 +0300 Subject: [PATCH 2/2] fixed environment creation and cleaning up for processing view one by one during checking (BUG#11337) --- mysql-test/r/view.result | 53 ++++++++++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 38 ++++++++++++++++++++++++++++ sql/sql_lex.cc | 39 +++++++++++++++++++++++++++++ sql/sql_lex.h | 11 ++++++--- sql/sql_table.cc | 36 +++++++++++++++++++-------- 5 files changed, 164 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 68cc0c4cb57..1dc4148c334 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1831,3 +1831,56 @@ select * from v1; t 01:00 drop view v1; +CREATE TABLE t1 (col1 time); +CREATE TABLE t2 (col1 time); +CREATE VIEW v1 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v2 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +CREATE VIEW v3 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v4 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +CREATE VIEW v5 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v6 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +DROP TABLE t1; +CHECK TABLE v1, v2, v3, v4, v5, v6; +Table Op Msg_type Msg_text +test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) +test.v2 check status OK +test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) +test.v4 check status OK +test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) +test.v6 check status OK +drop view v1, v2, v3, v4, v5, v6; +drop table t2; +CREATE TABLE t1 (col1 time); +CREATE TABLE t2 (col1 time); +CREATE TABLE t3 (col1 time); +create function f1 () returns int return (select max(col1) from t1); +create function f2 () returns int return (select max(col1) from t2); +CREATE VIEW v1 AS SELECT f1() FROM t3; +CREATE VIEW v2 AS SELECT f2() FROM t3; +CREATE VIEW v3 AS SELECT f1() FROM t3; +CREATE VIEW v4 AS SELECT f2() FROM t3; +CREATE VIEW v5 AS SELECT f1() FROM t3; +CREATE VIEW v6 AS SELECT f2() FROM t3; +drop function f1; +CHECK TABLE v1, v2, v3, v4, v5, v6; +Table Op Msg_type Msg_text +test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) +test.v2 check status OK +test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) +test.v4 check status OK +test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) +test.v6 check status OK +create function f1 () returns int return (select max(col1) from t1); +DROP TABLE t1; +CHECK TABLE v1, v2, v3, v4, v5, v6; +Table Op Msg_type Msg_text +test.v1 check error Table 'test.t1' doesn't exist +test.v2 check status OK +test.v3 check error Table 'test.t1' doesn't exist +test.v4 check status OK +test.v5 check error Table 'test.t1' doesn't exist +test.v6 check status OK +drop function f1; +drop function f2; +drop view v1, v2, v3, v4, v5, v6; +drop table t2,t3; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 13a5f8cef1f..532e40ec28c 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1673,3 +1673,41 @@ create view v1(k, K) as select 1,2; create view v1 as SELECT TIME_FORMAT(SEC_TO_TIME(3600),'%H:%i') as t; select * from v1; drop view v1; + +# +# checking views after some view with error (BUG#11337) +# +CREATE TABLE t1 (col1 time); +CREATE TABLE t2 (col1 time); +CREATE VIEW v1 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v2 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +CREATE VIEW v3 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v4 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +CREATE VIEW v5 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v6 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +DROP TABLE t1; +CHECK TABLE v1, v2, v3, v4, v5, v6; +drop view v1, v2, v3, v4, v5, v6; +drop table t2; + +CREATE TABLE t1 (col1 time); +CREATE TABLE t2 (col1 time); +CREATE TABLE t3 (col1 time); +create function f1 () returns int return (select max(col1) from t1); +create function f2 () returns int return (select max(col1) from t2); +CREATE VIEW v1 AS SELECT f1() FROM t3; +CREATE VIEW v2 AS SELECT f2() FROM t3; +CREATE VIEW v3 AS SELECT f1() FROM t3; +CREATE VIEW v4 AS SELECT f2() FROM t3; +CREATE VIEW v5 AS SELECT f1() FROM t3; +CREATE VIEW v6 AS SELECT f2() FROM t3; +drop function f1; +CHECK TABLE v1, v2, v3, v4, v5, v6; +create function f1 () returns int return (select max(col1) from t1); +DROP TABLE t1; +# following will show underlying table until BUG#11555 fix +CHECK TABLE v1, v2, v3, v4, v5, v6; +drop function f1; +drop function f2; +drop view v1, v2, v3, v4, v5, v6; +drop table t2,t3; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 08f0c3badf7..1067ce0f6e2 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1916,6 +1916,45 @@ void st_lex::link_first_table_back(TABLE_LIST *first, } + +/* + cleanup lex for case when we open table by table for processing + + SYNOPSIS + st_lex::cleanup_after_one_table_open() +*/ + +void st_lex::cleanup_after_one_table_open() +{ + /* + thd->lex->derived_tables & additional units may be set if we open + a view. It is necessary to clear thd->lex->derived_tables flag + to prevent processing of derived tables during next open_and_lock_tables + if next table is a real table and cleanup & remove underlying units + NOTE: all units will be connected to thd->lex->select_lex, because we + have not UNION on most upper level. + */ + if (all_selects_list != &select_lex) + { + derived_tables= 0; + /* cleunup underlying units (units of VIEW) */ + for (SELECT_LEX_UNIT *un= select_lex.first_inner_unit(); + un; + un= un->next_unit()) + un->cleanup(); + /* reduce all selects list to default state */ + all_selects_list= &select_lex; + /* remove underlying units (units of VIEW) subtree */ + select_lex.cut_subtree(); + } + time_zone_tables_used= 0; + if (spfuns.records) + my_hash_reset(&spfuns); + if (spprocs.records) + my_hash_reset(&spprocs); +} + + /* fix some structures at the end of preparation diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a9bfb6da926..ffe3a5ba833 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -371,7 +371,6 @@ typedef class st_select_lex_node SELECT_LEX_NODE; SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group SELECT_LEXs */ -struct st_lex; class THD; class select_result; class JOIN; @@ -627,7 +626,13 @@ public: order_list.first= 0; order_list.next= (byte**) &order_list.first; } - + /* + This method created for reiniting LEX in mysql_admin_table() and can be + used only if you are going remove all SELECT_LEX & units except belonger + to LEX (LEX::unit & LEX::select, for other purposes there are + SELECT_LEX_UNIT::exclude_level & SELECT_LEX_UNIT::exclude_tree + */ + void cut_subtree() { slave= 0; } bool test_limit(); friend void lex_start(THD *thd, uchar *buf, uint length); @@ -912,7 +917,7 @@ typedef struct st_lex { return ( query_tables_own_last ? *query_tables_own_last : 0); } - + void cleanup_after_one_table_open(); } LEX; struct st_lex_local: public st_lex diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 121a89555ce..4f8c14a666e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2103,6 +2103,7 @@ end: } + /* RETURN VALUES FALSE Message sent to net (admin operation went ok) @@ -2122,10 +2123,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT *), int (view_operator_func)(THD *, TABLE_LIST*)) { - TABLE_LIST *table, *next_global_table; + TABLE_LIST *table, *save_next_global, *save_next_local; + SELECT_LEX *select= &thd->lex->select_lex; List field_list; Item *item; Protocol *protocol= thd->protocol; + LEX *lex= thd->lex; int result_code; DBUG_ENTER("mysql_admin_table"); @@ -2152,12 +2155,25 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, thd->open_options|= extra_open_options; table->lock_type= lock_type; /* open only one table from local list of command */ - next_global_table= table->next_global; + save_next_global= table->next_global; table->next_global= 0; + save_next_local= table->next_local; + table->next_local= 0; + select->table_list.first= (byte*)table; + /* + Time zone tables and SP tables can be add to lex->query_tables list, + so it have to be prepared. + TODO: Investigate if we can put extra tables into argument instead of + using lex->query_tables + */ + lex->query_tables= table; + lex->query_tables_last= &table->next_global; + lex->query_tables_own_last= 0;; thd->no_warnings_for_error= no_warnings_for_error; open_and_lock_tables(thd, table); thd->no_warnings_for_error= 0; - table->next_global= next_global_table; + table->next_global= save_next_global; + table->next_local= save_next_local; /* if view are unsupported */ if (table->view && view_operator_func == NULL) { @@ -2205,7 +2221,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, err_msg= (const char *)buf; } protocol->store(err_msg, system_charset_info); + lex->cleanup_after_one_table_open(); thd->clear_error(); + /* + View opening can be interrupted in the middle of process so some + tables can be left opening + */ + close_thread_tables(thd); if (protocol->write()) goto err; continue; @@ -2274,6 +2296,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, send_result: + lex->cleanup_after_one_table_open(); thd->clear_error(); // these errors shouldn't get client protocol->prepare_for_resend(); protocol->store(table_name, system_charset_info); @@ -2401,13 +2424,6 @@ send_result_message: } close_thread_tables(thd); table->table=0; // For query cache - /* - thd->lex->derived_tables may be set to non zero value if we open - a view. It is necessary to clear thd->lex->derived_tables flag - to prevent processing of derived tables during next open_and_lock_tables - if next table is a real table. - */ - thd->lex->derived_tables= 0; if (protocol->write()) goto err; }