diff options
-rw-r--r-- | mysql-test/r/ps.result | 152 | ||||
-rw-r--r-- | mysql-test/t/ps.test | 123 | ||||
-rw-r--r-- | sql/item.h | 43 | ||||
-rw-r--r-- | sql/mysqld.cc | 14 | ||||
-rw-r--r-- | sql/sql_parse.cc | 1 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 39 | ||||
-rw-r--r-- | sql/sql_view.cc | 213 | ||||
-rw-r--r-- | sql/sql_view.h | 3 |
8 files changed, 479 insertions, 109 deletions
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 75d3f79f4b0..f2c1d5da3b5 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1733,6 +1733,158 @@ a b 9999999999999999 14632475938453979136 deallocate prepare stmt; drop table t1; +drop view if exists v1; +drop table if exists t1; +create table t1 (a int, b int); +insert into t1 values (1,1), (2,2), (3,3); +insert into t1 values (3,1), (1,2), (2,3); +prepare stmt from "create view v1 as select * from t1"; +execute stmt; +drop table t1; +create table t1 (a int, b int); +drop view v1; +execute stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` latin1 latin1_swedish_ci +drop view v1; +prepare stmt from "create view v1 (c,d) as select a,b from t1"; +execute stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d` from `t1` latin1 latin1_swedish_ci +select * from v1; +c d +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d` from `t1` latin1 latin1_swedish_ci +select * from v1; +c d +drop view v1; +prepare stmt from "create view v1 (c) as select b+1 from t1"; +execute stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`b` + 1) AS `c` from `t1` latin1 latin1_swedish_ci +select * from v1; +c +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`b` + 1) AS `c` from `t1` latin1 latin1_swedish_ci +select * from v1; +c +drop view v1; +prepare stmt from "create view v1 (c,d,e,f) as select a,b,a in (select a+2 from t1), a = all (select a from t1) from t1"; +execute stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d`,`t1`.`a` in (select (`t1`.`a` + 2) AS `a+2` from `t1`) AS `e`,`t1`.`a` = all (select `t1`.`a` AS `a` from `t1`) AS `f` from `t1` latin1 latin1_swedish_ci +select * from v1; +c d e f +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d`,`t1`.`a` in (select (`t1`.`a` + 2) AS `a+2` from `t1`) AS `e`,`t1`.`a` = all (select `t1`.`a` AS `a` from `t1`) AS `f` from `t1` latin1 latin1_swedish_ci +select * from v1; +c d e f +drop view v1; +prepare stmt from "create or replace view v1 as select 1"; +execute stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` latin1 latin1_swedish_ci +select * from v1; +1 +1 +execute stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` latin1 latin1_swedish_ci +deallocate prepare stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` latin1 latin1_swedish_ci +select * from v1; +1 +1 +drop view v1; +prepare stmt from "create view v1 as select 1, 1"; +execute stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`,1 AS `My_exp_1` latin1 latin1_swedish_ci +select * from v1; +1 My_exp_1 +1 1 +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`,1 AS `My_exp_1` latin1 latin1_swedish_ci +select * from v1; +1 My_exp_1 +1 1 +drop view v1; +prepare stmt from "create view v1 (x) as select a from t1 where a > 1"; +execute stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `x` from `t1` where (`t1`.`a` > 1) latin1 latin1_swedish_ci +select * from v1; +x +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `x` from `t1` where (`t1`.`a` > 1) latin1 latin1_swedish_ci +select * from v1; +x +drop view v1; +prepare stmt from "create view v1 as select * from `t1` `b`"; +execute stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `b`.`a` AS `a`,`b`.`b` AS `b` from `t1` `b` latin1 latin1_swedish_ci +select * from v1; +a b +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `b`.`a` AS `a`,`b`.`b` AS `b` from `t1` `b` latin1 latin1_swedish_ci +select * from v1; +a b +drop view v1; +prepare stmt from "create view v1 (a,b,c) as select * from t1"; +execute stmt; +ERROR HY000: View's SELECT and view's field list have different column counts +execute stmt; +ERROR HY000: View's SELECT and view's field list have different column counts +deallocate prepare stmt; +drop table t1; +create temporary table t1 (a int, b int); +prepare stmt from "create view v1 as select * from t1"; +execute stmt; +ERROR HY000: View's SELECT refers to a temporary table 't1' +execute stmt; +ERROR HY000: View's SELECT refers to a temporary table 't1' +deallocate prepare stmt; +drop table t1; +prepare stmt from "create view v1 as select * from t1"; +ERROR 42S02: Table 'test.t1' doesn't exist +prepare stmt from "create view v1 as select * from `t1` `b`"; +ERROR 42S02: Table 'test.t1' doesn't exist End of 5.0 tests. create procedure proc_1() reset query cache; call proc_1(); diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index a34d41a6dfb..bc784412392 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1838,6 +1838,129 @@ select * from t1 where a = @a and b = @b; deallocate prepare stmt; drop table t1; +# +# Bug#32890 Crash after repeated create and drop of tables and views +# + +--disable_warnings +drop view if exists v1; +drop table if exists t1; +--enable_warnings + +create table t1 (a int, b int); +insert into t1 values (1,1), (2,2), (3,3); +insert into t1 values (3,1), (1,2), (2,3); + +prepare stmt from "create view v1 as select * from t1"; +execute stmt; +drop table t1; +create table t1 (a int, b int); +drop view v1; +execute stmt; +show create view v1; +drop view v1; + +prepare stmt from "create view v1 (c,d) as select a,b from t1"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 (c) as select b+1 from t1"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 (c,d,e,f) as select a,b,a in (select a+2 from t1), a = all (select a from t1) from t1"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create or replace view v1 as select 1"; +execute stmt; +show create view v1; +select * from v1; +execute stmt; +show create view v1; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 as select 1, 1"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 (x) as select a from t1 where a > 1"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 as select * from `t1` `b`"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 (a,b,c) as select * from t1"; +--error ER_VIEW_WRONG_LIST +execute stmt; +--error ER_VIEW_WRONG_LIST +execute stmt; +deallocate prepare stmt; + +drop table t1; +create temporary table t1 (a int, b int); + +prepare stmt from "create view v1 as select * from t1"; +--error ER_VIEW_SELECT_TMPTABLE +execute stmt; +--error ER_VIEW_SELECT_TMPTABLE +execute stmt; +deallocate prepare stmt; + +drop table t1; + +--error ER_NO_SUCH_TABLE +prepare stmt from "create view v1 as select * from t1"; +--error ER_NO_SUCH_TABLE +prepare stmt from "create view v1 as select * from `t1` `b`"; + --echo End of 5.0 tests. # diff --git a/sql/item.h b/sql/item.h index e1c380a2a55..64894866504 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1013,6 +1013,23 @@ public: class sp_head; +class Item_basic_constant :public Item +{ +public: + /* to prevent drop fixed flag (no need parent cleanup call) */ + void cleanup() + { + /* + Restore the original field name as it might not have been allocated + in the statement memory. If the name is auto generated, it must be + done again between subsequent executions of a prepared statement. + */ + if (orig_name) + name= orig_name; + } +}; + + /***************************************************************************** The class is a base class for representation of stored routine variables in the Item-hierarchy. There are the following kinds of SP-vars: @@ -1295,7 +1312,7 @@ bool agg_item_charsets(DTCollation &c, const char *name, Item **items, uint nitems, uint flags, int item_sep); -class Item_num: public Item +class Item_num: public Item_basic_constant { public: Item_num() {} /* Remove gcc warning */ @@ -1487,7 +1504,7 @@ public: friend class st_select_lex_unit; }; -class Item_null :public Item +class Item_null :public Item_basic_constant { public: Item_null(char *name_par=0) @@ -1509,8 +1526,6 @@ public: bool send(Protocol *protocol, String *str); enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_NULL; } - /* to prevent drop fixed flag (no need parent cleanup call) */ - void cleanup() {} bool basic_const_item() const { return 1; } Item *clone_item() { return new Item_null(name); } bool is_null() { return 1; } @@ -1709,8 +1724,6 @@ public: int save_in_field(Field *field, bool no_conversions); bool basic_const_item() const { return 1; } Item *clone_item() { return new Item_int(name,value,max_length); } - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} virtual void print(String *str, enum_query_type query_type); Item_num *neg() { value= -value; return this; } uint decimal_precision() const @@ -1765,8 +1778,6 @@ public: { return new Item_decimal(name, &decimal_value, decimals, max_length); } - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} virtual void print(String *str, enum_query_type query_type); Item_num *neg() { @@ -1821,8 +1832,6 @@ public: String *val_str(String*); my_decimal *val_decimal(my_decimal *); bool basic_const_item() const { return 1; } - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} Item *clone_item() { return new Item_float(name, value, decimals, max_length); } Item_num *neg() { value= -value; return this; } @@ -1849,7 +1858,7 @@ public: }; -class Item_string :public Item +class Item_string :public Item_basic_constant { public: Item_string(const char *str,uint length, @@ -1936,8 +1945,6 @@ public: max_length= str_value.numchars() * collation.collation->mbmaxlen; } virtual void print(String *str, enum_query_type query_type); - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} bool check_partition_func_processor(uchar *int_arg) {return FALSE;} /** @@ -2068,10 +2075,10 @@ public: }; -class Item_hex_string: public Item +class Item_hex_string: public Item_basic_constant { public: - Item_hex_string(): Item() {} + Item_hex_string() {} Item_hex_string(const char *str,uint str_length); enum Type type() const { return VARBIN_ITEM; } double val_real() @@ -2087,8 +2094,6 @@ public: enum Item_result result_type () const { return STRING_RESULT; } enum Item_result cast_to_int_type() const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} virtual void print(String *str, enum_query_type query_type); bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); @@ -2680,7 +2685,7 @@ private: }; -class Item_cache: public Item +class Item_cache: public Item_basic_constant { protected: Item *example; @@ -2727,8 +2732,6 @@ public: static Item_cache* get_cache(const Item *item); table_map used_tables() const { return used_table_map; } virtual void keep_array() {} - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} virtual void print(String *str, enum_query_type query_type); bool eq_def(Field *field) { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9c4e6f9e2a2..a982a8f4809 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2573,8 +2573,18 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) (TABLE_LIST*) 0, ¬_used); // Flush logs } /* reenable logs after the options were reloaded */ - logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_TABLE:LOG_NONE, - opt_log ? LOG_TABLE:LOG_NONE); + if (log_output_options & LOG_NONE) + { + logger.set_handlers(LOG_FILE, + opt_slow_log ? LOG_TABLE : LOG_NONE, + opt_log ? LOG_TABLE : LOG_NONE); + } + else + { + logger.set_handlers(LOG_FILE, + opt_slow_log ? log_output_options : LOG_NONE, + opt_log ? log_output_options : LOG_NONE); + } break; #ifdef USE_ONE_SIGNAL_HAND case THR_SERVER_ALARM: diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e1ee2bd595b..1111fdac200 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6448,6 +6448,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, { thd->thread_stack= (char*) &tmp_thd; thd->store_globals(); + lex_start(thd); } if (thd) { diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 02d8ed00c32..c06c68df8d3 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1524,6 +1524,44 @@ static bool mysql_test_create_table(Prepared_statement *stmt) /** + @brief Validate and prepare for execution CREATE VIEW statement + + @param stmt prepared statement + + @note This function handles create view commands. + + @retval FALSE Operation was a success. + @retval TRUE An error occured. +*/ + +static bool mysql_test_create_view(Prepared_statement *stmt) +{ + DBUG_ENTER("mysql_test_create_view"); + THD *thd= stmt->thd; + LEX *lex= stmt->lex; + bool res= TRUE; + /* Skip first table, which is the view we are creating */ + bool link_to_local; + TABLE_LIST *view= lex->unlink_first_table(&link_to_local); + TABLE_LIST *tables= lex->query_tables; + + if (create_view_precheck(thd, tables, view, lex->create_view_mode)) + goto err; + + if (open_normal_and_derived_tables(thd, tables, 0)) + goto err; + + lex->view_prepare_mode= 1; + res= select_like_stmt_test(stmt, 0, 0); + +err: + /* put view back for PS rexecuting */ + lex->link_first_table_back(view, link_to_local); + DBUG_RETURN(res); +} + + +/* Validate and prepare for execution a multi update statement. @param stmt prepared statement @@ -1735,6 +1773,7 @@ static bool check_prepared_statement(Prepared_statement *stmt, my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0)); goto error; } + res= mysql_test_create_view(stmt); break; case SQLCOM_DO: res= mysql_test_do_fields(stmt, tables, lex->insert_list); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 68cc8e1839a..bbcb1bcb143 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -227,104 +227,31 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) return FALSE; } +#ifndef NO_EMBEDDED_ACCESS_CHECKS /** - Creating/altering VIEW procedure + @brief CREATE VIEW privileges pre-check. @param thd thread handler + @param tables tables used in the view @param views views to create @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE - @note This function handles both create and alter view commands. - @retval FALSE Operation was a success. @retval TRUE An error occured. */ -bool mysql_create_view(THD *thd, TABLE_LIST *views, - enum_view_create_mode mode) +bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, + enum_view_create_mode mode) { LEX *lex= thd->lex; - bool link_to_local; /* first table in list is target VIEW name => cut off it */ - TABLE_LIST *view= lex->unlink_first_table(&link_to_local); - TABLE_LIST *tables= lex->query_tables; TABLE_LIST *tbl; SELECT_LEX *select_lex= &lex->select_lex; -#ifndef NO_EMBEDDED_ACCESS_CHECKS SELECT_LEX *sl; -#endif - SELECT_LEX_UNIT *unit= &lex->unit; - bool res= FALSE; - DBUG_ENTER("mysql_create_view"); - - /* This is ensured in the parser. */ - DBUG_ASSERT(!lex->proc_list.first && !lex->result && - !lex->param_list.elements); - - if (mode != VIEW_CREATE_NEW) - { - if (mode == VIEW_ALTER && - fill_defined_view_parts(thd, view)) - { - res= TRUE; - goto err; - } - sp_cache_invalidate(); - } - - if (!lex->definer) - { - /* - DEFINER-clause is missing; we have to create default definer in - persistent arena to be PS/SP friendly. - If this is an ALTER VIEW then the current user should be set as - the definer. - */ - Query_arena original_arena; - Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); + bool res= TRUE; + DBUG_ENTER("create_view_precheck"); - if (!(lex->definer= create_default_definer(thd))) - res= TRUE; - - if (ps_arena) - thd->restore_active_arena(ps_arena, &original_arena); - - if (res) - goto err; - } - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* - check definer of view: - - same as current user - - current user has SUPER_ACL - */ - if (lex->definer && - (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 || - my_strcasecmp(system_charset_info, - lex->definer->host.str, - thd->security_ctx->priv_host) != 0)) - { - if (!(thd->security_ctx->master_access & SUPER_ACL)) - { - my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); - res= TRUE; - goto err; - } - else - { - if (!is_acl_user(lex->definer->host.str, - lex->definer->user.str)) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_NO_SUCH_USER, - ER(ER_NO_SUCH_USER), - lex->definer->user.str, - lex->definer->host.str); - } - } - } /* Privilege check for view creation: - user has CREATE VIEW privilege on view table @@ -346,10 +273,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, (check_access(thd, DROP_ACL, view->db, &view->grant.privilege, 0, 0, is_schema_db(view->db)) || check_grant(thd, DROP_ACL, view, 0, 1, 0)))) - { - res= TRUE; goto err; - } + for (sl= select_lex; sl; sl= sl->next_select()) { for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local) @@ -363,7 +288,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "ANY", thd->security_ctx->priv_user, thd->security_ctx->priv_host, tbl->table_name); - res= TRUE; goto err; } /* @@ -399,10 +323,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, if (check_access(thd, SELECT_ACL, tbl->db, &tbl->grant.privilege, 0, 0, test(tbl->schema_table)) || check_grant(thd, SELECT_ACL, tbl, 0, 1, 0)) - { - res= TRUE; goto err; - } } } } @@ -426,8 +347,126 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, } } } + + res= FALSE; + +err: + DBUG_RETURN(res || thd->is_error()); +} + +#else + +bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, + enum_view_create_mode mode) +{ + return FALSE; +} + +#endif + + +/** + @brief Creating/altering VIEW procedure + + @param thd thread handler + @param views views to create + @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE + + @note This function handles both create and alter view commands. + + @retval FALSE Operation was a success. + @retval TRUE An error occured. +*/ + +bool mysql_create_view(THD *thd, TABLE_LIST *views, + enum_view_create_mode mode) +{ + LEX *lex= thd->lex; + bool link_to_local; + /* first table in list is target VIEW name => cut off it */ + TABLE_LIST *view= lex->unlink_first_table(&link_to_local); + TABLE_LIST *tables= lex->query_tables; + TABLE_LIST *tbl; + SELECT_LEX *select_lex= &lex->select_lex; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + SELECT_LEX *sl; +#endif + SELECT_LEX_UNIT *unit= &lex->unit; + bool res= FALSE; + DBUG_ENTER("mysql_create_view"); + + /* This is ensured in the parser. */ + DBUG_ASSERT(!lex->proc_list.first && !lex->result && + !lex->param_list.elements); + + if (mode != VIEW_CREATE_NEW) + { + if (mode == VIEW_ALTER && + fill_defined_view_parts(thd, view)) + { + res= TRUE; + goto err; + } + sp_cache_invalidate(); + } + + if (!lex->definer) + { + /* + DEFINER-clause is missing; we have to create default definer in + persistent arena to be PS/SP friendly. + If this is an ALTER VIEW then the current user should be set as + the definer. + */ + Query_arena original_arena; + Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); + + if (!(lex->definer= create_default_definer(thd))) + res= TRUE; + + if (ps_arena) + thd->restore_active_arena(ps_arena, &original_arena); + + if (res) + goto err; + } + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* + check definer of view: + - same as current user + - current user has SUPER_ACL + */ + if (lex->definer && + (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 || + my_strcasecmp(system_charset_info, + lex->definer->host.str, + thd->security_ctx->priv_host) != 0)) + { + if (!(thd->security_ctx->master_access & SUPER_ACL)) + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); + res= TRUE; + goto err; + } + else + { + if (!is_acl_user(lex->definer->host.str, + lex->definer->user.str)) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_NO_SUCH_USER, + ER(ER_NO_SUCH_USER), + lex->definer->user.str, + lex->definer->host.str); + } + } + } #endif + if ((res= create_view_precheck(thd, tables, view, mode))) + goto err; + if (open_and_lock_tables(thd, tables)) { res= TRUE; diff --git a/sql/sql_view.h b/sql/sql_view.h index d3c83c82f44..b8138663489 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -15,6 +15,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, + enum_view_create_mode mode); + bool mysql_create_view(THD *thd, TABLE_LIST *view, enum_view_create_mode mode); |