List:Internals« Previous MessageNext Message »
From:pem Date:December 2 2005 2:11pm
Subject:bk commit into 5.0 tree (pem:1.2043)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of pem. When pem 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.2043 05/12/02 15:04:50 pem@stripped +5 -0
  Merge mysql.com:/usr/local/bk/mysql-5.0
  into  mysql.com:/usr/home/pem/bug14376/mysql-5.0

  sql/sp_pcontext.h
    1.24 05/12/02 15:04:43 pem@stripped +0 -0
    SCCS merged

  mysql-test/t/sp.test
    1.163 05/12/02 15:04:43 pem@stripped +0 -0
    SCCS merged

  mysql-test/r/sp.result
    1.170 05/12/02 15:04:43 pem@stripped +0 -0
    SCCS merged

  sql/sql_yacc.yy
    1.441 05/12/02 14:58:50 pem@stripped +0 -0
    Auto merged

  sql/sp_pcontext.cc
    1.27 05/12/02 14:58:50 pem@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:	pem
# Host:	mysql.comhem.se
# Root:	/usr/home/pem/bug14376/mysql-5.0/RESYNC

--- 1.440/sql/sql_yacc.yy	2005-12-02 14:30:35 +01:00
+++ 1.441/sql/sql_yacc.yy	2005-12-02 14:58:50 +01:00
@@ -175,6 +175,7 @@
 %token  CLIENT_SYM
 %token  CLOSE_SYM
 %token  COALESCE
+%token  CODE_SYM
 %token  COLLATE_SYM
 %token  COLLATION_SYM
 %token  COLUMNS
@@ -776,7 +777,7 @@
 
 %type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
 
-%type <lex_user> user grant_user
+%type <lex_user> user grant_user get_definer
 
 %type <charset>
 	opt_collate
@@ -827,10 +828,12 @@
 	subselect_end select_var_list select_var_list_init help opt_len
 	opt_extended_describe
         prepare prepare_src execute deallocate
-	statement sp_suid opt_view_list view_list or_replace algorithm
+	statement sp_suid
 	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
-        view_user view_suid
+        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
 END_OF_INPUT
 
 %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -1157,11 +1160,6 @@
 	| CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident
 	  {
 	    LEX *lex=Lex;
-            if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
-            {
-              my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-              YYABORT;
-            }
 	    lex->sql_command= SQLCOM_CREATE_INDEX;
 	    if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
 							TL_OPTION_UPDATING))
@@ -1258,80 +1256,14 @@
 	      YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
 	    sp->restore_thd_mem_root(YYTHD);
 	  }
-	| CREATE or_replace algorithm view_user view_suid VIEW_SYM table_ident
+	| CREATE
 	  {
-	    THD *thd= YYTHD;
-	    LEX *lex= thd->lex;
-	    lex->sql_command= SQLCOM_CREATE_VIEW;
-            lex->create_view_start= thd->query;
-	    /* first table in list is target VIEW name */
-	    if (!lex->select_lex.add_table_to_list(thd, $7, NULL, 0))
-              YYABORT;
+            Lex->create_view_mode= VIEW_CREATE_NEW;
+            Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
+            Lex->create_view_suid= TRUE;
 	  }
-	  opt_view_list AS select_view_init check_option
+	  view_or_trigger
 	  {}
-        | CREATE TRIGGER_SYM sp_name trg_action_time trg_event 
-          ON table_ident FOR_SYM EACH_SYM ROW_SYM
-          {
-            LEX *lex= Lex;
-            sp_head *sp;
-           
-            if (lex->sphead)
-            {
-              my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
-              YYABORT;
-            }
-
-            if (!(sp= new sp_head()))
-              YYABORT;
-            sp->reset_thd_mem_root(YYTHD);
-            sp->init(lex);
-            
-            sp->m_type= TYPE_ENUM_TRIGGER;
-            lex->sphead= sp;
-            lex->spname= $3;
-            /*
-              We have to turn of CLIENT_MULTI_QUERIES while parsing a
-              stored procedure, otherwise yylex will chop it into pieces
-              at each ';'.
-            */
-            sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
-            YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
-            
-            bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
-            lex->sphead->m_chistics= &lex->sp_chistics;
-            lex->sphead->m_body_begin= lex->ptr;
-          }
-          sp_proc_stmt
-          {
-            LEX *lex= Lex;
-            sp_head *sp= lex->sphead;
-            
-            lex->sql_command= SQLCOM_CREATE_TRIGGER;
-            sp->init_strings(YYTHD, lex, $3);
-            /* Restore flag if it was cleared above */
-            if (sp->m_old_cmq)
-              YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
-            sp->restore_thd_mem_root(YYTHD);
-
-            if (sp->is_not_allowed_in_function("trigger"))
-                YYABORT;
-
-            /*
-              We have to do it after parsing trigger body, because some of
-              sp_proc_stmt alternatives are not saving/restoring LEX, so
-              lex->query_tables can be wiped out.
-              
-              QQ: What are other consequences of this?
-              
-              QQ: Could we loosen lock type in certain cases ?
-            */
-            if (!lex->select_lex.add_table_to_list(YYTHD, $7, 
-                                                   (LEX_STRING*) 0,
-                                                   TL_OPTION_UPDATING,
-                                                   TL_WRITE))
-              YYABORT;
-          }
 	| CREATE USER clear_privileges grant_list
 	  {
 	    Lex->sql_command = SQLCOM_CREATE_USER;
@@ -1678,13 +1610,14 @@
             for (uint i = max-$2 ; i < max ; i++)
             {
               sp_instr_set *in;
+	      uint off= ctx->pvar_context2index(i);
 
-              ctx->set_type(i, type);
+              ctx->set_type(off, type);
               if (! has_default)
                 it= new Item_null();  /* QQ Set to the type with null_value? */
               in = new sp_instr_set(lex->sphead->instructions(),
                                     ctx,
-                                    ctx->pvar_context2index(i),
+                                    off,
                                     it, type, lex,
                                     (i == max - 1));
 
@@ -1693,7 +1626,7 @@
                 freeing LEX.
               */
               lex->sphead->add_instr(in);
-              ctx->set_default(i, it);
+              ctx->set_default(off, it);
             }
             ctx->declare_var_boundary(0);
             lex->sphead->restore_lex(YYTHD);
@@ -1768,7 +1701,8 @@
 	      delete $5;
 	      YYABORT;
 	    }
-            i= new sp_instr_cpush(sp->instructions(), ctx, $5);
+            i= new sp_instr_cpush(sp->instructions(), ctx, $5,
+                                  ctx->current_cursors());
 	    sp->add_instr(i);
 	    ctx->push_cursor(&$2);
 	    $$.vars= $$.conds= $$.hndlrs= 0;
@@ -2358,8 +2292,12 @@
 
 	      ivar.str= (char *)"_tmp_";
 	      ivar.length= 5;
