MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:March 9 2006 5:41pm
Subject:bk commit into 5.1 tree (anozdrin:1.2162)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of alik. When alik 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
  1.2162 06/03/09 20:41:21 anozdrin@stripped +25 -0
  Merge mysql.com:/home/alik/Documents/AllProgs/MySQL/devel/5.0-tree
  into  mysql.com:/home/alik/Documents/AllProgs/MySQL/devel/5.1-merged

  sql/sql_yacc.yy
    1.475 06/03/09 20:41:18 anozdrin@stripped +10 -8
    Manually merged.

  sql/sp.cc
    1.104 06/03/09 20:41:18 anozdrin@stripped +2 -4
    Manually merged.

  mysql-test/lib/mtr_cases.pl
    1.18 06/03/09 20:41:18 anozdrin@stripped +6 -7
    Manually merged.

  sql/sql_view.cc
    1.85 06/03/09 20:37:53 anozdrin@stripped +0 -0
    Auto merged

  sql/sql_trigger.cc
    1.51 06/03/09 20:37:53 anozdrin@stripped +0 -0
    Auto merged

  sql/sql_show.cc
    1.318 06/03/09 20:37:53 anozdrin@stripped +0 -0
    Auto merged

  sql/sql_parse.cc
    1.527 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  sql/sql_lex.h
    1.218 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  sql/sql_lex.cc
    1.172 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  sql/sp_head.h
    1.83 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  sql/sp_head.cc
    1.211 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  sql/mysql_priv.h
    1.386 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/t/sp-security.test
    1.31 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/t/skip_grants.test
    1.10 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/t/rpl_trigger.test
    1.8 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/r/sql_mode.result
    1.37 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/r/sp.result
    1.199 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/r/sp-security.result
    1.29 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/r/rpl_trigger.result
    1.6 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/r/rpl_sp.result
    1.20 06/03/09 20:37:52 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/r/rpl_ddl.result
    1.15 06/03/09 20:37:52 anozdrin@stripped +0 -2
    Auto merged

  mysql-test/r/mysqldump.result
    1.101 06/03/09 20:37:51 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/r/information_schema.result
    1.111 06/03/09 20:37:51 anozdrin@stripped +0 -0
    Auto merged

  mysql-test/mysql-test-run.pl
    1.84 06/03/09 20:37:51 anozdrin@stripped +0 -0
    Auto merged

  client/mysqldump.c
    1.230 06/03/09 20:37:51 anozdrin@stripped +0 -0
    Auto merged

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	anozdrin
# Host:	station.home
# Root:	/home/alik/Documents/AllProgs/MySQL/devel/5.1-merged/RESYNC

--- 1.229/client/mysqldump.c	2006-02-23 18:11:41 +03:00
+++ 1.230/client/mysqldump.c	2006-03-09 20:37:51 +03:00
@@ -80,6 +80,7 @@
 			     const char *statement);
 static ulong find_set(TYPELIB *lib, const char *x, uint length,
 		      char **err_pos, uint *err_len);
+static char *alloc_query_str(ulong size);
 
 static char *field_escape(char *to,const char *from,uint length);
 static my_bool  verbose=0,tFlag=0,dFlag=0,quick= 1, extended_insert= 1,
@@ -1313,19 +1314,64 @@
                              routine_name, row[2], strlen(row[2])));
           if (strlen(row[2]))
           {
+            char *query_str= NULL;
+            char *definer_begin;
+
             if (opt_drop)
               fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;;\n",
                       routine_type[i], routine_name);
+
+            /*
+              Cover DEFINER-clause in version-specific comments.
+
+              TODO: this is definitely a BAD IDEA to parse SHOW CREATE output.
+              We should user INFORMATION_SCHEMA instead. The only problem is
+              that now INFORMATION_SCHEMA does not provide information about
+              routine parameters.
+            */
+
+            definer_begin= strstr(row[2], " DEFINER");
+            
+            if (definer_begin)
+            {
+              char *definer_end= strstr(definer_begin, " PROCEDURE");
+
+              if (!definer_end)
+                definer_end= strstr(definer_begin, " FUNCTION");
+
+              if (definer_end)
+              {
+                char *query_str_tail;
+
+                /*
+                  Allocate memory for new query string: original string
+                  from SHOW statement and version-specific comments.
+                */
+                query_str= alloc_query_str(strlen(row[2]) + 23);
+
+                query_str_tail= strnmov(query_str, row[2],
+                                        definer_begin - row[2]);
+                query_str_tail= strmov(query_str_tail, "*/ /*!50019");
+                query_str_tail= strnmov(query_str_tail, definer_begin,
+                                        definer_end - definer_begin);
+                query_str_tail= strxmov(query_str_tail, "*/ /*!50003",
+                                        definer_end, NullS);
+              }
+            }
+
             /*
               we need to change sql_mode only for the CREATE
               PROCEDURE/FUNCTION otherwise we may need to re-quote routine_name
             */;
             fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\"*/;;\n",
                     row[1] /* sql_mode */);
-            fprintf(sql_file, "/*!50003 %s */;;\n", row[2]);
+            fprintf(sql_file, "/*!50003 %s */;;\n",
+                    (query_str != NULL ? query_str : row[2]));
             fprintf(sql_file,
                     "/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/"
                     ";;\n");
+
+            my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
           }
         } /* end of routine printing */
       } /* end of list of routines */

--- 1.385/sql/mysql_priv.h	2006-03-04 11:51:55 +03:00
+++ 1.386/sql/mysql_priv.h	2006-03-09 20:37:52 +03:00
@@ -548,7 +548,8 @@
 bool create_table_precheck(THD *thd, TABLE_LIST *tables,
                            TABLE_LIST *create_table);
 
-bool get_default_definer(THD *thd, LEX_USER *definer);
+void get_default_definer(THD *thd, LEX_USER *definer);
+LEX_USER *create_default_definer(THD *thd);
 LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
 
 enum enum_mysql_completiontype {

--- 1.171/sql/sql_lex.cc	2006-02-09 13:34:36 +03:00
+++ 1.172/sql/sql_lex.cc	2006-03-09 20:37:52 +03:00
@@ -228,7 +228,7 @@
 
   SYNOPSIS
     is_keyword()
-    name      checked name
+    name      checked name (must not be empty)
     len       length of checked name
 
   RETURN VALUES
@@ -238,6 +238,7 @@
 
 bool is_keyword(const char *name, uint len)
 {
+  DBUG_ASSERT(len != 0);
   return get_hash_symbol(name,len,0)!=0;
 }
 

--- 1.217/sql/sql_lex.h	2006-02-28 20:33:25 +03:00
+++ 1.218/sql/sql_lex.h	2006-03-09 20:37:52 +03:00
@@ -957,12 +957,16 @@
   SQL_LIST trg_table_fields;
 
   /*
-    trigger_definition_begin points to the beginning of the word "TRIGGER" in
-    CREATE TRIGGER statement. This is used to add possibly omitted DEFINER
-    clause to the trigger definition statement before dumping it to the
-    binlog. 
+    stmt_definition_begin is intended to point to the next word after
+    DEFINER-clause in the following statements:
+      - CREATE TRIGGER (points to "TRIGGER");
+      - CREATE PROCEDURE (points to "PROCEDURE");
+      - CREATE FUNCTION (points to "FUNCTION" or "AGGREGATE");
+
+    This pointer is required to add possibly omitted DEFINER-clause to the
+    DDL-statement before dumping it to the binlog. 
   */
-  const char *trigger_definition_begin;
+  const char *stmt_definition_begin;
 
   /*
     If non-0 then indicates that query requires prelocking and points to

--- 1.526/sql/sql_parse.cc	2006-03-01 23:39:23 +03:00
+++ 1.527/sql/sql_parse.cc	2006-03-09 20:37:52 +03:00
@@ -4281,6 +4281,90 @@
 #endif
 
     /*
+      If the definer is not specified, this means that CREATE-statement missed
+      DEFINER-clause. DEFINER-clause can be missed in two cases:
+      
+        - The user submitted a statement w/o the clause. This is a normal
+          case, we should assign CURRENT_USER as definer.
+
+        - Our slave received an updated from the master, that does not
+          replicate definer for stored rountines. We should also assign
+          CURRENT_USER as definer here, but also we should mark this routine
+          as NON-SUID. This is essential for the sake of backward
+          compatibility.
+          
+          The problem is the slave thread is running under "special" user (@),
+          that actually does not exist. In the older versions we do not fail
+          execution of a stored routine if its definer does not exist and
+          continue the execution under the authorization of the invoker
+          (BUG#13198). And now if we try to switch to slave-current-user (@),
+          we will fail.
+
+          Actually, this leads to the inconsistent state of master and
+          slave (different definers, different SUID behaviour), but it seems,
+          this is the best we can do.
+    */
+
+    if (!lex->definer)
+    {
+      bool res= FALSE;
+      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)
+      {
+        /* Error has been already reported. */
+        delete lex->sphead;
+        lex->sphead= 0;
+        goto error;
+      }
+
+      if (thd->slave_thread)
+        lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
+    }
+
+    /*
+      If the specified definer differs from the current user, we should check
+      that the current user has SUPER privilege (in order to create a stored
+      routine under another user one must have SUPER privilege).
+    */
+    
+    else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
+        my_strcasecmp(system_charset_info,
+                      lex->definer->host.str,
+                      thd->security_ctx->priv_host))
+    {
+      if (check_global_access(thd, SUPER_ACL))
+      {
+        my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
+        delete lex->sphead;
+        lex->sphead= 0;
+        goto error;
+      }
+    }
+
+    /* Check that the specified definer exists. Emit a warning if not. */
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+    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 /* NO_EMBEDDED_ACCESS_CHECKS */
+
+    /*
       We need to copy name and db in order to use them for
       check_routine_access which is called after lex->sphead has
       been deleted.
@@ -7344,41 +7428,49 @@
 
 /*
   Set the specified definer to the default value, which is the current user in
-  the thread. Also check that the current user satisfies to the definers
-  requirements.
+  the thread.
  
   SYNOPSIS
     get_default_definer()
     thd       [in] thread handler
     definer   [out] definer
- 
-  RETURN
-    error status, that is:
-      - FALSE -- on success;
-      - TRUE -- on error (current user can not be a definer).
 */
  
