List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:February 21 2008 5:58pm
Subject:bk commit into 5.0 tree (davi:1.2583) BUG#32890
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of davi.  When davi does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-02-21 14:58:29-03:00, davi@stripped +6 -0
  Bug#32890 Crash after repeated create and drop of tables and views
  
  The problem is that CREATE VIEW statements inside prepared statements
  weren't being expanded during the prepare phase, which leads to objects
  not being allocated in the appropriate memory arenas.
  
  The solution is to perform the validation of CREATE VIEW statements
  during the prepare phase of a prepared statement. The validation
  during the prepare phase assures that transformations of the parsed
  tree will use the permanent arena of the prepared statement.

  mysql-test/r/ps.result@stripped, 2008-02-21 14:58:27-03:00, davi@stripped +152 -0
    Add test case result for Bug#32890

  mysql-test/t/ps.test@stripped, 2008-02-21 14:58:27-03:00, davi@stripped +123 -0
    Add test case for Bug#32890

  sql/item.h@stripped, 2008-02-21 14:58:27-03:00, davi@stripped +23 -20
    Restore original field name if name is auto generated.

  sql/sql_prepare.cc@stripped, 2008-02-21 14:58:27-03:00, davi@stripped +40 -0
    Validate and prepare a CREATE VIEW statement for execution.

  sql/sql_view.cc@stripped, 2008-02-21 14:58:27-03:00, davi@stripped +126 -87
    Move privileges check to it's own function.

  sql/sql_view.h@stripped, 2008-02-21 14:58:27-03:00, davi@stripped +3 -0
    Export function which check privileges of a CREATE VIEW statement.

diff -Nrup a/mysql-test/r/ps.result b/mysql-test/r/ps.result
--- a/mysql-test/r/ps.result	2008-02-08 08:55:53 -02:00
+++ b/mysql-test/r/ps.result	2008-02-21 14:58:27 -03:00
@@ -1709,4 +1709,156 @@ 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
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1`
+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
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d` from `t1`
+select * from v1;
+c	d
+drop view v1;
+execute stmt;
+deallocate prepare stmt;
+show create view v1;
+View	Create View
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d` from `t1`
+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
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`b` + 1) AS `c` from `t1`
+select * from v1;
+c
+drop view v1;
+execute stmt;
+deallocate prepare stmt;
+show create view v1;
+View	Create View
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`b` + 1) AS `c` from `t1`
+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
+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`
+select * from v1;
+c	d	e	f
+drop view v1;
+execute stmt;
+deallocate prepare stmt;
+show create view v1;
+View	Create View
+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`
+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
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`
+select * from v1;
+1
+1
+execute stmt;
+show create view v1;
+View	Create View
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`
+deallocate prepare stmt;
+show create view v1;
+View	Create View
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`
+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
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`,1 AS `My_exp_1`
+select * from v1;
+1	My_exp_1
+1	1
+drop view v1;
+execute stmt;
+deallocate prepare stmt;
+show create view v1;
+View	Create View
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`,1 AS `My_exp_1`
+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
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `x` from `t1` where (`t1`.`a` > 1)
+select * from v1;
+x
+drop view v1;
+execute stmt;
+deallocate prepare stmt;
+show create view v1;
+View	Create View
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `x` from `t1` where (`t1`.`a` > 1)
+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
+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`
+select * from v1;
+a	b
+drop view v1;
+execute stmt;
+deallocate prepare stmt;
+show create view v1;
+View	Create View
+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`
+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.
diff -Nrup a/mysql-test/t/ps.test b/mysql-test/t/ps.test
--- a/mysql-test/t/ps.test	2008-02-08 08:55:53 -02:00
+++ b/mysql-test/t/ps.test	2008-02-21 14:58:27 -03:00
@@ -1824,4 +1824,127 @@ 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 -Nrup a/sql/item.h b/sql/item.h
--- a/sql/item.h	2007-12-13 08:49:11 -02:00
+++ b/sql/item.h	2008-02-21 14:58:27 -03:00
@@ -879,6 +879,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:
@@ -1161,7 +1178,7 @@ bool agg_item_charsets(DTCollation &c, c
                        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 */
@@ -1352,7 +1369,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)
@@ -1374,8 +1391,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; }
@@ -1567,8 +1582,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() {}
   void print(String *str);
   Item_num *neg() { value= -value; return this; }
   uint decimal_precision() const
