List:Internals« Previous MessageNext Message »
From:sanja Date:November 22 2005 11:29pm
Subject:bk commit into 5.0 tree (bell:1.1995)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of bell. When bell 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.1995 05/11/23 01:29:25 bell@stripped +1 -0
  merge

  sql/sp.cc
    1.101 05/11/23 01:29:21 bell@stripped +8 -2
    merge

# 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:	bell
# Host:	sanja.is.com.ua
# Root:	/home/bell/mysql/bk/work-merge-5.0/RESYNC

--- 1.100/sql/sp.cc	2005-11-23 00:51:48 +02:00
+++ 1.101/sql/sp.cc	2005-11-23 01:29:21 +02:00
@@ -29,6 +29,11 @@
 	      const char *returns, ulong returnslen,
 	      const char *body, ulong bodylen,
 	      st_sp_chistics *chistics);
+static int
+db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
+                ulong sql_mode, const char *params, const char *returns,
+                const char *body, st_sp_chistics &chistics,
+                const char *definer, longlong created, longlong modified);
 
 /*
  *
@@ -377,87 +382,84 @@
   close_proc_table(thd, &open_tables_state_backup);
   table= 0;
 
-  {
-    String defstr;
-    LEX *oldlex= thd->lex;
-    sp_rcontext *save_spcont= thd->spcont;
-    char olddb[128];
-    bool dbchanged;
-    enum enum_sql_command oldcmd= thd->lex->sql_command;
-    ulong old_sql_mode= thd->variables.sql_mode;
-    ha_rows select_limit= thd->variables.select_limit;
-
-    thd->variables.sql_mode= sql_mode;
-    thd->variables.select_limit= HA_POS_ERROR;
-
-    defstr.set_charset(system_charset_info);
-    if (!create_string(thd, &defstr,
-		       type,
-		       name,
-		       params, strlen(params),
-		       returns, strlen(returns),
-		       body, strlen(body),
-		       &chistics))
-    {
-      ret= SP_INTERNAL_ERROR;
-      goto done;
-    }
+  ret= db_load_routine(thd, type, name, sphp,
+                       sql_mode, params, returns, body, chistics,
+                       definer, created, modified);
+                       
+ done:
+  if (table)
+    close_proc_table(thd, &open_tables_state_backup);
+  DBUG_RETURN(ret);
+}
 
-    dbchanged= FALSE;
-    if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb),
-			    1, &dbchanged)))
-      goto done;
 
-    {
-      /* This is something of a kludge. We need to initialize some fields
-       * in thd->lex (the unit and master stuff), and the easiest way to
-       * do it is, is to call mysql_init_query(), but this unfortunately
-       * resets teh value_list where we keep the CALL parameters. So we
-       * copy the list and then restore it. (... and found_semicolon too).
-       */
-      List<Item> tmpvals= thd->lex->value_list;
-      char *tmpfsc= thd->lex->found_semicolon;
-
-      lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length());
-      thd->lex->value_list= tmpvals;
-      thd->lex->found_semicolon= tmpfsc;
-    }
+static int
+db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
+                ulong sql_mode, const char *params, const char *returns,
+                const char *body, st_sp_chistics &chistics,
+                const char *definer, longlong created, longlong modified)
+{
+  LEX *oldlex= thd->lex, newlex;
+  sp_rcontext *save_spcont= ;thd->spcont;
+  String defstr;
+  char olddb[128];
+  bool dbchanged;
+  ulong old_sql_mode= thd->variables.sql_mode;
+  ha_rows select_limit= thd->variables.select_limit;
+  int ret= SP_INTERNAL_ERROR;
+
+  thd->variables.sql_mode= sql_mode;
+  thd->variables.select_limit= HA_POS_ERROR;
+
+  thd->lex= &newlex;
+  newlex.current_select= NULL;
+
+  defstr.set_charset(system_charset_info);
+  if (!create_string(thd, &defstr,
+		     type,
+		     name,
+		     params, strlen(params),
+		     returns, strlen(returns),
+		     body, strlen(body),
+		     &chistics))
+    goto end;
 
-    thd->spcont= 0;
-    if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
-    {
-      LEX *newlex= thd->lex;
-      sp_head *sp= newlex->sphead;
+  dbchanged= FALSE;
+  if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb),
+			  1, &dbchanged)))
+    goto end;
+
+  lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length());
 