-bool get_default_definer(THD *thd, LEX_USER *definer)
+void get_default_definer(THD *thd, LEX_USER *definer)
 {
-  /* Check that current user has non-empty host name. */
-
   const Security_context *sctx= thd->security_ctx;
 
-  if (sctx->priv_host[0] == 0)
-  {
-    my_error(ER_MALFORMED_DEFINER, MYF(0));
-    return TRUE;
-  }
-
-  /* Fill in. */
-
   definer->user.str= (char *) sctx->priv_user;
   definer->user.length= strlen(definer->user.str);
 
   definer->host.str= (char *) sctx->priv_host;
   definer->host.length= strlen(definer->host.str);
+}
 
-  return FALSE;
+
+/*
+  Create default definer for the specified THD.
+
+  SYNOPSIS
+    create_default_definer()
+    thd         [in] thread handler
+
+  RETURN
+    On success, return a valid pointer to the created and initialized
+    LEX_USER, which contains definer information.
+    On error, return 0.
+*/
+
+LEX_USER *create_default_definer(THD *thd)
+{
+  LEX_USER *definer;
+
+  if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+    return 0;
+
+  get_default_definer(thd, definer);
+
+  return definer;
 }
 
 
@@ -7394,7 +7486,7 @@
 
   RETURN
     On success, return a valid pointer to the created and initialized
-    LEX_STRING, which contains definer information.
+    LEX_USER, which contains definer information.
     On error, return 0.
 */
 

--- 1.317/sql/sql_show.cc	2006-03-07 14:23:15 +03:00
+++ 1.318/sql/sql_show.cc	2006-03-09 20:37:53 +03:00
@@ -831,7 +831,8 @@
 
 int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
 {
-  if (!is_keyword(name,length) &&
+  if (!length ||
+      !is_keyword(name,length) &&
       !require_quotes(name, length) &&
       !(thd->options & OPTION_QUOTE_SHOW_CREATE))
     return EOF;

--- 1.474/sql/sql_yacc.yy	2006-03-08 00:06:48 +03:00
+++ 1.475/sql/sql_yacc.yy	2006-03-09 20:41:18 +03:00
@@ -826,7 +826,7 @@
 
 %type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
 
-%type <lex_user> user grant_user get_definer
+%type <lex_user> user grant_user
 
 %type <charset>
 	opt_collate
@@ -881,8 +881,9 @@
 	sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
         load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
         definer view_replace_or_algorithm view_replace view_algorithm_opt
-        view_algorithm view_or_trigger_tail view_suid view_tail view_list_opt
-        view_list view_select view_check_option trigger_tail
+        view_algorithm view_or_trigger_or_sp view_or_trigger_or_sp_tail
+        view_suid view_tail view_list_opt view_list view_select
+        view_check_option trigger_tail sp_tail
         install uninstall partition_entry binlog_base64_event
 END_OF_INPUT
 
@@ -1252,78 +1253,6 @@
 	    lex->name=$4.str;
             lex->create_info.options=$3;
 	  }
-	| CREATE udf_func_type FUNCTION_SYM sp_name
-	  {
-	    LEX *lex=Lex;
-	    lex->spname= $4;
-	    lex->udf.type= $2;
-	  }
-	  create_function_tail
-	  {}
-	| CREATE PROCEDURE sp_name
-	  {
-	    LEX *lex= Lex;
-	    sp_head *sp;
-
-	    if (lex->sphead)
-	    {
-	      my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
-	      YYABORT;
-	    }
-	    /* Order is important here: new - reset - init */
-	    sp= new sp_head();
-	    sp->reset_thd_mem_root(YYTHD);
-	    sp->init(lex);
-
-	    sp->m_type= TYPE_ENUM_PROCEDURE;
-	    lex->sphead= sp;
-	    /*
-	     * We have to turn of CLIENT_MULTI_QUERIES while parsing a
-	     * stored procedure, otherwise yylex will chop it into pieces
-	     * at each ';'.
-	     */
-            $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
-	    YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
-	  }
-          '('
-	  {
-	    LEX *lex= Lex;
-
-	    lex->sphead->m_param_begin= lex->tok_start+1;
-	  }
-	  sp_pdparam_list
-	  ')'
-	  {
-	    LEX *lex= Lex;
-
-	    lex->sphead->m_param_end= lex->tok_start;
-	    bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
-	  }
-	  sp_c_chistics
-	  {
-	    LEX *lex= Lex;
-
-	    lex->sphead->m_chistics= &lex->sp_chistics;
-	    lex->sphead->m_body_begin= lex->tok_start;
-	  }
-	  sp_proc_stmt
-	  {
-	    LEX *lex= Lex;
-	    sp_head *sp= lex->sphead;
-
-	    if (sp->check_backpatch(YYTHD))
-	      YYABORT;
-	    sp->init_strings(YYTHD, lex, $3);
-	    lex->sql_command= SQLCOM_CREATE_PROCEDURE;
-
-	    /*
-              Restore flag if it was cleared above
-              Be careful with counting. the block where we save the value
-              is $4.
-            */
-	    YYTHD->client_capabilities |= $<ulong_num>4;
-	    sp->restore_thd_mem_root(YYTHD);
-	  }
 	| CREATE EVENT_SYM opt_if_not_exists sp_name
           /*
              BE CAREFUL when you add a new rule to update the block where
@@ -1390,7 +1319,7 @@
             Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
             Lex->create_view_suid= TRUE;
 	  }
-	  view_or_trigger
+	  view_or_trigger_or_sp
 	  {}
 	| CREATE USER clear_privileges grant_list
 	  {
@@ -10783,45 +10712,61 @@
           lex->nest_level--;
 	};
 
+/**************************************************************************
+
+ CREATE VIEW | TRIGGER | PROCEDURE statements.
+
+**************************************************************************/
+
+view_or_trigger_or_sp:
+	definer view_or_trigger_or_sp_tail
+	{}
+	| view_replace_or_algorithm definer view_tail
+	{}
+	;
+
+view_or_trigger_or_sp_tail:
+	view_tail
+	{}
+	| trigger_tail
+	{}
+	| sp_tail
+	{}
+	;
+
+/**************************************************************************
+
+ DEFINER clause support.
+
+**************************************************************************/
+
 definer:
-	get_definer
+	/* empty */
 	{
-	  THD *thd= YYTHD;
-	  
-	  if (! (thd->lex->definer= create_definer(thd, &$1->user, &$1->host)))
-	    YYABORT;
+          /*
+            We have to distinguish missing DEFINER-clause from case when
+            CURRENT_USER specified as definer explicitly in order to properly
+            handle CREATE TRIGGER statements which come to replication thread
+            from older master servers (i.e. to create non-suid trigger in this
+            case).
+           */
+          YYTHD->lex->definer= 0;
 	}
-	;
-
-get_definer:
-	opt_current_definer
+	| DEFINER_SYM EQ CURRENT_USER optional_braces
 	{
-	  THD *thd= YYTHD;
-          
-	  if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
-	    YYABORT;
-
-	  if (get_default_definer(thd, $$))
-	    YYABORT;
+          if (! (YYTHD->lex->definer= create_default_definer(YYTHD)))
+            YYABORT;
 	}
 	| DEFINER_SYM EQ ident_or_text '@' ident_or_text
 	{
-	  if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user))))
-	    YYABORT;
-
-	  $$->user= $3;
-	  $$->host= $5;
+          if (!(YYTHD->lex->definer= create_definer(YYTHD, &$3, &$5)))
+            YYABORT;
 	}
 	;
 