-	      Item *var= (Item*) new Item_splocal(ivar, 
-						  ctx->current_pvars()-1);
+	      Item_splocal *var= new Item_splocal(ivar,
+                                                  ctx->current_pvars()-1);
+#ifndef DBUG_OFF
+              if (var)
+                var->owner= sp;
+#endif
 	      Item *expr= new Item_func_eq(var, $2);
 
 	      i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
@@ -3369,11 +3307,6 @@
 	{
 	  THD *thd= YYTHD;
 	  LEX *lex= thd->lex;
-          if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
-          {
-            my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-            YYABORT;
-          }
 	  lex->sql_command= SQLCOM_ALTER_TABLE;
 	  lex->name= 0;
 	  lex->duplicates= DUP_ERROR; 
@@ -3441,7 +3374,8 @@
 	    lex->sql_command= SQLCOM_ALTER_FUNCTION;
 	    lex->spname= $3;
 	  }
-	| ALTER algorithm view_user view_suid VIEW_SYM table_ident
+        | ALTER view_algorithm_opt definer view_suid
+          VIEW_SYM table_ident
 	  {
 	    THD *thd= YYTHD;
 	    LEX *lex= thd->lex;
@@ -3451,7 +3385,7 @@
 	    /* first table in list is target VIEW name */
 	    lex->select_lex.add_table_to_list(thd, $6, NULL, 0);
 	  }
-	  opt_view_list AS select_view_init check_option
+	  view_list_opt AS view_select view_check_option
 	  {}
 	;
 
@@ -3683,11 +3617,6 @@
 	START_SYM TRANSACTION_SYM start_transaction_opts
         {
           LEX *lex= Lex;
-          if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
-          {
-            my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-            YYABORT;
-          }
           lex->sql_command= SQLCOM_BEGIN;
           lex->start_transaction_opt= $3;
         }
@@ -3872,13 +3801,7 @@
 rename:
 	RENAME table_or_tables
 	{
-          LEX *lex= Lex;
-          if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
-          {
-            my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-            YYABORT;
-          }
-          lex->sql_command=SQLCOM_RENAME_TABLE;
+          Lex->sql_command= SQLCOM_RENAME_TABLE;
 	}
 	table_to_table_list
 	{}
@@ -4019,18 +3942,6 @@
 	|
 	'(' select_paren ')' union_opt;
 
-select_view_init:
-        SELECT_SYM remember_name select_init2
-          {
-            Lex->create_view_select_start= $2;
-          }
-        |
-        '(' remember_name select_paren ')' union_opt
-          {
-            Lex->create_view_select_start= $2;
-          }
-        ;
-
 select_paren:
 	SELECT_SYM select_part2
 	  {
@@ -5967,7 +5878,13 @@
 	       YYABORT;
 	     else
 	     {
-	       ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($1,1,t->offset,t->type));
+               my_var *var;
+	       ((select_dumpvar *)lex->result)->
+                 var_list.push_back(var= new my_var($1,1,t->offset,t->type));
+#ifndef DBUG_OFF
+	       if (var)
+		 var->owner= lex->sphead;
+#endif
 	     }
 	   }
            ;
@@ -6027,21 +5944,10 @@
 	  lex->sql_command = SQLCOM_DROP_TABLE;
 	  lex->drop_temporary= $2;
 	  lex->drop_if_exists= $4;
-          if (!lex->drop_temporary && lex->sphead &&
-              lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
-          {
-            my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-            YYABORT;
-          }
 	}
 	| DROP INDEX_SYM ident ON table_ident {}
 	  {
 	     LEX *lex=Lex;
-             if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
-             {
-               my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-               YYABORT;
-             }
 	     lex->sql_command= SQLCOM_DROP_INDEX;
 	     lex->alter_info.drop_list.empty();
 	     lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
@@ -6087,13 +5993,7 @@
           }
 	| DROP VIEW_SYM if_exists table_list opt_restrict
 	  {
-	    THD *thd= YYTHD;
-	    LEX *lex= thd->lex;
-            if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
-            {
-              my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-              YYABORT;
-            }
+	    LEX *lex= Lex;
 	    lex->sql_command= SQLCOM_DROP_VIEW;
 	    lex->drop_if_exists= $3;
 	  }
@@ -6706,7 +6606,28 @@
 	      YYABORT;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
               YYABORT;
-	  };
+	  }
+        | PROCEDURE CODE_SYM sp_name
+          {
+#ifdef DBUG_OFF
+            yyerror(ER(ER_SYNTAX_ERROR));
+            YYABORT;
+#else
+            Lex->sql_command= SQLCOM_SHOW_PROC_CODE;
+	    Lex->spname= $3;
+#endif
+          }
+        | FUNCTION_SYM CODE_SYM sp_name
+          {
+#ifdef DBUG_OFF
+            yyerror(ER(ER_SYNTAX_ERROR));
+            YYABORT;
+#else
+            Lex->sql_command= SQLCOM_SHOW_FUNC_CODE;
+	    Lex->spname= $3;
+#endif
+          }
+        ;
 
 show_engine_param:
 	STATUS_SYM
@@ -7266,6 +7187,10 @@
             Item_splocal *splocal;
             splocal= new Item_splocal($1, spv->offset, lex->tok_start_prev - 
                                       lex->sphead->m_tmp_query);
+#ifndef DBUG_OFF
+            if (splocal)
+              splocal->owner= lex->sphead;
+#endif
 	    $$ = (Item*) splocal;
             lex->variables_used= 1;
 	    lex->safe_to_cache_query=0;
@@ -7615,6 +7540,7 @@
 	| CHANGED		{}
 	| CIPHER_SYM		{}
 	| CLIENT_SYM		{}
+        | CODE_SYM              {}
 	| COLLATION_SYM		{}
         | COLUMNS               {}
 	| COMMITTED_SYM		{}
@@ -8044,6 +7970,9 @@
 	    names.length= 5;
 	    if (spc && spc->find_pvar(&names))
               my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
+            else
+              yyerror(ER(ER_SYNTAX_ERROR));
+
 	    YYABORT;
 	  }
 	| NAMES_SYM charset_name_or_default opt_collate
@@ -8733,11 +8662,6 @@
 	BEGIN_SYM  
         {
 	  LEX *lex=Lex;
-          if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
-          {
-            my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-            YYABORT;
-          }
           lex->sql_command = SQLCOM_BEGIN;
           lex->start_transaction_opt= 0;
         }