-      if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
-	goto done;
-      if (sp)
-      {
-	delete sp;
-	newlex->sphead= NULL;
-      }
-      ret= SP_PARSE_ERROR;
-    }
-    else
-    {
-      if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
-	goto db_done;
-      *sphp= thd->lex->sphead;
       (*sphp)->set_definer((char*) definer, (uint) strlen(definer));
       (*sphp)->set_info(created, modified, &chistics, sql_mode);
-      (*sphp)->optimize();
-    }
-db_done:
-    thd->spcont= save_spcont;
-    thd->lex->sql_command= oldcmd;
-    thd->variables.sql_mode= old_sql_mode;
-    thd->variables.select_limit= select_limit;
-  }
+  thd->spcont= 0;
+  if (yyparse(thd) || thd->is_fatal_error || newlex.sphead == NULL)
+  {
+    sp_head *sp= newlex.sphead;
 
- done:
-  if (table)
-    close_proc_table(thd, &open_tables_state_backup);
-  DBUG_RETURN(ret);
+    if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
+      goto end;
+    delete sp;
+    ret= SP_PARSE_ERROR;
+  }
+  else
+  {
+    if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
+      goto db_end;
+    *sphp= newlex.sphead;
+    (*sphp)->set_definer((char*) definer, (uint) strlen(definer));
+    (*sphp)->set_info((char *)definer, (uint)strlen(definer),
+		      created, modified, &chistics, sql_mode);
+    (*sphp)->optimize();
+  }
+db_end:
+  thd->spcont= save_spcont;
+  thd->variables.sql_mode= old_sql_mode;
+  thd->variables.select_limit= select_limit;
+end:  
+  thd->lex= oldlex;
+  return ret;
 }
 
 
@@ -903,45 +905,106 @@
 ******************************************************************************/
 
 /*
-  Obtain object representing stored procedure by its name from
+  Obtain object representing stored procedure/function by its name from
   stored procedures cache and looking into mysql.proc if needed.
 
   SYNOPSIS
-    sp_find_procedure()
+    sp_find_routine()
       thd        - thread context
+      type       - type of object (TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE)
       name       - name of procedure
+      cp         - hash to look routine in
       cache_only - if true perform cache-only lookup
                    (Don't look in mysql.proc).
 
-  TODO
-    We should consider merging of sp_find_procedure() and
-    sp_find_function() into one sp_find_routine() function
-    (the same applies to other similarly paired functions).
-
   RETURN VALUE
     Non-0 pointer to sp_head object for the procedure, or
     0 - in case of error.
 */
 
 sp_head *
-sp_find_procedure(THD *thd, sp_name *name, bool cache_only)
+sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp,
+                bool cache_only)
 {
   sp_head *sp;
-  DBUG_ENTER("sp_find_procedure");
-  DBUG_PRINT("enter", ("name: %.*s.%.*s",
-		       name->m_db.length, name->m_db.str,
-		       name->m_name.length, name->m_name.str));
-
-  if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name)) && !cache_only)
+  ulong depth= (type == TYPE_ENUM_PROCEDURE ?
+                thd->variables.max_sp_recursion_depth :
+                0);
+
+  DBUG_ENTER("sp_find_routine");
+  DBUG_PRINT("enter", ("name:  %.*s.%.*s, type: %d, cache only %d",
+                       name->m_db.length, name->m_db.str,
+                       name->m_name.length, name->m_name.str,
+                       type, cache_only));
+
+  if ((sp= sp_cache_lookup(cp, name)))
+  {
+    ulong level;
+    DBUG_PRINT("info", ("found: 0x%lx", (ulong)sp));
+    if (sp->m_first_free_instance)
+    {
+      DBUG_PRINT("info", ("first free: 0x%lx, level: %lu, flags %x",
+                          (ulong)sp->m_first_free_instance,
+                          sp->m_first_free_instance->m_recursion_level,
+                          sp->m_first_free_instance->m_flags));
+      DBUG_ASSERT(!(sp->m_first_free_instance->m_flags & sp_head::IS_INVOKED));
+      if (sp->m_first_free_instance->m_recursion_level > depth)
+      {
+        sp->recursion_level_error();
+        DBUG_RETURN(0);
+      }
+      DBUG_RETURN(sp->m_first_free_instance);
+    }
+    level= sp->m_last_cached_sp->m_recursion_level + 1;
+    if (level > depth)
+    {
+      sp->recursion_level_error();
+      DBUG_RETURN(0);
+    }
+    {
+      sp_head *new_sp;
+      const char *returns= "";
+      char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
+      String retstr(64);
+      strxmov(definer, sp->m_definer_user.str, "@",
+                       sp->m_definer_host.str, NullS);
+      if (type == TYPE_ENUM_FUNCTION)
+      {
+        sp_returns_type(thd, retstr, sp);
+        returns= retstr.ptr();
+      }
+      if (db_load_routine(thd, type, name, &new_sp,
+                          sp->m_sql_mode, sp->m_params.str, returns,
+                          sp->m_body.str, *sp->m_chistics, definer,
+                          sp->m_created, sp->m_modified) == SP_OK)
+      {
+        sp->m_last_cached_sp->m_next_cached_sp= new_sp;
+        new_sp->m_recursion_level= level;
+        new_sp->m_first_instance= sp;
+        sp->m_last_cached_sp= sp->m_first_free_instance= new_sp;
+        DBUG_PRINT("info", ("added level: 0x%lx, level: %lu, flags %x",
+                          (ulong)new_sp, new_sp->m_recursion_level,
+                          new_sp->m_flags));
+        DBUG_RETURN(new_sp);
+      }
+      DBUG_RETURN(0);
+    }
+  }
+  if (!cache_only)
   {
-    if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, name, &sp) == SP_OK)
-      sp_cache_insert(&thd->sp_proc_cache, sp);
+    if (db_find_routine(thd, type, name, &sp) == SP_OK)
+    {
+      sp_cache_insert(cp, sp);
+      DBUG_PRINT("info", ("added new: 0x%lx, level: %lu, flags %x",
+                          (ulong)sp, sp->m_recursion_level,
+                          sp->m_flags));
+    }
   }