-opt_current_definer:
-	/* empty */
-	| DEFINER_SYM EQ CURRENT_USER optional_braces
-	;
-
 /**************************************************************************
 
- CREATE VIEW statement options.
+ CREATE VIEW statement parts.
 
 **************************************************************************/
 
@@ -10855,20 +10800,6 @@
 	{}
 	;
 
-view_or_trigger:
-	definer view_or_trigger_tail
-	{}
-	| view_replace_or_algorithm definer view_tail
-	{}
-	;
-
-view_or_trigger_tail:
-	view_tail
-	{}
-	| trigger_tail
-	{}
-	;
-
 view_suid:
 	/* empty */
 	{ Lex->create_view_suid= TRUE; }
@@ -10967,7 +10898,7 @@
 	  sp->reset_thd_mem_root(YYTHD);
 	  sp->init(lex);
 
-	  lex->trigger_definition_begin= $2;
+	  lex->stmt_definition_begin= $2;
           lex->ident.str= $7;
           lex->ident.length= $10 - $7;
 
@@ -11013,6 +10944,90 @@
 	                                         TL_OPTION_UPDATING,
                                                  TL_IGNORE))
 	    YYABORT;
+	}
+	;
+
+/**************************************************************************
+
+ CREATE FUNCTION | PROCEDURE statements parts.
+
+**************************************************************************/
+
+sp_tail:
+	udf_func_type remember_name FUNCTION_SYM sp_name
+	{
+	  LEX *lex=Lex;
+	  lex->udf.type= $1;
+	  lex->stmt_definition_begin= $2;
+	  lex->spname= $4;
+	}
+	create_function_tail
+	{}
+	| PROCEDURE remember_name sp_name
+	{
+	  LEX *lex= Lex;
+	  sp_head *sp;
+
+	  if (lex->sphead)
+	  {
+	    my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
+	    YYABORT;
+	  }
+	  
+	  lex->stmt_definition_begin= $2;
+	  
+	  /* Order is important here: new - reset - init */
+	  sp= new sp_head();
+	  sp->reset_thd_mem_root(YYTHD);
+	  sp->init(lex);
+
+	  sp->m_type= TYPE_ENUM_PROCEDURE;
+	  lex->sphead= sp;
+	  /*
+	   * We have to turn of CLIENT_MULTI_QUERIES while parsing a
+	   * stored procedure, otherwise yylex will chop it into pieces
+	   * at each ';'.
+	   */
+          $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
+	  YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
+	}
+        '('
+	{
+	  LEX *lex= Lex;
+
+	  lex->sphead->m_param_begin= lex->tok_start+1;
+	}
+	sp_pdparam_list
+	')'
+	{
+	  LEX *lex= Lex;
+
+	  lex->sphead->m_param_end= lex->tok_start;
+	  bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+	}
+	sp_c_chistics
+	{
+	  LEX *lex= Lex;
+
+	  lex->sphead->m_chistics= &lex->sp_chistics;
+	  lex->sphead->m_body_begin= lex->tok_start;
+	}
+	sp_proc_stmt
+	{
+	  LEX *lex= Lex;
+	  sp_head *sp= lex->sphead;
+
+	  if (sp->check_backpatch(YYTHD))
+	    YYABORT;
+	  sp->init_strings(YYTHD, lex, $3);
+	  lex->sql_command= SQLCOM_CREATE_PROCEDURE;
+          /*
+            Restore flag if it was cleared above
+            Be careful with counting. the block where we save the value
+            is $4.
+          */
+          YYTHD->client_capabilities |= $<ulong_num>4;
+	  sp->restore_thd_mem_root(YYTHD);
 	}
 	;
 

--- 1.9/mysql-test/t/skip_grants.test	2006-03-03 13:48:52 +03:00
+++ 1.10/mysql-test/t/skip_grants.test	2006-03-09 20:37:52 +03:00
@@ -9,14 +9,6 @@
 use test;
 
 #
-# test that we can create VIEW if privileges check switched off
-#
-create table t1 (field1 INT);
--- error ER_MALFORMED_DEFINER
-CREATE VIEW v1 AS SELECT field1 FROM t1;
-drop table t1;
-
-#
 # Test that we can create and drop procedure without warnings
 # see bug#9993
 #
@@ -33,3 +25,48 @@
 
 # BUG#17595: DROP FUNCTION IF EXISTS f1 crashes server
 drop function if exists f1;
+
+#
+# BUG#16777: Can not create trigger nor view w/o definer if --skip-grant-tables
+# specified
+#
+# Also, a test that we can create VIEW if privileges check switched off has
+# been moved here.
+#
+
+# Prepare.
+
+--disable_warnings
+
+DROP VIEW IF EXISTS v1;
+DROP VIEW IF EXISTS v2;
+
+DROP TABLE IF EXISTS t1;
+
+--enable_warnings
+
+# Test case.
+
+CREATE TABLE t1(c INT);
+
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+  FOR EACH ROW
+    SET @a = 1;
+
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+CREATE DEFINER=a@b TRIGGER ti_ai AFTER INSERT ON t1
+  FOR EACH ROW
+    SET @b = 1;
+
+CREATE DEFINER=a@b VIEW v2 AS SELECT * FROM t1;
+
+# Cleanup.
+
+DROP TRIGGER t1_bi;
+DROP TRIGGER ti_ai;
+
+DROP VIEW v1;
+DROP VIEW v2;
+
+DROP TABLE t1;

--- 1.84/sql/sql_view.cc	2006-02-08 20:08:09 +03:00
+++ 1.85/sql/sql_view.cc	2006-03-09 20:37:53 +03:00
@@ -208,6 +208,26 @@
   if (mode != VIEW_CREATE_NEW)
     sp_cache_invalidate();
 
+  if (!lex->definer)
+  {
+    /*
+      DEFINER-clause is missing; we have to create default definer in
+      persistent arena to be PS/SP friendly.
+    */
+
+    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:
@@ -817,8 +837,7 @@
     push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                         ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER),
                         table->db, table->table_name);
-    if (get_default_definer(thd, &table->definer))
-      goto err;
+    get_default_definer(thd, &table->definer);
   }
 
   /*

--- 1.50/sql/sql_trigger.cc	2006-03-07 22:00:42 +03:00
+++ 1.51/sql/sql_trigger.cc	2006-03-09 20:37:53 +03:00
@@ -270,8 +270,18 @@
         log_query.set((char *) 0, 0, system_charset_info); /* reset log_query */
 
         log_query.append(STRING_WITH_LEN("CREATE "));
-        append_definer(thd, &log_query, &definer_user, &definer_host);
-        log_query.append(thd->lex->trigger_definition_begin);
+
+        if (definer_user.str && definer_host.str)
+        {
+          /*
+            Append definer-clause if the trigger is SUID (a usual trigger in
+            new MySQL versions).
+          */
+
+          append_definer(thd, &log_query, &definer_user, &definer_host);
+        }
+
+        log_query.append(thd->lex->stmt_definition_begin);
       }
 
       /* Such a statement can always go directly to binlog, no trans cache. */
@@ -295,17 +305,30 @@
                      LEX)
       tables       - table list containing one open table for which the
                      trigger is created.
-      definer_user - [out] after a call it points to 0-terminated string,
-                     which contains user name part of the actual trigger
-                     definer. The caller is responsible to provide memory for
+      definer_user - [out] after a call it points to 0-terminated string or
+                     contains the NULL-string:
+                       - 0-terminated is returned if the trigger is SUID. The
+                         string contains user name part of the actual trigger
+                         definer.
+                       - NULL-string is returned if the trigger is non-SUID.
+                     Anyway, the caller is responsible to provide memory for
                      storing LEX_STRING object.
-      definer_host - [out] after a call it points to 0-terminated string,
-                     which contains host name part of the actual trigger
-                     definer. The caller is responsible to provide memory for
+      definer_host - [out] after a call it points to 0-terminated string or
+                     contains the NULL-string:
+                       - 0-terminated string is returned if the trigger is
+                         SUID. The string contains host name part of the
+                         actual trigger definer.
+                       - NULL-string is returned if the trigger is non-SUID.
+                     Anyway, the caller is responsible to provide memory for
                      storing LEX_STRING object.
 
   NOTE
-    Assumes that trigger name is fully qualified.
+    - Assumes that trigger name is fully qualified.
+    - NULL-string means the following LEX_STRING instance:
+      { str = 0; length = 0 }.
+    - In other words, definer_user and definer_host should contain
+      simultaneously NULL-strings (non-SUID/old trigger) or valid strings
+      (SUID/new trigger).
 
   RETURN VALUE
     False - success
@@ -342,12 +365,30 @@
     return 1;
   }
 