@@ -8770,11 +8694,6 @@
 	COMMIT_SYM opt_work opt_chain opt_release
 	{
 	  LEX *lex=Lex;
-          if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
-          {
-            my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-            YYABORT;
-          }
 	  lex->sql_command= SQLCOM_COMMIT;
 	  lex->tx_chain= $3; 
 	  lex->tx_release= $4;
@@ -8785,11 +8704,6 @@
 	ROLLBACK_SYM opt_work opt_chain opt_release
 	{
 	  LEX *lex=Lex;
-          if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
-          {
-            my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
-            YYABORT;
-          }
 	  lex->sql_command= SQLCOM_ROLLBACK;
 	  lex->tx_chain= $3; 
 	  lex->tx_release= $4;
@@ -8969,8 +8883,119 @@
 	  lex->current_select = lex->current_select->return_after_parsing();
 	};
 
-opt_view_list:
-	/* empty */ {}
+definer:
+	get_definer
+	{
+	  THD *thd= YYTHD;
+	  
+	  if (! (thd->lex->definer= create_definer(thd, &$1->user, &$1->host)))
+	    YYABORT;
+	}
+	;
+
+get_definer:
+	opt_current_definer
+	{
+	  THD *thd= YYTHD;
+          
+	  if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+	    YYABORT;
+
+	  if (get_default_definer(thd, $$))
+	    YYABORT;
+	}
+	| DEFINER_SYM EQ ident_or_text '@' ident_or_text
+	{
+	  if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user))))
+	    YYABORT;
+
+	  $$->user= $3;
+	  $$->host= $5;
+	}
+	;
+
+opt_current_definer:
+	/* empty */
+	| DEFINER_SYM EQ CURRENT_USER optional_braces
+	;
+
+/**************************************************************************
+
+ CREATE VIEW statement options.
+
+**************************************************************************/
+
+view_replace_or_algorithm:
+	view_replace
+	{}
+	| view_replace view_algorithm
+	{}
+	| view_algorithm
+	{}
+	;
+
+view_replace:
+	OR_SYM REPLACE
+	{ Lex->create_view_mode= VIEW_CREATE_OR_REPLACE; }
+	;
+
+view_algorithm:
+	ALGORITHM_SYM EQ UNDEFINED_SYM
+	{ Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
+	| ALGORITHM_SYM EQ MERGE_SYM
+	{ Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; }
+	| ALGORITHM_SYM EQ TEMPTABLE_SYM
+	{ Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; }
+	;
+
+view_algorithm_opt:
+	/* empty */
+	{ Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
+	| view_algorithm
+	{}
+	;
+
+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; }
+	| SQL_SYM SECURITY_SYM DEFINER_SYM
+	{ Lex->create_view_suid= TRUE; }
+	| SQL_SYM SECURITY_SYM INVOKER_SYM
+	{ Lex->create_view_suid= FALSE; }
+	;
+
+view_tail:
+	view_suid VIEW_SYM table_ident
+	{
+	  THD *thd= YYTHD;
+	  LEX *lex= thd->lex;
+	  lex->sql_command= SQLCOM_CREATE_VIEW;
+	  lex->create_view_start= thd->query;
+	  /* first table in list is target VIEW name */
+	  if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+	    YYABORT;
+	}
+	view_list_opt AS view_select view_check_option
+	{}
+	;
+
+view_list_opt:
+	/* empty */
+	{}
 	| '(' view_list ')'
 	;
 
@@ -8987,79 +9012,102 @@
 	  }
 	;
 
-or_replace:
-	/* empty */	 { Lex->create_view_mode= VIEW_CREATE_NEW; }
-	| OR_SYM REPLACE { Lex->create_view_mode= VIEW_CREATE_OR_REPLACE; }
+view_select:
+	SELECT_SYM remember_name select_init2
+	{
+	  Lex->create_view_select_start= $2;
+	}
+	| '(' remember_name select_paren ')' union_opt
+	{
+	  Lex->create_view_select_start= $2;
+	}
 	;
 
-algorithm:
+view_check_option:
 	/* empty */