-
   DBUG_RETURN(sp);
 }
 
 
+
 int
 sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
 {
@@ -959,8 +1022,10 @@
     lex_name.str= thd->strmake(table->table_name, lex_name.length);
     name= new sp_name(lex_db, lex_name);
     name->init_qname(thd);
-    if (sp_find_procedure(thd, name) != NULL ||
-        sp_find_function(thd, name) != NULL)
+    if (sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name,
+                        &thd->sp_proc_cache, FALSE) != NULL ||
+        sp_find_routine(thd, TYPE_ENUM_FUNCTION, name,
+                        &thd->sp_func_cache, FALSE) != NULL)
     {
       if (any)
         DBUG_RETURN(1);
@@ -1028,7 +1093,8 @@
   DBUG_ENTER("sp_show_create_procedure");
   DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str));
 
-  if ((sp= sp_find_procedure(thd, name)))
+  if ((sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name,
+                           &thd->sp_proc_cache, FALSE)))
   {
     int ret= sp->show_create_procedure(thd);
 
@@ -1054,42 +1120,6 @@
   FUNCTION
 ******************************************************************************/
 
-/*
-  Obtain object representing stored function by its name from
-  stored functions cache and looking into mysql.proc if needed.
-
-  SYNOPSIS
-    sp_find_function()
-      thd        - thread context
-      name       - name of function
-      cache_only - if true perform cache-only lookup
-                   (Don't look in mysql.proc).
-
-  NOTE
-    See TODO section for sp_find_procedure().
-
-  RETURN VALUE
-    Non-0 pointer to sp_head object for the function, or
-    0 - in case of error.
-*/
-
-sp_head *
-sp_find_function(THD *thd, sp_name *name, bool cache_only)
-{
-  sp_head *sp;
-  DBUG_ENTER("sp_find_function");
-  DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str));
-
-  if (!(sp= sp_cache_lookup(&thd->sp_func_cache, name)) &&
-      !cache_only)
-  {
-    if (db_find_routine(thd, TYPE_ENUM_FUNCTION, name, &sp) == SP_OK)
-      sp_cache_insert(&thd->sp_func_cache, sp);
-  }
-  DBUG_RETURN(sp);
-}
-
-
 int
 sp_create_function(THD *thd, sp_head *sp)
 {
@@ -1137,7 +1167,8 @@
   DBUG_ENTER("sp_show_create_function");
   DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str));
 
-  if ((sp= sp_find_function(thd, name)))
+  if ((sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, name,
+                           &thd->sp_func_cache, FALSE)))
   {
     int ret= sp->show_create_function(thd);
 
@@ -1447,10 +1478,6 @@
                               &thd->sp_func_cache : &thd->sp_proc_cache),
                               &name)))
     {
-      LEX *oldlex= thd->lex;
-      LEX *newlex= new st_lex;
-      thd->lex= newlex;
-      newlex->current_select= NULL;
       name.m_name.str= strchr(name.m_qname.str, '.');
       name.m_db.length= name.m_name.str - name.m_qname.str;
       name.m_db.str= strmake_root(thd->mem_root, name.m_qname.str,
@@ -1465,8 +1492,6 @@
         else
           sp_cache_insert(&thd->sp_proc_cache, sp);
       }
-      delete newlex;
-      thd->lex= oldlex;
     }
     if (sp)
     {
Thread
bk commit into 5.0 tree (bell:1.1995)sanja23 Nov