-  /*
-    Definer attribute of the Lex instance is always set in sql_yacc.yy when
-    trigger is created.
-  */
+  if (!lex->definer)
+  {
+    /*
+      DEFINER-clause is missing.
 
-  DBUG_ASSERT(lex->definer);
+      If we are in slave thread, this means that we received CREATE TRIGGER
+      from the master, that does not support definer in triggers. So, we
+      should mark this trigger as non-SUID. Note that this does not happen
+      when we parse triggers' definitions during opening .TRG file.
+      LEX::definer is ignored in that case.
+
+      Otherwise, we should use CURRENT_USER() as definer.
+
+      NOTE: when CREATE TRIGGER statement is allowed to be executed in PS/SP,
+      it will be required to create the definer below in persistent MEM_ROOT
+      of PS/SP.
+    */
+
+    if (!thd->slave_thread)
+    {
+      if (!(lex->definer= create_default_definer(thd)))
+        return 1;
+    }
+  }
 
   /*
     If the specified definer differs from the current user, we should check
@@ -355,10 +396,11 @@
     under another user one must have SUPER privilege).
   */
   
-  if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
-      my_strcasecmp(system_charset_info,
-                    lex->definer->host.str,
-                    thd->security_ctx->priv_host))
+  if (lex->definer &&
+      (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
+       my_strcasecmp(system_charset_info,
+                     lex->definer->host.str,
+                     thd->security_ctx->priv_host)))
   {
     if (check_global_access(thd, SUPER_ACL))
     {
@@ -450,8 +492,8 @@
   *trg_sql_mode= thd->variables.sql_mode;
 
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
-  if (!is_acl_user(lex->definer->host.str,
-                   lex->definer->user.str))
+  if (lex->definer && !is_acl_user(lex->definer->host.str,
+                                   lex->definer->user.str))
   {
     push_warning_printf(thd,
                         MYSQL_ERROR::WARN_LEVEL_NOTE,
@@ -462,12 +504,30 @@
   }
 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
 
-  *definer_user= lex->definer->user;
-  *definer_host= lex->definer->host;
+  if (lex->definer)
+  {
+    /* SUID trigger. */
+
+    *definer_user= lex->definer->user;
+    *definer_host= lex->definer->host;
+
+    trg_definer->str= trg_definer_holder;
+    trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@",
+                                 definer_host->str, NullS) - trg_definer->str;
+  }
+  else
+  {
+    /* non-SUID trigger. */
+
+    definer_user->str= 0;
+    definer_user->length= 0;
 
-  trg_definer->str= trg_definer_holder;
-  trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@",
-                               definer_host->str, NullS) - trg_definer->str;
+    definer_host->str= 0;
+    definer_host->length= 0;
+
+    trg_definer->str= (char*) "";
+    trg_definer->length= 0;
+  }
 
   if (!sql_create_definition_file(NULL, &file, &triggers_file_type,
                                   (gptr)this, triggers_file_parameters, 0))

--- 1.19/mysql-test/r/rpl_sp.result	2006-02-18 19:38:04 +03:00
+++ 1.20/mysql-test/r/rpl_sp.result	2006-03-09 20:37:52 +03:00
@@ -31,7 +31,7 @@
 set b = 8;
 insert into t1 values (b);
 insert into t1 values (unix_timestamp());
-end	@	#	#		
+end	root@localhost	#	#		
 set timestamp=1000000000;
 call foo();
 select * from t1;
@@ -118,7 +118,7 @@
 db	name	type	specific_name	language	sql_data_access	is_deterministic	security_type	param_list	returns	body	definer	created	modified	sql_mode	comment
 mysqltest1	foo4	PROCEDURE	foo4	SQL	CONTAINS_SQL	YES	DEFINER			begin
 insert into t2 values(20),(20);
-end	@	#	#		
+end	root@localhost	#	#		
 drop procedure foo4;
 select * from mysql.proc where name="foo4" and db='mysqltest1';
 db	name	type	specific_name	language	sql_data_access	is_deterministic	security_type	param_list	returns	body	definer	created	modified	sql_mode	comment
@@ -223,13 +223,13 @@
 db	name	type	specific_name	language	sql_data_access	is_deterministic	security_type	param_list	returns	body	definer	created	modified	sql_mode	comment
 mysqltest1	fn1	FUNCTION	fn1	SQL	NO_SQL	NO	DEFINER		int(11)	begin
 return unix_timestamp();
-end	@	#	#		
+end	root@localhost	#	#		
 mysqltest1	fn2	FUNCTION	fn2	SQL	NO_SQL	NO	DEFINER		int(11)	begin
 return unix_timestamp();
-end	@	#	#		
+end	zedjzlcsjhd@localhost	#	#		
 mysqltest1	fn3	FUNCTION	fn3	SQL	READS_SQL_DATA	NO	DEFINER		int(11)	begin
 return 0;
-end	@	#	#		
+end	root@localhost	#	#		
 delete from t2;
 alter table t2 add unique (a);
 drop function fn1;
@@ -274,7 +274,7 @@
 master-bin.000001	#	Query	1	#	drop database if exists mysqltest1
 master-bin.000001	#	Query	1	#	create database mysqltest1
 master-bin.000001	#	Query	1	#	use `mysqltest1`; create table t1 (a varchar(100))
-master-bin.000001	#	Query	1	#	use `mysqltest1`; create procedure foo()
+master-bin.000001	#	Query	1	#	use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo()
 begin
 declare b int;
 set b = 8;
@@ -284,19 +284,19 @@
 master-bin.000001	#	Query	1	#	use `mysqltest1`; insert into t1 values ( NAME_CONST('b',8))
 master-bin.000001	#	Query	1	#	use `mysqltest1`; insert into t1 values (unix_timestamp())
 master-bin.000001	#	Query	1	#	use `mysqltest1`; delete from t1
-master-bin.000001	#	Query	1	#	use `mysqltest1`; create procedure foo2()
+master-bin.000001	#	Query	1	#	use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo2()
 select * from mysqltest1.t1
 master-bin.000001	#	Query	1	#	use `mysqltest1`; alter procedure foo2 contains sql
 master-bin.000001	#	Query	1	#	use `mysqltest1`; drop table t1
 master-bin.000001	#	Query	1	#	use `mysqltest1`; create table t1 (a int)
 master-bin.000001	#	Query	1	#	use `mysqltest1`; create table t2 like t1
-master-bin.000001	#	Query	1	#	use `mysqltest1`; create procedure foo3()
+master-bin.000001	#	Query	1	#	use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo3()
 deterministic
 insert into t1 values (15)
 master-bin.000001	#	Query	1	#	use `mysqltest1`; grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1
 master-bin.000001	#	Query	1	#	use `mysqltest1`; grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1
 master-bin.000001	#	Query	1	#	use `mysqltest1`; grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1
-master-bin.000001	#	Query	1	#	use `mysqltest1`; create procedure foo4()
+master-bin.000001	#	Query	1	#	use `mysqltest1`; CREATE DEFINER=`zedjzlcsjhd`@`127.0.0.1` procedure foo4()
 deterministic
 begin
 insert into t2 values(3);
@@ -311,7 +311,7 @@
 master-bin.000001	#	Query	1	#	use `mysqltest1`; delete from t2
 master-bin.000001	#	Query	1	#	use `mysqltest1`; alter table t2 add unique (a)
 master-bin.000001	#	Query	1	#	use `mysqltest1`; drop procedure foo4
-master-bin.000001	#	Query	1	#	use `mysqltest1`; create procedure foo4()
+master-bin.000001	#	Query	1	#	use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo4()
 deterministic
 begin
 insert into t2 values(20),(20);
@@ -321,7 +321,7 @@
 master-bin.000001	#	Query	1	#	use `mysqltest1`; drop procedure foo
 master-bin.000001	#	Query	1	#	use `mysqltest1`; drop procedure foo2
 master-bin.000001	#	Query	1	#	use `mysqltest1`; drop procedure foo3
-master-bin.000001	#	Query	1	#	use `mysqltest1`; create function fn1(x int)
+master-bin.000001	#	Query	1	#	use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn1(x int)
 returns int
 deterministic
 begin
@@ -332,7 +332,7 @@
 master-bin.000001	#	Query	1	#	use `mysqltest1`; SELECT `fn1`(20)
 master-bin.000001	#	Query	1	#	use `mysqltest1`; insert into t2 values(fn1(21))
 master-bin.000001	#	Query	1	#	use `mysqltest1`; drop function fn1
-master-bin.000001	#	Query	1	#	use `mysqltest1`; create function fn1()
+master-bin.000001	#	Query	1	#	use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn1()
 returns int
 no sql
 begin
@@ -340,13 +340,13 @@
 end
 master-bin.000001	#	Query	1	#	use `mysqltest1`; delete from t1
 master-bin.000001	#	Query	1	#	use `mysqltest1`; insert into t1 values(fn1())
-master-bin.000001	#	Query	1	#	use `mysqltest1`; create function fn2()
+master-bin.000001	#	Query	1	#	use `mysqltest1`; CREATE DEFINER=`zedjzlcsjhd`@`127.0.0.1` function fn2()
 returns int
 no sql
 begin
 return unix_timestamp();
 end
-master-bin.000001	#	Query	1	#	use `mysqltest1`; create function fn3()
+master-bin.000001	#	Query	1	#	use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn3()
 returns int
 not deterministic
 reads sql data
@@ -356,7 +356,7 @@
 master-bin.000001	#	Query	1	#	use `mysqltest1`; delete from t2
 master-bin.000001	#	Query	1	#	use `mysqltest1`; alter table t2 add unique (a)
 master-bin.000001	#	Query	1	#	use `mysqltest1`; drop function fn1
-master-bin.000001	#	Query	1	#	use `mysqltest1`; create function fn1(x int)
+master-bin.000001	#	Query	1	#	use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function fn1(x int)
 returns int
 begin
 insert into t2 values(x),(x);

--- 1.110/mysql-test/r/information_schema.result	2006-03-06 13:35:32 +03:00
+++ 1.111/mysql-test/r/information_schema.result	2006-03-09 20:37:51 +03:00
@@ -322,7 +322,7 @@
 sub1		
 show create function sub2;
 Function	sql_mode	Create Function
-sub2		CREATE FUNCTION `sub2`(i int) RETURNS int(11)
+sub2		CREATE DEFINER=`mysqltest_1`@`localhost` FUNCTION `sub2`(i int) RETURNS int(11)
 return i+1
 show function status like "sub2";
 Db	Name	Type	Definer	Modified	Created	Security_type	Comment
@@ -330,7 +330,7 @@
 drop function sub2;
 show create procedure sel2;
 Procedure	sql_mode	Create Procedure
-sel2		CREATE PROCEDURE `sel2`()
+sel2		CREATE DEFINER=`root`@`localhost` PROCEDURE `sel2`()
 begin
 select * from t1;
 select * from t2;

--- 1.36/mysql-test/r/sql_mode.result	2006-02-22 12:09:51 +03:00
+++ 1.37/mysql-test/r/sql_mode.result	2006-03-09 20:37:52 +03:00
@@ -427,23 +427,23 @@
 create function `foo` () returns int return 5;
 show create function `foo`;
 Function	sql_mode	Create Function
-foo		CREATE FUNCTION `foo`() RETURNS int(11)
+foo		CREATE DEFINER=`root`@`localhost` FUNCTION `foo`() RETURNS int(11)
 return 5
 SET @@SQL_MODE='ANSI_QUOTES';
 show create function `foo`;
 Function	sql_mode	Create Function
-foo		CREATE FUNCTION `foo`() RETURNS int(11)
+foo		CREATE DEFINER=`root`@`localhost` FUNCTION `foo`() RETURNS int(11)
 return 5
 drop function `foo`;
 create function `foo` () returns int return 5;
 show create function `foo`;
 Function	sql_mode	Create Function
-foo	ANSI_QUOTES	CREATE FUNCTION "foo"() RETURNS int(11)
+foo	ANSI_QUOTES	CREATE DEFINER="root"@"localhost" FUNCTION "foo"() RETURNS int(11)
 return 5
 SET @@SQL_MODE='';
 show create function `foo`;
 Function	sql_mode	Create Function
-foo	ANSI_QUOTES	CREATE FUNCTION "foo"() RETURNS int(11)
+foo	ANSI_QUOTES	CREATE DEFINER="root"@"localhost" FUNCTION "foo"() RETURNS int(11)
 return 5
 drop function `foo`;
 SET @@SQL_MODE='';

--- 1.17/mysql-test/lib/mtr_cases.pl	2006-03-07 22:02:56 +03:00
+++ 1.18/mysql-test/lib/mtr_cases.pl	2006-03-09 20:41:18 +03:00
@@ -262,6 +262,12 @@
       $tinfo->{'skip'}= 1;
       return;
     }