-	  { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
-	| ALGORITHM_SYM EQ UNDEFINED_SYM
-	  { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
-	| ALGORITHM_SYM EQ MERGE_SYM
-	  { Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; }
-	| ALGORITHM_SYM EQ TEMPTABLE_SYM
-	  { Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; }
+	{ Lex->create_view_check= VIEW_CHECK_NONE; }
+	| WITH CHECK_SYM OPTION
+	{ Lex->create_view_check= VIEW_CHECK_CASCADED; }
+	| WITH CASCADED CHECK_SYM OPTION
+	{ Lex->create_view_check= VIEW_CHECK_CASCADED; }
+	| WITH LOCAL_SYM CHECK_SYM OPTION
+	{ Lex->create_view_check= VIEW_CHECK_LOCAL; }
 	;
 
-view_user:
-        /* empty */
-          {
-            THD *thd= YYTHD;
-            if (!(thd->lex->create_view_definer=
-                  (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
-              YYABORT;
-            if (default_view_definer(thd->security_ctx,
-                                     thd->lex->create_view_definer))
-              YYABORT;
-          }
-        | CURRENT_USER optional_braces
-          {
-            THD *thd= YYTHD;
-            if (!(thd->lex->create_view_definer=
-                  (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
-              YYABORT;
-            if (default_view_definer(thd->security_ctx,
-                                     thd->lex->create_view_definer))
-              YYABORT;
-          }
-	| DEFINER_SYM EQ ident_or_text '@' ident_or_text
+/**************************************************************************
+
+ CREATE TRIGGER statement parts.
+
+**************************************************************************/
+
+trigger_tail:
+	TRIGGER_SYM remember_name sp_name trg_action_time trg_event 
+	ON table_ident FOR_SYM EACH_SYM ROW_SYM
+	{
+	  LEX *lex= Lex;
+	  sp_head *sp;
+	 
+	  if (lex->sphead)
 	  {
-	    THD *thd= YYTHD;
-            st_lex_user *view_user;
-	    if (!(thd->lex->create_view_definer= view_user=
-                  (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
-	      YYABORT;
-	    view_user->user = $3; view_user->host=$5;
-            if (view_user->host.length == 0)
-            {
-              my_error(ER_NO_VIEW_USER, MYF(0));
-              YYABORT;
-            }
+	    my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
+	    YYABORT;
 	  }
-        ;
-
-view_suid:
-        /* empty */
-	  { Lex->create_view_suid= TRUE; }
-        |
-	  SQL_SYM SECURITY_SYM DEFINER_SYM
-	  { Lex->create_view_suid= TRUE; }
-	| SQL_SYM SECURITY_SYM INVOKER_SYM
-	  { Lex->create_view_suid= FALSE; }
+	
+	  if (!(sp= new sp_head()))
+	    YYABORT;
+	  sp->reset_thd_mem_root(YYTHD);
+	  sp->init(lex);
+	
+	  lex->trigger_definition_begin= $2;
+	  
+	  sp->m_type= TYPE_ENUM_TRIGGER;
+	  lex->sphead= sp;
+	  lex->spname= $3;
+	  /*
+	    We have to turn of CLIENT_MULTI_QUERIES while parsing a
+	    stored procedure, otherwise yylex will chop it into pieces
+	    at each ';'.
+	  */
+	  sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
+	  YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
+	  
+	  bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+	  lex->sphead->m_chistics= &lex->sp_chistics;
+	  lex->sphead->m_body_begin= lex->ptr;
+	}
+	sp_proc_stmt
+	{
+	  LEX *lex= Lex;
+	  sp_head *sp= lex->sphead;
+	  
+	  lex->sql_command= SQLCOM_CREATE_TRIGGER;
+	  sp->init_strings(YYTHD, lex, $3);
+	  /* Restore flag if it was cleared above */
+	  if (sp->m_old_cmq)
+	    YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
+	  sp->restore_thd_mem_root(YYTHD);
+	
+	  if (sp->is_not_allowed_in_function("trigger"))
+	      YYABORT;
+	
+	  /*
+	    We have to do it after parsing trigger body, because some of
+	    sp_proc_stmt alternatives are not saving/restoring LEX, so
+	    lex->query_tables can be wiped out.
+	    
+	    QQ: What are other consequences of this?
+	    
+	    QQ: Could we loosen lock type in certain cases ?
+	  */
+	  if (!lex->select_lex.add_table_to_list(YYTHD, $7, 
+	                                         (LEX_STRING*) 0,
+	                                         TL_OPTION_UPDATING,
+	                                         TL_WRITE))
+	    YYABORT;
+	}
 	;
 
-check_option:
-        /* empty */
-          { Lex->create_view_check= VIEW_CHECK_NONE; }
-        | WITH CHECK_SYM OPTION
-          { Lex->create_view_check= VIEW_CHECK_CASCADED; }
-        | WITH CASCADED CHECK_SYM OPTION
-          { Lex->create_view_check= VIEW_CHECK_CASCADED; }
-        | WITH LOCAL_SYM CHECK_SYM OPTION
-          { Lex->create_view_check= VIEW_CHECK_LOCAL; }
-        ;
+/*************************************************************************/
 
 xa: XA_SYM begin_or_start xid opt_join_or_resume
       {

--- 1.169/mysql-test/r/sp.result	2005-11-01 14:58:44 +01:00
+++ 1.170/mysql-test/r/sp.result	2005-12-02 15:04:43 +01:00
@@ -988,6 +988,10 @@
 select f5(1)|
 f5(1)
 1
+select f5(2)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+select f5(3)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
 create function f6() returns int
 begin
 declare n int;
@@ -1035,6 +1039,12 @@
 ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
 create function f1() returns int
 return (select sum(data) from t1) + (select sum(data) from v1)|
+select f1()|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+select * from v1|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+select * from v2|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
 drop function f1|
 create function f1() returns int
 return (select sum(data) from t1)|
@@ -1053,7 +1063,7 @@
 select *, f0() from v0|
 f0()	f0()
 100	100
-lock tables t1 read, t1 as t11 read, mysql.proc read|
+lock tables t1 read, t1 as t11 read|
 select f3()|
 f3()
 1
@@ -1251,6 +1261,62 @@
 drop procedure ip|
 show procedure status like '%p%'|
 Db	Name	Type	Definer	Modified	Created	Security_type	Comment
+drop table if exists fib|
+create table fib ( f bigint unsigned not null )|
+drop procedure if exists fib|
+create procedure fib(n int unsigned)
+begin
+if n > 1 then
+begin
+declare x, y bigint unsigned;
+declare c cursor for select f from fib order by f desc limit 2;
+open c;
+fetch c into y;
+fetch c into x;
+close c;
+insert into fib values (x+y);
+call fib(n-1);
+end;
+end if;
+end|
+set @@max_sp_recursion_depth= 20|
+insert into fib values (0), (1)|
+call fib(3)|
+select * from fib order by f asc|
+f
+0
+1
+1
+2
+delete from fib|
+insert into fib values (0), (1)|
+call fib(20)|
+select * from fib order by f asc|
+f
+0
+1
+1
+2
+3
+5
+8
+13
+21
+34
+55
+89
+144
+233
+377
+610
+987
+1597
+2584
+4181
+6765
+drop table fib|
+drop procedure fib|
+set @@max_sp_recursion_depth= 0|
 drop procedure if exists bar|
 create procedure bar(x char(16), y int)
 comment "111111111111" sql security invoker
@@ -1479,6 +1545,52 @@
 @x2
 2
 drop procedure bug2260|
+drop procedure if exists bug2267_1|
+create procedure bug2267_1()
+begin
+show procedure status;
+end|
+drop procedure if exists bug2267_2|
+create procedure bug2267_2()
+begin
+show function status;
+end|
+drop procedure if exists bug2267_3|
+create procedure bug2267_3()
+begin
+show create procedure bug2267_1;
+end|
+drop procedure if exists bug2267_4|
+drop function if exists bug2267_4|
+create procedure bug2267_4()
+begin
+show create function bug2267_4;
+end|
+create function bug2267_4() returns int return 100|
+call bug2267_1()|
+Db	Name	Type	Definer	Modified	Created	Security_type	Comment
+test	bug2267_1	PROCEDURE	root@localhost	0000-00-00 00:00:00	0000-00-00 00:00:00	DEFINER	
+test	bug2267_2	PROCEDURE	root@localhost	0000-00-00 00:00:00	0000-00-00 00:00:00	DEFINER	
+test	bug2267_3	PROCEDURE	root@localhost	0000-00-00 00:00:00	0000-00-00 00:00:00	DEFINER	
+test	bug2267_4	PROCEDURE	root@localhost	0000-00-00 00:00:00	0000-00-00 00:00:00	DEFINER	
+call bug2267_2()|
+Db	Name	Type	Definer	Modified	Created	Security_type	Comment
+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`()
+begin
+show procedure status;
+end
+call bug2267_4()|
+Function	sql_mode	Create Function
+bug2267_4		CREATE FUNCTION `bug2267_4`() RETURNS int(11)
+return 100
+drop procedure bug2267_1|
+drop procedure bug2267_2|
+drop procedure bug2267_3|
+drop procedure bug2267_4|
+drop function bug2267_4|
 drop procedure if exists bug2227|
 create procedure bug2227(x int)
 begin
@@ -1490,6 +1602,18 @@
 1.3	x	y	42	z
 1.3	9	2.6	42	zzz
 drop procedure bug2227|
+drop procedure if exists bug2614|
+create procedure bug2614()
+begin
+drop table if exists t3;
+create table t3 (id int default '0' not null);
+insert into t3 select 12;
+insert into t3 select * from t3;
+end|
+call bug2614()|
+call bug2614()|
+drop table t3|
+drop procedure bug2614|
 drop function if exists bug2674|
 create function bug2674() returns int
 return @@sort_buffer_size|
@@ -3417,6 +3541,9 @@
 tm1	CREATE TEMPORARY TABLE `tm1` (
   `spv1` decimal(6,3) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop procedure bug12589_1|
+drop procedure bug12589_2|
+drop procedure bug12589_3|
 drop table if exists t3|
 drop procedure if exists bug7049_1|
 drop procedure if exists bug7049_2|
@@ -3575,6 +3702,374 @@
 DROP PROCEDURE IF EXISTS bug13095;
 DROP VIEW IF EXISTS bug13095_v1;
 DROP TABLE IF EXISTS bug13095_t1;
+drop procedure if exists bug14210|
+set @@session.max_heap_table_size=16384|
+select @@session.max_heap_table_size|
+@@session.max_heap_table_size
+16384
+create table t3 (a char(255)) engine=InnoDB|
+create procedure bug14210_fill_table()
+begin
+declare table_size, max_table_size int default 0;
+select @@session.max_heap_table_size into max_table_size;
+delete from t3;
+insert into t3 (a) values (repeat('a', 255));
+repeat
+insert into t3 select a from t3;
+select count(*)*255 from t3 into table_size;
+until table_size > max_table_size*2 end repeat;
+end|
+call bug14210_fill_table()|
+drop procedure bug14210_fill_table|
+create table t4 like t3|
+create procedure bug14210()
+begin
+declare a char(255);
+declare done int default 0;
+declare c cursor for select * from t3;
+declare continue handler for sqlstate '02000' set done = 1;
+open c;
+repeat
+fetch c into a;
+if not done then
+insert into t4 values (upper(a));
+end if;
+until done end repeat;
+close c;
+end|
+call bug14210()|
+select count(*) from t4|
+count(*)
+256
+drop table t3, t4|
+drop procedure bug14210|
+set @@session.max_heap_table_size=default|
+drop function if exists bug14723|
+drop procedure if exists bug14723|
+/*!50003 create function bug14723()
+returns bigint(20)
+main_loop: begin
+return 42;
+end */;;
+show create function bug14723;;
+Function	sql_mode	Create Function
+bug14723		CREATE FUNCTION `bug14723`() RETURNS bigint(20)
+main_loop: begin
+return 42;
+end
+select bug14723();;
+bug14723()
+42
+/*!50003 create procedure bug14723()
+main_loop: begin
+select 42;
+end */;;
+show create procedure bug14723;;
+Procedure	sql_mode	Create Procedure
+bug14723		CREATE PROCEDURE `bug14723`()
+main_loop: begin
+select 42;
+end
+call bug14723();;
+42
+42
+drop function bug14723|
+drop procedure bug14723|
+create procedure bug14845()
+begin
+declare a char(255);
+declare done int default 0;
+declare c cursor for select count(*) from t1 where 1 = 0;
+declare continue handler for sqlstate '02000' set done = 1;
+open c;
+repeat
+fetch c into a;
+if not done then
+select a;
+end if;
+until done end repeat;
+close c;
+end|
+call bug14845()|
+a
+0
+drop procedure bug14845|
+drop procedure if exists bug13549_1|
+drop procedure if exists bug13549_2|
+CREATE PROCEDURE `bug13549_2`()
+begin
+call bug13549_1();
+end|
+CREATE PROCEDURE `bug13549_1`()
+begin
+declare done int default 0;
+set done= not done;
+end|
+CALL bug13549_2()|
+drop procedure bug13549_2|
+drop procedure bug13549_1|
+drop function if exists bug10100f|
+drop procedure if exists bug10100p|
+drop procedure if exists bug10100t|
+drop procedure if exists bug10100pt|
+drop procedure if exists bug10100pv|
+drop procedure if exists bug10100pd|
+drop procedure if exists bug10100pc|
+create function bug10100f(prm int) returns int
+begin
+if prm > 1 then
+return prm * bug10100f(prm - 1);
+end if;
+return 1;
+end|
+create procedure bug10100p(prm int, inout res int)
+begin
+set res = res * prm;
+if prm > 1 then
+call bug10100p(prm - 1, res);  
+end if;
+end|
+create procedure bug10100t(prm int)
+begin
+declare res int;
+set res = 1;
+call bug10100p(prm, res);
+select res;
+end|
+create table t3 (a int)|
+insert into t3 values (0)|
+create view v1 as select a from t3;
+create procedure bug10100pt(level int, lim int)
+begin
+if level < lim then
+update t3 set a=level;
+FLUSH TABLES;
+call bug10100pt(level+1, lim);
+else
+select * from t3;
+end if;
+end|
+create procedure bug10100pv(level int, lim int)
+begin
+if level < lim then
+update v1 set a=level;
+FLUSH TABLES;
+call bug10100pv(level+1, lim);
+else
+select * from v1;
+end if;
+end|
+prepare stmt2 from "select * from t3;";
+create procedure bug10100pd(level int, lim int)
+begin
+if level < lim then
+select level;
+prepare stmt1 from "update t3 set a=a+2";
+execute stmt1;
+FLUSH TABLES;
+execute stmt1;
+FLUSH TABLES;
+execute stmt1;
+FLUSH TABLES;
+deallocate prepare stmt1;
+execute stmt2;
+select * from t3;
+call bug10100pd(level+1, lim);
+else
+execute stmt2;
+end if;
+end|
+create procedure bug10100pc(level int, lim int)
+begin
+declare lv int;
+declare c cursor for select a from t3;
+open c;
+if level < lim then
+select level;
+fetch c into lv;
+select lv;
+update t3 set a=level+lv;
+FLUSH TABLES;
+call bug10100pc(level+1, lim);
+else
+select * from t3;
+end if;
+close c;
+end|
+set @@max_sp_recursion_depth=4|
+select @@max_sp_recursion_depth|
+@@max_sp_recursion_depth
+4
+select bug10100f(3)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+select bug10100f(6)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+call bug10100t(5)|
+res
+120
+call bug10100pt(1,5)|
+a
+4
+call bug10100pv(1,5)|
+a
+4
+update t3 set a=1|
+call bug10100pd(1,5)|
+level
+1
+a
+7
+a
+7
+level
+2
+a
+13
+a
+13
+level
+3
+a
+19
+a
+19
+level
+4
+a
+25
+a
+25
+a
+25
+select * from t3|
+a
+25
+update t3 set a=1|
+call bug10100pc(1,5)|
+level
+1
+lv
+1
+level
+2
+lv
+2
+level
+3
+lv
+4
+level
+4
+lv
+7
+a
+11
+select * from t3|
+a
+11
+set @@max_sp_recursion_depth=0|
+select @@max_sp_recursion_depth|
+@@max_sp_recursion_depth
+0
+select bug10100f(5)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+call bug10100t(5)|
+ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine bug10100p
+set @@max_sp_recursion_depth=255|
+set @var=1|
+call bug10100p(255, @var)|
+call bug10100pt(1,255)|
+call bug10100pv(1,255)|
+call bug10100pd(1,255)|
+call bug10100pc(1,255)|
+set @@max_sp_recursion_depth=0|
+deallocate prepare stmt2|
+drop function bug10100f|
+drop procedure bug10100p|
+drop procedure bug10100t|
+drop procedure bug10100pt|
+drop procedure bug10100pv|
+drop procedure bug10100pd|
+drop procedure bug10100pc|
+drop view v1|
+drop procedure if exists bug13729|
+drop table if exists t3|
+create table t3 (s1 int, primary key (s1))|
+insert into t3 values (1),(2)|
+create procedure bug13729()
+begin
+declare continue handler for sqlexception select 55;
+update t3 set s1 = 1;
+end|
+call bug13729()|
+55
+55
+select * from t3|
+s1
+1
+2
+drop procedure bug13729|
+drop table t3|
+drop procedure if exists bug14643_1|
+drop procedure if exists bug14643_2|
+create procedure bug14643_1()
+begin
+declare continue handler for sqlexception select 'boo' as 'Handler';
+begin
+declare v int default x;
+if v = 1 then
+select 1;
+else
+select 2;
+end if;
+end;
+end|
+create procedure bug14643_2()
+begin
+declare continue handler for sqlexception select 'boo' as 'Handler';
+case x
+when 1 then
+select 1;
+else
+select 2;
+end case;
+end|
+call bug14643_1()|
+Handler
+boo
+2
+2
+call bug14643_2()|
+Handler
+boo
+2
+2
+drop procedure bug14643_1|
+drop procedure bug14643_2|
+drop procedure if exists bug14304|
+drop table if exists t3, t4|
+create table t3(a int primary key auto_increment)|
+create table t4(a int primary key auto_increment)|
+create procedure bug14304()
+begin
+insert into t3 set a=null;
+insert into t4 set a=null;
+insert into t4 set a=null;
+insert into t4 set a=null;
+insert into t4 set a=null;
+insert into t4 set a=null;
+insert into t4 select null as a;
+insert into t3 set a=null;
+insert into t3 set a=null;
+select * from t3;
+end|
+call bug14304()|
+a
+1
+2
+3
+drop procedure bug14304|
+drop table t3, t4|
 drop procedure if exists bug14376|
 create procedure bug14376()
 begin

--- 1.162/mysql-test/t/sp.test	2005-11-01 14:58:45 +01:00
+++ 1.163/mysql-test/t/sp.test	2005-12-02 15:04:43 +01:00
@@ -1211,15 +1211,13 @@
   end if;
 end|
 select f5(1)|
-# This should generate an error about insuficient number of tables locked
-# Now this crash server
---disable_parsing # until bug#11394 fix
---error 1100
+# Since currently recursive functions are disallowed ER_SP_NO_RECURSION
+# error will be returned, once we will allow them error about
+# insufficient number of locked tables will be returned instead.
+--error ER_SP_NO_RECURSION
 select f5(2)|
-# But now it simply miserably fails because we are trying to use the same
-# lex on the next iteration :/ It should generate some error too...
+--error ER_SP_NO_RECURSION
 select f5(3)|
---enable_parsing
 
 # OTOH this should work 
 create function f6() returns int
@@ -1265,13 +1263,12 @@
 # views and functions ?
 create function f1() returns int
   return (select sum(data) from t1) + (select sum(data) from v1)|
-# This queries will crash server because we can't use LEX in
-# reenterable fashion yet. Patch disabling recursion will heal this.
---disable_parsing
+--error ER_SP_NO_RECURSION
 select f1()|
+--error ER_SP_NO_RECURSION
 select * from v1|
+--error ER_SP_NO_RECURSION
 select * from v2|
---enable_parsing
 # Back to the normal cases
 drop function f1|
 create function f1() returns int
@@ -1289,9 +1286,7 @@
 #
 # Let us test how well prelocking works with explicit LOCK TABLES.
 #
-# Nowdays we have to lock mysql.proc to be able to read SP definitions.
-# But Monty was going to fix this.
-lock tables t1 read, t1 as t11 read, mysql.proc read|
+lock tables t1 read, t1 as t11 read|
 # These should work well
 select f3()|
 select id, f3() from t1 as t11|
@@ -1481,9 +1476,6 @@
 
 # Fibonacci, for recursion test. (Yet Another Numerical series :)
 #
-# This part of test is disabled until we implement support for
-# recursive stored procedures.
---disable_parsing
 --disable_warnings
 drop table if exists fib|
 --enable_warnings
@@ -1512,6 +1504,9 @@
   end if;
 end|
 
+# Enable recursion
+set @@max_sp_recursion_depth= 20|
+
 # Minimum test: recursion of 3 levels
 
 insert into fib values (0), (1)|
@@ -1531,7 +1526,7 @@
 select * from fib order by f asc|
 drop table fib|
 drop procedure fib|
---enable_parsing
+set @@max_sp_recursion_depth= 0|
 
 #
 # Comment & suid
@@ -1800,16 +1795,8 @@
 drop procedure bug2260|
 
 #
-# BUG#2267
+# BUG#2267 "Lost connect if stored procedure has SHOW FUNCTION STATUS"
 #
-# NOTE: This test case will be fixed as soon as Monty
-#       will allow to open mysql.proc table under LOCK TABLES
-#       without mentioning in lock list.
-#       
-# FIXME: Other solution would be to use preopened proc table
-#        instead of opening it anew.
-# 
---disable_parsing
 --disable_warnings
 drop procedure if exists bug2267_1|
 --enable_warnings
@@ -1836,11 +1823,13 @@
 
 --disable_warnings
 drop procedure if exists bug2267_4|
+drop function if exists bug2267_4|
 --enable_warnings
 create procedure bug2267_4()
 begin
-  show create function fac;
+  show create function bug2267_4;
 end|
+create function bug2267_4() returns int return 100|
 
 --replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
 call bug2267_1()|
@@ -1853,7 +1842,7 @@
 drop procedure bug2267_2|
 drop procedure bug2267_3|
 drop procedure bug2267_4|
---enable_parsing
+drop function bug2267_4|
 
 #
 # BUG#2227
@@ -1873,23 +1862,16 @@
 drop procedure bug2227|
 
 #
-# BUG#2614
+# BUG#2614 "Stored procedure with INSERT ... SELECT that does not
+#           contain any tables crashes server"
 #
-# QQ The second insert doesn't work with temporary tables (it was an
-# QQ ordinary table before we changed the locking scheme). It results
-# QQ in an error: 1137: Can't reopen table: 't3'
-# QQ which is a known limit with temporary tables.
-# QQ For this reason we can't run this test any more (i.e., if we modify
-# QQ it, it's no longer a test case for the bug), but we keep it here
-# QQ anyway, for tracability.
---disable_parsing
 --disable_warnings
 drop procedure if exists bug2614|
 --enable_warnings
 create procedure bug2614()
 begin
-  drop temporary table if exists t3;
-  create temporary table t3 (id int default '0' not null);
+  drop table if exists t3;
+  create table t3 (id int default '0' not null);
   insert into t3 select 12;
   insert into t3 select * from t3;
 end|
@@ -1898,9 +1880,8 @@
 call bug2614()|
 --enable_warnings
 call bug2614()|
-drop temporary table t3|
+drop table t3|
 drop procedure bug2614|
---enable_parsing
 
 #
 # BUG#2674
@@ -4291,6 +4272,9 @@
 # No warnings here
 call bug12589_2()|
 call bug12589_3()|
+drop procedure bug12589_1|
+drop procedure bug12589_2|
+drop procedure bug12589_3|
 
 #
 # BUG#7049: Stored procedure CALL errors are ignored
@@ -4488,6 +4472,388 @@
 
 delimiter |;
 
+#
+# BUG#14210: "Simple query with > operator on large table gives server
+# crash"
+# Check that cursors work in case when HEAP tables are converted to
+# MyISAM
+#
+--disable_warnings
+drop procedure if exists bug14210|
+--enable_warnings
+set @@session.max_heap_table_size=16384|
+select @@session.max_heap_table_size|
+# To trigger the memory corruption the original table must be InnoDB.
+# No harm if it's not, so don't warn if the suite is run with --skip-innodb
+--disable_warnings
+create table t3 (a char(255)) engine=InnoDB|
+--enable_warnings
+create procedure bug14210_fill_table()
+begin
+  declare table_size, max_table_size int default 0;
+  select @@session.max_heap_table_size into max_table_size;
+  delete from t3;
+  insert into t3 (a) values (repeat('a', 255));
+  repeat
+    insert into t3 select a from t3;
+    select count(*)*255 from t3 into table_size;
+  until table_size > max_table_size*2 end repeat;
+end|
+call bug14210_fill_table()|
+drop procedure bug14210_fill_table|
+create table t4 like t3|
+
+create procedure bug14210()
+begin
+  declare a char(255);
+  declare done int default 0;
+  declare c cursor for select * from t3;
+  declare continue handler for sqlstate '02000' set done = 1;
+  open c;
+  repeat
+    fetch c into a;
+    if not done then
+       insert into t4 values (upper(a));
+    end if;
+  until done end repeat;
+  close c;
+end|
+call bug14210()|
+select count(*) from t4|
+
+drop table t3, t4|
+drop procedure bug14210|
+set @@session.max_heap_table_size=default|
+
+
+#
+# BUG#1473: Dumping of stored functions seems to cause corruption in
+#           the function body
+#
+--disable_warnings
+drop function if exists bug14723|
+drop procedure if exists bug14723|
+--enable_warnings
+
+delimiter ;;|
+/*!50003 create function bug14723()
+ returns bigint(20)
+main_loop: begin
+  return 42;
+end */;;
+show create function bug14723;;
+select bug14723();;
+
+/*!50003 create procedure bug14723()
+main_loop: begin
+  select 42;
+end */;;
+show create procedure bug14723;;
+call bug14723();;
+
+delimiter |;;
+
+drop function bug14723|
+drop procedure bug14723|
+
+#
+# Bug#14845 "mysql_stmt_fetch returns MYSQL_NO_DATA when COUNT(*) is 0"
+# Check that when fetching from a cursor, COUNT(*) works properly.
+#
+create procedure bug14845()
+begin
+  declare a char(255);
+  declare done int default 0;
+  declare c cursor for select count(*) from t1 where 1 = 0;
+  declare continue handler for sqlstate '02000' set done = 1;
+  open c;
+  repeat
+    fetch c into a;
+    if not done then
+      select a;
+    end if;
+  until done end repeat;
+  close c;
+end|
+call bug14845()|
+drop procedure bug14845|
+
+#
+# BUG#13549 "Server crash with nested stored procedures".
+# Server should not crash when during execution of stored procedure
+# we have to parse trigger/function definition and this new trigger/
+# function has more local variables declared than invoking stored
+# procedure and last of these variables is used in argument of NOT
+# operator.
+#
+--disable_warnings
+drop procedure if exists bug13549_1|
+drop procedure if exists bug13549_2|
+--enable_warnings
+CREATE PROCEDURE `bug13549_2`()
+begin
+  call bug13549_1();
+end|
+CREATE PROCEDURE `bug13549_1`()
+begin
+  declare done int default 0;
+  set done= not done;
+end|
+CALL bug13549_2()|
+drop procedure bug13549_2|
+drop procedure bug13549_1|
+
+#
+# BUG#10100: function (and stored procedure?) recursivity problem
+#
+--disable_warnings
+drop function if exists bug10100f|
+drop procedure if exists bug10100p|
+drop procedure if exists bug10100t|
+drop procedure if exists bug10100pt|
+drop procedure if exists bug10100pv|
+drop procedure if exists bug10100pd|
+drop procedure if exists bug10100pc|
+--enable_warnings
+# routines with simple recursion
+create function bug10100f(prm int) returns int
+begin
+  if prm > 1 then
+    return prm * bug10100f(prm - 1);
+  end if;
+  return 1;
+end|
+create procedure bug10100p(prm int, inout res int)
+begin
+  set res = res * prm;
+  if prm > 1 then
+    call bug10100p(prm - 1, res);  
+  end if;
+end|
+create procedure bug10100t(prm int)
+begin
+  declare res int;
+  set res = 1;
+  call bug10100p(prm, res);
+  select res;
+end|
+
+# a procedure which use tables and recursion
+create table t3 (a int)|
+insert into t3 values (0)|
+create view v1 as select a from t3;
+create procedure bug10100pt(level int, lim int)
+begin
+  if level < lim then
+    update t3 set a=level;
+    FLUSH TABLES;
+    call bug10100pt(level+1, lim);
+  else
+    select * from t3;
+  end if;
+end|
+# view & recursion
+create procedure bug10100pv(level int, lim int)
+begin
+  if level < lim then
+    update v1 set a=level;
+    FLUSH TABLES;
+    call bug10100pv(level+1, lim);
+  else
+    select * from v1;
+  end if;
+end|
+# dynamic sql & recursion
+prepare stmt2 from "select * from t3;";
+create procedure bug10100pd(level int, lim int)
+begin
+  if level < lim then
+    select level;
+    prepare stmt1 from "update t3 set a=a+2";
+    execute stmt1;
+    FLUSH TABLES;
+    execute stmt1;
+    FLUSH TABLES;
+    execute stmt1;
+    FLUSH TABLES;
+    deallocate prepare stmt1;
+    execute stmt2;
+    select * from t3;
+    call bug10100pd(level+1, lim);
+  else
+    execute stmt2;
+  end if;
+end|
+# cursor & recursion
+create procedure bug10100pc(level int, lim int)
+begin
+  declare lv int;
+  declare c cursor for select a from t3;
+  open c;
+  if level < lim then
+    select level;
+    fetch c into lv;
+    select lv;
+    update t3 set a=level+lv;
+    FLUSH TABLES;
+    call bug10100pc(level+1, lim);
+  else
+    select * from t3;
+  end if;
+  close c;
+end|
+
+set @@max_sp_recursion_depth=4|
+select @@max_sp_recursion_depth|
+-- error ER_SP_NO_RECURSION
+select bug10100f(3)|
+-- error ER_SP_NO_RECURSION
+select bug10100f(6)|
+call bug10100t(5)|
+call bug10100pt(1,5)|
+call bug10100pv(1,5)|
+update t3 set a=1|
+call bug10100pd(1,5)|
+select * from t3|
+update t3 set a=1|
+call bug10100pc(1,5)|
+select * from t3|
+set @@max_sp_recursion_depth=0|
+select @@max_sp_recursion_depth|
+-- error ER_SP_NO_RECURSION
+select bug10100f(5)|
+-- error ER_SP_RECURSION_LIMIT
+call bug10100t(5)|
+
+#end of the stack checking
+set @@max_sp_recursion_depth=255|
+set @var=1|
+#disable log because error about stack overrun contains numbers which
+#depend on a system
+-- disable_result_log
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100p(255, @var)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pt(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pv(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pd(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pc(1,255)|
+-- enable_result_log
+set @@max_sp_recursion_depth=0|
+
+deallocate prepare stmt2|
+
+drop function bug10100f|
+drop procedure bug10100p|
+drop procedure bug10100t|
+drop procedure bug10100pt|
+drop procedure bug10100pv|
+drop procedure bug10100pd|
+drop procedure bug10100pc|
+drop view v1|
+
+#
+# BUG#13729: Stored procedures: packet error after exception handled
+#
+--disable_warnings
+drop procedure if exists bug13729|
+drop table if exists t3|
+--enable_warnings
+
+create table t3 (s1 int, primary key (s1))|
+
+insert into t3 values (1),(2)|
+
+create procedure bug13729()
+begin
+  declare continue handler for sqlexception select 55;
+
+  update t3 set s1 = 1;
+end|
+
+call bug13729()|
+# Used to cause Packets out of order
+select * from t3|
+
+drop procedure bug13729|
+drop table t3|
+
+#
+# BUG#14643: Stored Procedure: Continuing after failed var. initialization
+#            crashes server.
+#
+--disable_warnings
+drop procedure if exists bug14643_1|
+drop procedure if exists bug14643_2|
+--enable_warnings
+
+create procedure bug14643_1()
+begin
+  declare continue handler for sqlexception select 'boo' as 'Handler';
+
+  begin
+    declare v int default x;
+
+    if v = 1 then
+      select 1;
+    else
+      select 2;
+    end if;
+  end;
+end|
+
+create procedure bug14643_2()
+begin
+  declare continue handler for sqlexception select 'boo' as 'Handler';
+
+  case x
+  when 1 then
+    select 1;
+  else
+    select 2;
+  end case;
+end|
+
+call bug14643_1()|
+call bug14643_2()|
+
+drop procedure bug14643_1|
+drop procedure bug14643_2|
+
+#
+# BUG#14304: auto_increment field incorrect set in SP
+#
+--disable_warnings
+drop procedure if exists bug14304|
+drop table if exists t3, t4|
+--enable_warnings
+
+create table t3(a int primary key auto_increment)|
+create table t4(a int primary key auto_increment)|
+
+create procedure bug14304()
+begin
+  insert into t3 set a=null;
+  insert into t4 set a=null;
+  insert into t4 set a=null;
+  insert into t4 set a=null;
+  insert into t4 set a=null;
+  insert into t4 set a=null;
+  insert into t4 select null as a;
+  
+  insert into t3 set a=null;
+  insert into t3 set a=null;
+  
+  select * from t3;
+end|
+
+call bug14304()|
+
+drop procedure bug14304|
+drop table t3, t4|
 
 #
 # BUG#14376: MySQL crash on scoped variable (re)initialization

--- 1.26/sql/sp_pcontext.cc	2005-12-02 14:30:35 +01:00
+++ 1.27/sql/sp_pcontext.cc	2005-12-02 14:58:50 +01:00
@@ -169,6 +169,28 @@
   return NULL;
 }
 
+/*
+  Find a variable by offset from the top.
+  This used for two things:
+  - When evaluating parameters at the beginning, and setting out parameters
+    at the end, of invokation. (Top frame only, so no recursion then.)
+  - For printing of sp_instr_set. (Debug mode only.)
+ */
+sp_pvar_t *
+sp_pcontext::find_pvar(uint offset)
+{
+  if (m_poffset <= offset && offset < m_poffset + m_pvar.elements)
+  {                           // This frame
+    sp_pvar_t *p;
+
+    get_dynamic(&m_pvar, (gptr)&p, offset - m_poffset);
+    return p;
+  }
+  if (m_parent)
+    return m_parent->find_pvar(offset); // Some previous frame
+  return NULL;                  // index out of bounds
+}
+
 void
 sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
 		       sp_param_mode_t mode)
@@ -331,3 +353,21 @@
     return m_parent->find_cursor(name, poff, scoped);
   return FALSE;
 }
+
+/*
+  Find a cursor by offset from the top.
+  This is only used for debugging.
+ */
+my_bool
+sp_pcontext::find_cursor(uint offset, LEX_STRING *n)
+{
+  if (m_coffset <= offset && offset < m_coffset + m_cursor.elements)
+  {                           // This frame
+    get_dynamic(&m_cursor, (gptr)n, offset - m_coffset);
+    return TRUE;
+  }
+  if (m_parent)
+    return m_parent->find_cursor(offset, n); // Some previous frame
+  return FALSE;                 // index out of bounds
+}
+

--- 1.23/sql/sp_pcontext.h	2005-12-02 14:30:35 +01:00
+++ 1.24/sql/sp_pcontext.h	2005-12-02 15:04:43 +01:00
@@ -170,18 +170,9 @@
   sp_pvar_t *
   find_pvar(LEX_STRING *name, my_bool scoped=0);
 
-  // Find by index
+  // Find by offset
   sp_pvar_t *
-  find_pvar(uint i)
-  {
-    sp_pvar_t *p;
-
-    if (i < m_pvar.elements)
-      get_dynamic(&m_pvar, (gptr)&p, i);
-    else
-      p= NULL;
-    return p;
-  }
+  find_pvar(uint offset);
 
   /*
     Set the current scope boundary (for default values)
@@ -270,6 +261,10 @@
 
   my_bool
   find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0);
+
+  /* Find by offset (for debugging only) */
+  my_bool
+  find_cursor(uint offset, LEX_STRING *n);
 
   inline uint
   max_cursors()
Thread
bk commit into 5.0 tree (pem:1.2043)pem2 Dec