Loading mysql-test/r/view.result +53 −0 Original line number Diff line number Diff line Loading @@ -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; mysql-test/t/view.test +38 −0 Original line number Diff line number Diff line Loading @@ -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; sql/sql_lex.cc +39 −0 Original line number Diff line number Diff line Loading @@ -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 Loading sql/sql_lex.h +8 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -627,7 +626,13 @@ class st_select_lex: public st_select_lex_node 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); Loading Loading @@ -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 Loading sql/sql_table.cc +26 −10 Original line number Diff line number Diff line Loading @@ -2103,6 +2103,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, } /* RETURN VALUES FALSE Message sent to net (admin operation went ok) Loading @@ -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<Item> field_list; Item *item; Protocol *protocol= thd->protocol; LEX *lex= thd->lex; int result_code; DBUG_ENTER("mysql_admin_table"); Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -2401,13 +2424,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, } 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; } Loading Loading
mysql-test/r/view.result +53 −0 Original line number Diff line number Diff line Loading @@ -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;
mysql-test/t/view.test +38 −0 Original line number Diff line number Diff line Loading @@ -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;
sql/sql_lex.cc +39 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
sql/sql_lex.h +8 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -627,7 +626,13 @@ class st_select_lex: public st_select_lex_node 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); Loading Loading @@ -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 Loading
sql/sql_table.cc +26 −10 Original line number Diff line number Diff line Loading @@ -2103,6 +2103,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, } /* RETURN VALUES FALSE Message sent to net (admin operation went ok) Loading @@ -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<Item> field_list; Item *item; Protocol *protocol= thd->protocol; LEX *lex= thd->lex; int result_code; DBUG_ENTER("mysql_admin_table"); Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -2401,13 +2424,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, } 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; } Loading