+    if ( ! $::opt_with_ndbcluster )
+    {
+      # Ndb is not supported, skip them
+      $tinfo->{'skip'}= 1;
+      return;
+    }
   }
   else
   {

--- 1.83/mysql-test/mysql-test-run.pl	2006-03-09 10:15:02 +03:00
+++ 1.84/mysql-test/mysql-test-run.pl	2006-03-09 20:37:51 +03:00
@@ -2034,7 +2034,7 @@
     if ( $tinfo->{'master_restart'} or
          $master->[0]->{'running_master_is_special'} or
 	 # Stop if cluster is started but test cases does not need cluster
-	 ( $tinfo->{'ndb_test'} != $using_ndbcluster_master ) )
+	 ( $opt_with_ndbcluster && $tinfo->{'ndb_test'} != $using_ndbcluster_master ) )
     {
       stop_masters();
       $master->[0]->{'running_master_is_special'}= 0; # Forget why we stopped
@@ -2087,7 +2087,7 @@
 
     if ( $tinfo->{'component_id'} eq 'mysqld' and ! $opt_local_master )
     {
-      if ( $master->[0]->{'ndbcluster'} )
+      if ( $opt_with_ndbcluster and $master->[0]->{'ndbcluster'} )
       {
 	# Cluster is not started
 

--- 1.5/mysql-test/r/rpl_trigger.result	2006-02-15 16:36:22 +03:00
+++ 1.6/mysql-test/r/rpl_trigger.result	2006-03-09 20:37:52 +03:00
@@ -105,7 +105,7 @@
 SELECT routine_name, definer
 FROM information_schema.routines;
 routine_name	definer
-bug12480	@
+bug12480	root@localhost
 SELECT trigger_name, definer
 FROM information_schema.triggers;
 trigger_name	definer
@@ -858,3 +858,44 @@
 drop trigger trg11;
 drop table t21,t31;
 drop table t11;
+STOP SLAVE;
+FLUSH LOGS;
+RESET SLAVE;
+START SLAVE;
+SELECT MASTER_POS_WAIT('master-bin.000001', 513) >= 0;
+MASTER_POS_WAIT('master-bin.000001', 513) >= 0
+1
+SHOW TABLES LIKE 't_';
+Tables_in_test (t_)
+t1
+t2
+SHOW TRIGGERS;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer
+trg1	INSERT	t1	INSERT INTO t2 VALUES(CURRENT_USER())	AFTER	NULL		
+SELECT * FROM t1;
+c
+1
+SELECT * FROM t2;
+s
+@
+INSERT INTO t1 VALUES(2);
+SELECT * FROM t1;
+c
+1
+2
+SELECT * FROM t2;
+s
+@
+root@localhost
+DROP TRIGGER trg1;
+Warnings:
+Warning	1454	No definer attribute for trigger 'test'.'trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
+DROP TABLE t1;
+DROP TABLE t2;
+STOP SLAVE;
+RESET SLAVE;
+SHOW TABLES LIKE 't_';
+Tables_in_test (t_)
+SHOW TRIGGERS;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer
+RESET MASTER;

--- 1.7/mysql-test/t/rpl_trigger.test	2006-02-15 16:36:22 +03:00
+++ 1.8/mysql-test/t/rpl_trigger.test	2006-03-09 20:37:52 +03:00
@@ -170,6 +170,7 @@
 drop table t1,t2;
 drop database other;
 
+
 #
 # Test specific triggers including SELECT into var with replication
 # BUG#13227:
@@ -264,6 +265,79 @@
   dec $rnd;
 }
 
+
+#
+# BUG#16266: Definer is not fully qualified error during replication.
+#
+# The idea of this test is to emulate replication of a trigger from the old
+# master (master w/o "DEFINER in triggers" support) to the new slave and check
+# that:
+#   1. the trigger on the slave will be replicated w/o errors;
+#   2. the trigger on the slave will be non-SUID (will have no DEFINER);
+#   3. the trigger can be activated later on the slave w/o errors.
+#
+# In order to emulate this kind of replication, we make the slave playing the binlog,
+# recorded by 5.0.16 master. This binlog contains the following statements:
+#   CREATE TABLE t1(c INT);
+#   CREATE TABLE t2(s CHAR(200));
+#   CREATE TRIGGER trg1 AFTER INSERT ON t1
+#     FOR EACH ROW
+#       INSERT INTO t2 VALUES(CURRENT_USER());
+#   INSERT INTO t1 VALUES(1);
+#
+
+# 1. Check that the trigger's replication is succeeded.
+
+# Stop the slave.
+
+connection slave;
+STOP SLAVE;
+
+# Replace master's binlog.
+
+connection master;
+FLUSH LOGS;
+exec cp $MYSQL_TEST_DIR/std_data/bug16266.000001 $MYSQLTEST_VARDIR/log/master-bin.000001;
+
+# Make the slave to replay the new binlog.
+
+connection slave;
+RESET SLAVE;
+START SLAVE;
+
+SELECT MASTER_POS_WAIT('master-bin.000001', 513) >= 0;
+
+# Check that the replication succeeded.
+
+SHOW TABLES LIKE 't_';
+SHOW TRIGGERS;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+# 2. Check that the trigger is non-SUID on the slave;
+# 3. Check that the trigger can be activated on the slave.
+
+INSERT INTO t1 VALUES(2);
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+# That's all, cleanup.
+
+DROP TRIGGER trg1;
+DROP TABLE t1;
+DROP TABLE t2;
+
+STOP SLAVE;
+RESET SLAVE;
+
+# The master should be clean.
+
+connection master;
+SHOW TABLES LIKE 't_';
+SHOW TRIGGERS;
+
+RESET MASTER;
 
 
 #

--- 1.28/mysql-test/r/sp-security.result	2006-03-01 23:35:41 +03:00
+++ 1.29/mysql-test/r/sp-security.result	2006-03-09 20:37:52 +03:00
@@ -323,3 +323,99 @@
 GRANT EXECUTE ON PROCEDURE p1 TO user_bug7787@localhost;
 DROP DATABASE db_bug7787;
 use test;
+
+---> connection: root
+DROP DATABASE IF EXISTS mysqltest;
+CREATE DATABASE mysqltest;
+CREATE USER mysqltest_1@localhost;
+GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
+CREATE USER mysqltest_2@localhost;
+GRANT SUPER ON *.* TO mysqltest_2@localhost;
+GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
+
+---> connection: mysqltest_2_con
+use mysqltest;
+CREATE PROCEDURE wl2897_p1() SELECT 1;
+CREATE FUNCTION wl2897_f1() RETURNS INT RETURN 1;
+
+---> connection: mysqltest_1_con
+use mysqltest;
+CREATE DEFINER=root@localhost PROCEDURE wl2897_p2() SELECT 2;
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
+CREATE DEFINER=root@localhost FUNCTION wl2897_f2() RETURNS INT RETURN 2;
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
+
+---> connection: mysqltest_2_con
+use mysqltest;
+CREATE DEFINER='a @ b @ c'@localhost PROCEDURE wl2897_p3() SELECT 3;
+Warnings:
+Note	1449	There is no 'a @ b @ c'@'localhost' registered
+CREATE DEFINER='a @ b @ c'@localhost FUNCTION wl2897_f3() RETURNS INT RETURN 3;
+Warnings:
+Note	1449	There is no 'a @ b @ c'@'localhost' registered
+
+---> connection: con1root
+use mysqltest;
+SHOW CREATE PROCEDURE wl2897_p1;
+Procedure	sql_mode	Create Procedure
+wl2897_p1		CREATE DEFINER=`mysqltest_2`@`localhost` PROCEDURE `wl2897_p1`()
+SELECT 1
+SHOW CREATE PROCEDURE wl2897_p3;
+Procedure	sql_mode	Create Procedure
+wl2897_p3		CREATE DEFINER=`a @ b @ c`@`localhost` PROCEDURE `wl2897_p3`()
+SELECT 3
+SHOW CREATE FUNCTION wl2897_f1;
+Function	sql_mode	Create Function
+wl2897_f1		CREATE DEFINER=`mysqltest_2`@`localhost` FUNCTION `wl2897_f1`() RETURNS int(11)
+RETURN 1
+SHOW CREATE FUNCTION wl2897_f3;
+Function	sql_mode	Create Function
+wl2897_f3		CREATE DEFINER=`a @ b @ c`@`localhost` FUNCTION `wl2897_f3`() RETURNS int(11)
+RETURN 3
+DROP USER mysqltest_1@localhost;
+DROP USER mysqltest_2@localhost;
+DROP DATABASE mysqltest;
+
+---> connection: root
+DROP DATABASE IF EXISTS mysqltest;
+CREATE DATABASE mysqltest;
+CREATE USER mysqltest_1@localhost;
+GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
+CREATE USER mysqltest_2@localhost;
+GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
+
+---> connection: mysqltest_1_con
+use mysqltest;
+CREATE PROCEDURE bug13198_p1()
+SELECT 1;
+CREATE FUNCTION bug13198_f1() RETURNS INT
+RETURN 1;
+CALL bug13198_p1();
+1
+1
+SELECT bug13198_f1();
+bug13198_f1()
+1
+
+---> connection: mysqltest_2_con
+use mysqltest;
+CALL bug13198_p1();
+1
+1
+SELECT bug13198_f1();
+bug13198_f1()
+1
+
+---> connection: root
+DROP USER mysqltest_1@localhost;
+
+---> connection: mysqltest_2_con
+use mysqltest;
+CALL bug13198_p1();
+ERROR HY000: There is no 'mysqltest_1'@'localhost' registered
+SELECT bug13198_f1();
+ERROR HY000: There is no 'mysqltest_1'@'localhost' registered
+
+---> connection: root
+DROP USER mysqltest_2@localhost;
+DROP DATABASE mysqltest;

--- 1.198/mysql-test/r/sp.result	2006-03-08 00:06:47 +03:00
+++ 1.199/mysql-test/r/sp.result	2006-03-09 20:37:52 +03:00
@@ -788,7 +788,7 @@
   insert into t1 values ("chistics", 1)|
 show create procedure chistics|
 Procedure	sql_mode	Create Procedure
-chistics		CREATE PROCEDURE `chistics`()
+chistics		CREATE DEFINER=`root`@`localhost` PROCEDURE `chistics`()
     MODIFIES SQL DATA
     COMMENT 'Characteristics procedure test'
 insert into t1 values ("chistics", 1)
@@ -800,7 +800,7 @@
 alter procedure chistics sql security invoker|
 show create procedure chistics|
 Procedure	sql_mode	Create Procedure
-chistics		CREATE PROCEDURE `chistics`()
+chistics		CREATE DEFINER=`root`@`localhost` PROCEDURE `chistics`()
     MODIFIES SQL DATA
     SQL SECURITY INVOKER
     COMMENT 'Characteristics procedure test'
@@ -815,7 +815,7 @@
   return 42|
 show create function chistics|
 Function	sql_mode	Create Function
-chistics		CREATE FUNCTION `chistics`() RETURNS int(11)
+chistics		CREATE DEFINER=`root`@`localhost` FUNCTION `chistics`() RETURNS int(11)
     DETERMINISTIC
     SQL SECURITY INVOKER
     COMMENT 'Characteristics procedure test'
@@ -828,7 +828,7 @@
 comment 'Characteristics function test'|
 show create function chistics|
 Function	sql_mode	Create Function
-chistics		CREATE FUNCTION `chistics`() RETURNS int(11)
+chistics		CREATE DEFINER=`root`@`localhost` FUNCTION `chistics`() RETURNS int(11)
     NO SQL
     DETERMINISTIC
     SQL SECURITY INVOKER
@@ -1287,7 +1287,7 @@
 end|
 show create procedure opp|
 Procedure	sql_mode	Create Procedure
-opp		CREATE PROCEDURE `opp`(n bigint unsigned, out pp bool)
+opp		CREATE DEFINER=`root`@`localhost` PROCEDURE `opp`(n bigint unsigned, out pp bool)
 begin
 declare r double;
 declare b, s bigint unsigned default 0;
@@ -1386,7 +1386,7 @@
 alter procedure bar|
 show create procedure bar|
 Procedure	sql_mode	Create Procedure
-bar		CREATE PROCEDURE `bar`(x char(16), y int)
+bar		CREATE DEFINER=`root`@`localhost` PROCEDURE `bar`(x char(16), y int)
     COMMENT '3333333333'
 insert into test.t1 values (x, y)
 show procedure status like 'bar'|
@@ -1966,13 +1966,13 @@
 test	bug2267_4	FUNCTION	root@localhost	0000-00-00 00:00:00	0000-00-00 00:00:00	DEFINER	
 call bug2267_3()|
 Procedure	sql_mode	Create Procedure
-bug2267_1		CREATE PROCEDURE `bug2267_1`()
+bug2267_1		CREATE DEFINER=`root`@`localhost` PROCEDURE `bug2267_1`()
 begin
 show procedure status;
 end
 call bug2267_4()|
 Function	sql_mode	Create Function
-bug2267_4		CREATE FUNCTION `bug2267_4`() RETURNS int(11)
+bug2267_4		CREATE DEFINER=`root`@`localhost` FUNCTION `bug2267_4`() RETURNS int(11)
 return 100
 drop procedure bug2267_1|
 drop procedure bug2267_2|
@@ -2333,20 +2333,20 @@
 set @@sql_mode = ''|
 show create procedure bug2564_1|
 Procedure	sql_mode	Create Procedure
-bug2564_1		CREATE PROCEDURE `bug2564_1`()
+bug2564_1		CREATE DEFINER=`root`@`localhost` PROCEDURE `bug2564_1`()
     COMMENT 'Joe''s procedure'
 insert into `t1` values ("foo", 1)
 show create procedure bug2564_2|
 Procedure	sql_mode	Create Procedure
-bug2564_2	ANSI_QUOTES	CREATE PROCEDURE "bug2564_2"()
+bug2564_2	ANSI_QUOTES	CREATE DEFINER="root"@"localhost" PROCEDURE "bug2564_2"()
 insert into "t1" values ('foo', 1)
 show create function bug2564_3|
 Function	sql_mode	Create Function
-bug2564_3		CREATE FUNCTION `bug2564_3`(x int, y int) RETURNS int(11)
+bug2564_3		CREATE DEFINER=`root`@`localhost` FUNCTION `bug2564_3`(x int, y int) RETURNS int(11)
 return x || y
 show create function bug2564_4|
 Function	sql_mode	Create Function
-bug2564_4	REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI	CREATE FUNCTION "bug2564_4"(x int, y int) RETURNS int(11)
+bug2564_4	REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI	CREATE DEFINER="root"@"localhost" FUNCTION "bug2564_4"(x int, y int) RETURNS int(11)
 return x || y
 drop procedure bug2564_1|
 drop procedure bug2564_2|
@@ -4060,7 +4060,7 @@
 end */;;
 show create function bug14723;;
 Function	sql_mode	Create Function
-bug14723		CREATE FUNCTION `bug14723`() RETURNS bigint(20)
+bug14723		CREATE DEFINER=`root`@`localhost` FUNCTION `bug14723`() RETURNS bigint(20)
 main_loop: begin
 return 42;
 end
@@ -4073,7 +4073,7 @@
 end */;;
 show create procedure bug14723;;
 Procedure	sql_mode	Create Procedure
-bug14723		CREATE PROCEDURE `bug14723`()
+bug14723		CREATE DEFINER=`root`@`localhost` PROCEDURE `bug14723`()
 main_loop: begin
 select 42;
 end

--- 1.30/mysql-test/t/sp-security.test	2006-02-22 13:59:56 +03:00
+++ 1.31/mysql-test/t/sp-security.test	2006-03-09 20:37:52 +03:00
@@ -547,4 +547,200 @@
 DROP DATABASE db_bug7787;
 use test;
 
+
+#
+# WL#2897: Complete definer support in the stored routines.
+#
+# The following cases are tested:
+#   1. check that if DEFINER-clause is not explicitly specified, stored routines
+#     are created with CURRENT_USER privileges;
+#   2. check that if DEFINER-clause specifies non-current user, SUPER privilege
+#     is required to create a stored routine;
+#   3. check that if DEFINER-clause specifies non-existent user, a warning is
+#     emitted.
+#   4. check that SHOW CREATE PROCEDURE | FUNCTION works correctly;
+#
+# The following cases are tested in other test suites:
+#   - check that mysqldump dumps new attribute correctly;
+#   - check that slave replicates CREATE-statements with explicitly specified
+#     DEFINER correctly.
+#
+
+# Setup the environment.
+
+--echo
+--echo ---> connection: root
+--connection con1root
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest;
+--enable_warnings
+
+CREATE DATABASE mysqltest;
+
+CREATE USER mysqltest_1@localhost;
+GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
+
+CREATE USER mysqltest_2@localhost;
+GRANT SUPER ON *.* TO mysqltest_2@localhost;
+GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
+
+--connect (mysqltest_2_con,localhost,mysqltest_2,,mysqltest)
+--connect (mysqltest_1_con,localhost,mysqltest_1,,mysqltest)
+
+# test case (1).
+
+--echo
+--echo ---> connection: mysqltest_2_con
+--connection mysqltest_2_con
+
+use mysqltest;
+
+CREATE PROCEDURE wl2897_p1() SELECT 1;
+
+CREATE FUNCTION wl2897_f1() RETURNS INT RETURN 1;
+
+# test case (2).
+
+--echo
+--echo ---> connection: mysqltest_1_con
+--connection mysqltest_1_con
+
+use mysqltest;
+
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+CREATE DEFINER=root@localhost PROCEDURE wl2897_p2() SELECT 2;
+
+--error ER_SPECIFIC_ACCESS_DENIED_ERROR
+CREATE DEFINER=root@localhost FUNCTION wl2897_f2() RETURNS INT RETURN 2;
+
+# test case (3).
+
+--echo
+--echo ---> connection: mysqltest_2_con
+--connection mysqltest_2_con
+
+use mysqltest;
+
+CREATE DEFINER='a @ b @ c'@localhost PROCEDURE wl2897_p3() SELECT 3;
+
+CREATE DEFINER='a @ b @ c'@localhost FUNCTION wl2897_f3() RETURNS INT RETURN 3;
+
+# test case (4).
+
+--echo
+--echo ---> connection: con1root
+--connection con1root
+
+use mysqltest;
+
+SHOW CREATE PROCEDURE wl2897_p1;
+SHOW CREATE PROCEDURE wl2897_p3;
+
+SHOW CREATE FUNCTION wl2897_f1;
+SHOW CREATE FUNCTION wl2897_f3;
+
+# Cleanup.
+
+DROP USER mysqltest_1@localhost;
+DROP USER mysqltest_2@localhost;
+
+DROP DATABASE mysqltest;
+
+--disconnect mysqltest_1_con
+--disconnect mysqltest_2_con
+
+
+#
+# BUG#13198: SP executes if definer does not exist
+#
+
+# Prepare environment.
+
+--echo
+--echo ---> connection: root
+--connection con1root
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest;
+--enable_warnings
+
+CREATE DATABASE mysqltest;
+
+CREATE USER mysqltest_1@localhost;
+GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost;
+
+CREATE USER mysqltest_2@localhost;
+GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost;
+
+--connect (mysqltest_1_con,localhost,mysqltest_1,,mysqltest)
+--connect (mysqltest_2_con,localhost,mysqltest_2,,mysqltest)
+
+# Create a procedure/function under u1.
+
+--echo
+--echo ---> connection: mysqltest_1_con
+--connection mysqltest_1_con
+
+use mysqltest;
+
+CREATE PROCEDURE bug13198_p1()
+  SELECT 1;
+
+CREATE FUNCTION bug13198_f1() RETURNS INT
+  RETURN 1;
+
+CALL bug13198_p1();
+
+SELECT bug13198_f1();
+
+# Check that u2 can call the procedure/function.
+
+--echo
+--echo ---> connection: mysqltest_2_con
+--connection mysqltest_2_con
+
+use mysqltest;
+
+CALL bug13198_p1();
+
+SELECT bug13198_f1();
+
+# Drop user u1 (definer of the object);
+
+--echo
+--echo ---> connection: root
+--connection con1root
+
+--disconnect mysqltest_1_con
+
+DROP USER mysqltest_1@localhost;
+
+# Check that u2 can not call the procedure/function.
+
+--echo
+--echo ---> connection: mysqltest_2_con
+--connection mysqltest_2_con
+
+use mysqltest;
+
+--error ER_NO_SUCH_USER
+CALL bug13198_p1();
+
+--error ER_NO_SUCH_USER
+SELECT bug13198_f1();
+
+# Cleanup.
+
+--echo
+--echo ---> connection: root
+--connection con1root
+
+--disconnect mysqltest_2_con
+
+DROP USER mysqltest_2@localhost;
+
+DROP DATABASE mysqltest;
+
+
 # End of 5.0 bugs.

--- 1.103/sql/sp.cc	2006-02-22 13:59:56 +03:00
+++ 1.104/sql/sp.cc	2006-03-09 20:41:18 +03:00
@@ -20,6 +20,8 @@
 #include "sp_cache.h"
 #include "sql_trigger.h"
 
+#include <my_user.h>
+
 static bool
 create_string(THD *thd, String *buf,
 	      int sp_type,
@@ -27,7 +29,9 @@
 	      const char *params, ulong paramslen,
 	      const char *returns, ulong returnslen,
 	      const char *body, ulong bodylen,
-	      st_sp_chistics *chistics);
+	      st_sp_chistics *chistics,
+              const LEX_STRING *definer_user,
+              const LEX_STRING *definer_host);
 static int
 db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
                 ulong sql_mode, const char *params, const char *returns,
@@ -405,6 +409,15 @@
   ulong old_sql_mode= thd->variables.sql_mode;
   ha_rows old_select_limit= thd->variables.select_limit;
   sp_rcontext *old_spcont= thd->spcont;
+  
+  char definer_user_name_holder[USERNAME_LENGTH + 1];
+  LEX_STRING_WITH_INIT definer_user_name(definer_user_name_holder,
+                                         USERNAME_LENGTH);
+
+  char definer_host_name_holder[HOSTNAME_LENGTH + 1];
+  LEX_STRING_WITH_INIT definer_host_name(definer_host_name_holder,
+                                         HOSTNAME_LENGTH);
+  
   int ret;
 
   thd->variables.sql_mode= sql_mode;
@@ -413,14 +426,25 @@
   thd->lex= &newlex;
   newlex.current_select= NULL;
 
+  parse_user(definer, strlen(definer),
+             definer_user_name.str, &definer_user_name.length,
+             definer_host_name.str, &definer_host_name.length);
+
   defstr.set_charset(system_charset_info);
+
+  /*
+    We have to add DEFINER clause and provide proper routine characterstics in
+    routine definition statement that we build here to be able to use this
+    definition for SHOW CREATE PROCEDURE later.
+   */
+
   if (!create_string(thd, &defstr,
 		     type,
 		     name,
 		     params, strlen(params),
 		     returns, strlen(returns),
 		     body, strlen(body),
-		     &chistics))
+		     &chistics, &definer_user_name, &definer_host_name))
   {
     ret= SP_INTERNAL_ERROR;
     goto end;
@@ -448,7 +472,7 @@
     if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
       goto end;
     *sphp= newlex.sphead;
-    (*sphp)->set_definer((char*) definer, (uint) strlen(definer));
+    (*sphp)->set_definer(&definer_user_name, &definer_host_name);
     (*sphp)->set_info(created, modified, &chistics, sql_mode);
     (*sphp)->optimize();
   }