@@ -1621,8 +1634,6 @@ public:
   {
     return new Item_decimal(name, &decimal_value, decimals, max_length);
   }
-  // to prevent drop fixed flag (no need parent cleanup call)
-  void cleanup() {}
   void print(String *str);
   Item_num *neg()
   {
@@ -1673,8 +1684,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; }
@@ -1696,7 +1705,7 @@ public:
 };
 
 
-class Item_string :public Item
+class Item_string :public Item_basic_constant
 {
 public:
   Item_string(const char *str,uint length,
@@ -1780,8 +1789,6 @@ public:
     max_length= str_value.numchars() * collation.collation->mbmaxlen;
   }
   void print(String *str);
-  // to prevent drop fixed flag (no need parent cleanup call)
-  void cleanup() {}
 };
 
 
@@ -1839,10 +1846,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()
@@ -1858,8 +1865,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() {}
   void print(String *str);
   bool eq(const Item *item, bool binary_cmp) const;
   virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
@@ -2449,7 +2454,7 @@ private:
 };
 
 
-class Item_cache: public Item
+class Item_cache: public Item_basic_constant
 {
 protected:
   Item *example;
@@ -2486,8 +2491,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() {}
   void print(String *str);
   bool eq_def(Field *field) 
   { 
diff -Nrup a/sql/sql_prepare.cc b/sql/sql_prepare.cc
--- a/sql/sql_prepare.cc	2007-11-19 14:59:43 -02:00
+++ b/sql/sql_prepare.cc	2008-02-21 14:58:27 -03:00
@@ -1512,6 +1512,45 @@ static bool mysql_test_create_table(Prep
 }
 
 
+/**
+  @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;
+  SELECT_LEX *select_lex= &lex->select_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.
 
@@ -1730,6 +1769,7 @@ static bool check_prepared_statement(Pre
       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 -Nrup a/sql/sql_view.cc b/sql/sql_view.cc
--- a/sql/sql_view.cc	2008-02-21 06:17:32 -03:00
+++ b/sql/sql_view.cc	2008-02-21 14:58:27 -03:00
@@ -227,104 +227,31 @@ fill_defined_view_parts (THD *thd, TABLE
   return FALSE;
 }
 
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
 /**
-  @brief 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 && !lex->derived_tables);
-
-  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;
+  bool res= TRUE;
+  DBUG_ENTER("create_view_precheck");
 
-    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_L
        (check_access(thd, DROP_ACL, view->db, &view->grant.privilege,
                      0, 0, is_schema_db(view->db)) ||
         grant_option && 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_L
         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_L
         if (check_access(thd, SELECT_ACL, tbl->db,
                          &tbl->grant.privilege, 0, 0, test(tbl->schema_table)) ||
             grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0))
-        {
-          res= TRUE;
           goto err;
-        }
       }
     }
   }
@@ -426,7 +347,125 @@ bool mysql_create_view(THD *thd, TABLE_L
       }
     }
   }
+
+  res= FALSE;
+
+err:
+  DBUG_RETURN(res || thd->net.report_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 && !lex->derived_tables);
+
+  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))
   {
diff -Nrup a/sql/sql_view.h b/sql/sql_view.h
--- a/sql/sql_view.h	2006-12-23 17:04:28 -02:00
+++ b/sql/sql_view.h	2008-02-21 14:58:27 -03:00
@@ -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);
 
Thread
bk commit into 5.0 tree (davi:1.2583) BUG#32890Davi Arnaut21 Feb
  • Re: bk commit into 5.0 tree (davi:1.2583) BUG#32890Konstantin Osipov21 Feb