@@ -501,8 +525,10 @@
   else
   {
     restore_record(table, s->default_values); // Get default values for fields
-    strxnmov(definer, sizeof(definer)-1, thd->security_ctx->priv_user, "@",
-            thd->security_ctx->priv_host, NullS);
+
+    /* NOTE: all needed privilege checks have been already done. */
+    strxnmov(definer, sizeof(definer)-1, thd->lex->definer->user.str, "@",
+            thd->lex->definer->host.str, NullS);
 
     if (table->s->fields != MYSQL_PROC_FIELD_COUNT)
     {
@@ -593,9 +619,17 @@
     else if (mysql_bin_log.is_open())
     {
       thd->clear_error();
+
+      String log_query;
+      log_query.set_charset(system_charset_info);
+      log_query.append(STRING_WITH_LEN("CREATE "));
+      append_definer(thd, &log_query, &thd->lex->definer->user,
+                     &thd->lex->definer->host);
+      log_query.append(thd->lex->stmt_definition_begin);
+
       /* Such a statement can always go directly to binlog, no trans cache */
       thd->binlog_query(THD::MYSQL_QUERY_TYPE,
-                        thd->query, thd->query_length, FALSE, FALSE);
+                        log_query.c_ptr(), log_query.length(), FALSE, FALSE);
     }
 
   }
@@ -1724,14 +1758,18 @@
 	      const char *params, ulong paramslen,
 	      const char *returns, ulong returnslen,
 	      const char *body, ulong bodylen,
-	      st_sp_chistics *chistics)
+	      st_sp_chistics *chistics,
+              const LEX_STRING *definer_user,
+              const LEX_STRING *definer_host)
 {
   /* Make some room to begin with */
   if (buf->alloc(100 + name->m_qname.length + paramslen + returnslen + bodylen +
-		 chistics->comment.length))
+		 chistics->comment.length + 10 /* length of " DEFINER= "*/ +
+                 USER_HOST_BUFF_SIZE))
     return FALSE;
 
   buf->append(STRING_WITH_LEN("CREATE "));
+  append_definer(thd, buf, definer_user, definer_host);
   if (type == TYPE_ENUM_FUNCTION)
     buf->append(STRING_WITH_LEN("FUNCTION "));
   else

--- 1.210/sql/sp_head.cc	2006-03-01 18:27:46 +03:00
+++ 1.211/sql/sp_head.cc	2006-03-09 20:37:52 +03:00
@@ -1846,19 +1846,27 @@
 void
 sp_head::set_definer(const char *definer, uint definerlen)
 {
-  uint user_name_len;
-  char user_name_str[USERNAME_LENGTH + 1];
-  uint host_name_len;
-  char host_name_str[HOSTNAME_LENGTH + 1];
+  char user_name_holder[USERNAME_LENGTH + 1];
+  LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_LENGTH);
 
-  parse_user(definer, definerlen, user_name_str, &user_name_len,
-             host_name_str, &host_name_len);
+  char host_name_holder[HOSTNAME_LENGTH + 1];
+  LEX_STRING_WITH_INIT host_name(host_name_holder, HOSTNAME_LENGTH);
 
-  m_definer_user.str= strmake_root(mem_root, user_name_str, user_name_len);
-  m_definer_user.length= user_name_len;
+  parse_user(definer, definerlen, user_name.str, &user_name.length,
+             host_name.str, &host_name.length);
 
-  m_definer_host.str= strmake_root(mem_root, host_name_str, host_name_len);
-  m_definer_host.length= host_name_len;
+  set_definer(&user_name, &host_name);
+}
+
+
+void
+sp_head::set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name)
+{
+  m_definer_user.str= strmake_root(mem_root, user_name->str, user_name->length);
+  m_definer_user.length= user_name->length;
+
+  m_definer_host.str= strmake_root(mem_root, host_name->str, host_name->length);
+  m_definer_host.length= host_name->length;
 }
 
 
@@ -3204,24 +3212,9 @@
                                 sp->m_definer_host.str,
                                 sp->m_db.str))
     {
-#ifdef NOT_YET_REPLICATION_SAFE
-      /*
-        Until we don't properly replicate information about stored routine
-        definer with stored routine creation statement all stored routines
-        on slave are created under ''@'' definer. Therefore we won't be able
-        to run any routine which was replicated from master on slave server
-        if we emit error here. This will cause big problems for users
-        who use slave for fail-over. So until we fully implement WL#2897
-        "Complete definer support in the stored routines" we run suid
-        stored routines for which we were unable to find definer under
-        invoker security context.
-      */
       my_error(ER_NO_SUCH_USER, MYF(0), sp->m_definer_user.str,
                sp->m_definer_host.str);
       return TRUE;
-#else
-      return FALSE;
-#endif
     }
     *backup= thd->security_ctx;
     thd->security_ctx= &sp->m_security_ctx;

--- 1.82/sql/sp_head.h	2006-03-01 18:27:46 +03:00
+++ 1.83/sql/sp_head.h	2006-03-09 20:37:52 +03:00
@@ -303,6 +303,7 @@
 		st_sp_chistics *chistics, ulong sql_mode);
 
   void set_definer(const char *definer, uint definerlen);
+  void set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name);
 
   void reset_thd_mem_root(THD *thd);
 

--- 1.100/mysql-test/r/mysqldump.result	2006-03-06 13:35:33 +03:00
+++ 1.101/mysql-test/r/mysqldump.result	2006-03-09 20:37:51 +03:00
@@ -2279,12 +2279,12 @@
 DELIMITER ;;
 /*!50003 DROP FUNCTION IF EXISTS `bug9056_func1` */;;
 /*!50003 SET SESSION SQL_MODE=""*/;;
-/*!50003 CREATE FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11)
+/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 FUNCTION `bug9056_func1`(a INT, b INT) RETURNS int(11)
 RETURN a+b */;;
 /*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
 /*!50003 DROP FUNCTION IF EXISTS `bug9056_func2` */;;
 /*!50003 SET SESSION SQL_MODE=""*/;;
-/*!50003 CREATE FUNCTION `bug9056_func2`(f1 char binary) RETURNS char(1)
+/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 FUNCTION `bug9056_func2`(f1 char binary) RETURNS char(1)
 begin
 set f1= concat( 'hello', f1 );
 return f1;
@@ -2292,17 +2292,17 @@
 /*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
 /*!50003 DROP PROCEDURE IF EXISTS `a'b` */;;
 /*!50003 SET SESSION SQL_MODE="REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI"*/;;
-/*!50003 CREATE PROCEDURE "a'b"()
+/*!50003 CREATE*/ /*!50019 DEFINER="root"@"localhost"*/ /*!50003 PROCEDURE "a'b"()
 select 1 */;;
 /*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
 /*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc1` */;;
 /*!50003 SET SESSION SQL_MODE=""*/;;
-/*!50003 CREATE PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT)
+/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc1`(IN a INT, IN b INT, OUT c INT)
 BEGIN SELECT a+b INTO c; end */;;
 /*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;;
 /*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc2` */;;
 /*!50003 SET SESSION SQL_MODE=""*/;;
-/*!50003 CREATE PROCEDURE `bug9056_proc2`(OUT a INT)
+/*!50003 CREATE*/ /*!50019 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc2`(OUT a INT)
 BEGIN 
 select sum(id) from t1 into a; 
 END */;;
@@ -2724,11 +2724,11 @@
 select 42 */|
 show create function f;
 Function	sql_mode	Create Function
-f		CREATE FUNCTION `f`() RETURNS bigint(20)
+f		CREATE DEFINER=`root`@`localhost` FUNCTION `f`() RETURNS bigint(20)
 return 42
 show create procedure p;
 Procedure	sql_mode	Create Procedure
-p		CREATE PROCEDURE `p`()
+p		CREATE DEFINER=`root`@`localhost` PROCEDURE `p`()
 select 42
 drop function f;
 drop procedure p;
Thread
bk commit into 5.1 tree (anozdrin:1.2162)Alexander Nozdrin9 Mar