List:Commits« Previous MessageNext Message »
From:Chad MILLER Date:January 3 2007 10:15pm
Subject:bk commit into 5.0 tree (cmiller:1.2326)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of cmiller. When cmiller does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-01-03 17:15:10-05:00, cmiller@stripped +33 -0
  Bug#24795: Add SHOW PROFILE
  
  
  Add rudimentary query profiling support.

  BitKeeper/etc/collapsed@stripped, 2007-01-03 17:13:00-05:00, cmiller@stripped +3 -0

  libmysqld/Makefile.am@stripped, 2007-01-03 17:15:06-05:00, cmiller@stripped +1 -0
    Add profile file to source list.

  mysql-test/r/profile.result@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +30 -0
    Test profiling code.
    ---
    A not-very-useful result.

  mysql-test/r/profile.result@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +0 -0

  mysql-test/t/profile.test@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +39 -0
    Test profiling code.
    ---
    Test syntax, but not values of profiles code.

  mysql-test/t/profile.test@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +0 -0

  sql/Makefile.am@stripped, 2007-01-03 17:15:06-05:00, cmiller@stripped +2 -0
    Add profiling files to source and header lists.

  sql/ha_archive.cc@stripped, 2007-01-03 17:15:06-05:00, cmiller@stripped +2 -2
    Macro-ized other discovered instances of setting proc_info.

  sql/ha_myisam.cc@stripped, 2007-01-03 17:15:06-05:00, cmiller@stripped +12 -12
    Macroize setting thread-state info

  sql/item_func.cc@stripped, 2007-01-03 17:15:06-05:00, cmiller@stripped +4 -4
    Macro-ized other discovered instances of setting proc_info.

  sql/lex.h@stripped, 2007-01-03 17:15:06-05:00, cmiller@stripped +13 -0
    Add lexer info for profiling.

  sql/lock.cc@stripped, 2007-01-03 17:15:06-05:00, cmiller@stripped +4 -4
    Macroize setting thread-state info

  sql/log_event.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +4 -4
    Macro-ized other discovered instances of setting proc_info.

  sql/mysql_priv.h@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +4 -0
    Set constants for profiling.

  sql/repl_failsafe.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +3 -3
    Macro-ized other discovered instances of setting proc_info.

  sql/slave.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +3 -3
    Macro-ized other discovered instances of setting proc_info.

  sql/sp_head.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +2 -2
    Macro-ized other discovered instances of setting proc_info.

  sql/sql_base.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +12 -12
    Macroize setting thread-state info
    ---
    Macro-ized other discovered instances of setting proc_info.

  sql/sql_cache.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +12 -0
    Macroize setting thread-state info

  sql/sql_class.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +2 -0
    Integrate profiling.

  sql/sql_class.h@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +3 -0
    Instantiate profiling object.

  sql/sql_delete.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +6 -6
    Macroize setting thread-state info

  sql/sql_insert.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +19 -19
    Macroize setting thread-state info
    ---
    Macro-ized other discovered instances of setting proc_info.

  sql/sql_lex.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +1 -0
    Initialize profiling.

  sql/sql_lex.h@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +3 -0
    Define lex tokens and allocate space for profiling options.

  sql/sql_parse.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +28 -12
    Integrate profiling.
    ---
    Macro-ized other discovered instances of setting proc_info.

  sql/sql_profile.cc@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +441 -0
    Add profiling code.
    ---
    Add wishlist comment.

  sql/sql_profile.cc@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +0 -0

  sql/sql_profile.h@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +187 -0
    Add profiling code.
    ---
    Changed the value of the macro so that it's syntactically equivalent to a
    single statement.

  sql/sql_profile.h@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +0 -0

  sql/sql_repl.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +1 -1
    Macro-ized other discovered instances of setting proc_info.

  sql/sql_select.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +43 -30
    Macroize setting thread-state info.
    
    Clean up some lines.

  sql/sql_show.cc@stripped, 2007-01-03 17:15:07-05:00, cmiller@stripped +1 -1
    Macro-ized other discovered instances of setting proc_info.
    ---
    Revert bad use of macro.

  sql/sql_table.cc@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +10 -10
    Macroize setting thread-state info

  sql/sql_update.cc@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +7 -7
    Macroize setting thread-state info

  sql/sql_view.cc@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +1 -1
    Macro-ized other discovered instances of setting proc_info.

  sql/sql_yacc.yy@stripped, 2007-01-03 17:15:08-05:00, cmiller@stripped +73 -1
    Add parser info for profiling.
    ---
    Fix new YACC shift/reduce conflict.  (Now at 249.)

# 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:	cmiller
# Host:	zippy.cornsilk.net
# Root:	/home/cmiller/work/mysql/mysql-5.0-community--bug24795

--- 1.128/sql/Makefile.am	2007-01-03 17:15:17 -05:00
+++ 1.129/sql/Makefile.am	2007-01-03 17:15:17 -05:00
@@ -52,6 +52,7 @@ noinst_HEADERS =	item.h item_func.h item
 			procedure.h sql_class.h sql_lex.h sql_list.h \
 			sql_manager.h sql_map.h sql_string.h unireg.h \
 			sql_error.h field.h handler.h mysqld_suffix.h \
+ 			sql_profile.h \
 			ha_myisammrg.h\
 			ha_heap.h ha_myisam.h ha_berkeley.h ha_innodb.h \
 			ha_ndbcluster.h opt_range.h protocol.h \
@@ -80,6 +81,7 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.
 			set_var.cc sql_parse.cc sql_yacc.yy \
 			sql_base.cc table.cc sql_select.cc sql_insert.cc \
                         sql_prepare.cc sql_error.cc sql_locale.cc \
+			sql_profile.cc \
 			sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
 			procedure.cc item_uniq.cc sql_test.cc \
 			log.cc log_event.cc init.cc derror.cc sql_acl.cc \

--- 1.170/sql/ha_myisam.cc	2007-01-03 17:15:17 -05:00
+++ 1.171/sql/ha_myisam.cc	2007-01-03 17:15:17 -05:00
@@ -340,7 +340,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_
   MYISAM_SHARE* share = file->s;
   const char *old_proc_info=thd->proc_info;
 
-  thd->proc_info="Checking table";
+  THD_PROC_INFO(thd, "Checking table");
   myisamchk_init(&param);
   param.thd = thd;
   param.op_name =   "check";
@@ -414,7 +414,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_
     file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
   }
 
-  thd->proc_info=old_proc_info;
+  THD_PROC_INFO(thd, old_proc_info);
   return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
 }
 
@@ -680,22 +680,22 @@ int ha_myisam::repair(THD *thd, MI_CHECK
         char buf[40];
         /* TODO: respect myisam_repair_threads variable */
         my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
-        thd->proc_info=buf;
+        THD_PROC_INFO(thd, buf);
         error = mi_repair_parallel(&param, file, fixed_name,
             param.testflag & T_QUICK);
-        thd->proc_info="Repair done"; // to reset proc_info, as
+        THD_PROC_INFO(thd, "Repair done"); // to reset proc_info, as
                                       // it was pointing to local buffer
       }
       else
       {
-        thd->proc_info="Repair by sorting";
+        THD_PROC_INFO(thd, "Repair by sorting");
         error = mi_repair_by_sort(&param, file, fixed_name,
             param.testflag & T_QUICK);
       }
     }
     else
     {
-      thd->proc_info="Repair with keycache";
+      THD_PROC_INFO(thd, "Repair with keycache");
       param.testflag &= ~T_REP_BY_SORT;
       error=  mi_repair(&param, file, fixed_name,
 			param.testflag & T_QUICK);
@@ -709,7 +709,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK
 	(share->state.changed & STATE_NOT_SORTED_PAGES))
     {
       optimize_done=1;
-      thd->proc_info="Sorting index";
+      THD_PROC_INFO(thd, "Sorting index");
       error=mi_sort_index(&param,file,fixed_name);
     }
     if (!statistics_done && (local_testflag & T_STATISTICS))
@@ -717,14 +717,14 @@ int ha_myisam::repair(THD *thd, MI_CHECK
       if (share->state.changed & STATE_NOT_ANALYZED)
       {
 	optimize_done=1;
-	thd->proc_info="Analyzing";
+	THD_PROC_INFO(thd, "Analyzing");
 	error = chk_key(&param, file);
       }
       else
 	local_testflag&= ~T_STATISTICS;		// Don't update statistics
     }
   }
-  thd->proc_info="Saving state";
+  THD_PROC_INFO(thd, "Saving state");
   if (!error)
   {
     if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
@@ -762,7 +762,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK
     file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
     update_state_info(&param, file, 0);
   }
-  thd->proc_info=old_proc_info;
+  THD_PROC_INFO(thd, old_proc_info);
   if (!thd->locked_tables)
     mi_lock_database(file,F_UNLCK);
   DBUG_RETURN(error ? HA_ADMIN_FAILED :
@@ -987,7 +987,7 @@ int ha_myisam::enable_indexes(uint mode)
     THD *thd=current_thd;
     MI_CHECK param;
     const char *save_proc_info=thd->proc_info;
-    thd->proc_info="Creating index";
+    THD_PROC_INFO(thd, "Creating index");
     myisamchk_init(&param);
     param.op_name= "recreating_index";
     param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
@@ -1012,7 +1012,7 @@ int ha_myisam::enable_indexes(uint mode)
         thd->clear_error();
     }
     info(HA_STATUS_CONST);
-    thd->proc_info=save_proc_info;
+    THD_PROC_INFO(thd, save_proc_info);
   }
   else
   {

--- 1.316/sql/item_func.cc	2007-01-03 17:15:17 -05:00
+++ 1.317/sql/item_func.cc	2007-01-03 17:15:17 -05:00
@@ -3193,7 +3193,7 @@ void debug_sync_point(const char* lock_n
     Structure is now initialized.  Try to get the lock.
     Set up control struct to allow others to abort locks
   */
-  thd->proc_info="User lock";
+  THD_PROC_INFO(thd, "User lock");
   thd->mysys_var->current_mutex= &LOCK_user_locks;
   thd->mysys_var->current_cond=  &ull->cond;
 
@@ -3218,7 +3218,7 @@ void debug_sync_point(const char* lock_n
   }
   pthread_mutex_unlock(&LOCK_user_locks);
   pthread_mutex_lock(&thd->mysys_var->mutex);
-  thd->proc_info=0;
+  THD_PROC_INFO(thd, 0);
   thd->mysys_var->current_mutex= 0;
   thd->mysys_var->current_cond=  0;
   pthread_mutex_unlock(&thd->mysys_var->mutex);
@@ -3299,7 +3299,7 @@ longlong Item_func_get_lock::val_int()
     Structure is now initialized.  Try to get the lock.
     Set up control struct to allow others to abort locks.
   */
-  thd->proc_info="User lock";
+  THD_PROC_INFO(thd, "User lock");
   thd->mysys_var->current_mutex= &LOCK_user_locks;
   thd->mysys_var->current_cond=  &ull->cond;
 
@@ -3337,7 +3337,7 @@ longlong Item_func_get_lock::val_int()
   pthread_mutex_unlock(&LOCK_user_locks);
 
   pthread_mutex_lock(&thd->mysys_var->mutex);
-  thd->proc_info=0;
+  THD_PROC_INFO(thd, 0);
   thd->mysys_var->current_mutex= 0;
   thd->mysys_var->current_cond=  0;
   pthread_mutex_unlock(&thd->mysys_var->mutex);

--- 1.144/sql/lex.h	2007-01-03 17:15:17 -05:00
+++ 1.145/sql/lex.h	2007-01-03 17:15:17 -05:00
@@ -88,6 +88,7 @@ static SYMBOL symbols[] = {
   { "BINLOG",		SYM(BINLOG_SYM)},
   { "BIT",		SYM(BIT_SYM)},
   { "BLOB",		SYM(BLOB_SYM)},
+  { "BLOCK",  SYM(BLOCK_SYM)},
   { "BOOL",		SYM(BOOL_SYM)},
   { "BOOLEAN",		SYM(BOOLEAN_SYM)},
   { "BOTH",		SYM(BOTH)},
@@ -126,8 +127,10 @@ static SYMBOL symbols[] = {
   { "CONSISTENT",	SYM(CONSISTENT_SYM)},
   { "CONSTRAINT",	SYM(CONSTRAINT)},
   { "CONTAINS",         SYM(CONTAINS_SYM)},
+  { "CONTEXT",    SYM(CONTEXT_SYM)},
   { "CONTINUE",         SYM(CONTINUE_SYM)},
   { "CONVERT",		SYM(CONVERT_SYM)},
+  { "CPU",        SYM(CPU_SYM)},
   { "CREATE",		SYM(CREATE)},
   { "CROSS",		SYM(CROSS)},
   { "CUBE",		SYM(CUBE_SYM)},
@@ -193,6 +196,7 @@ static SYMBOL symbols[] = {
   { "EXTENDED",		SYM(EXTENDED_SYM)},
   { "FALSE",		SYM(FALSE_SYM)},
   { "FAST",		SYM(FAST_SYM)},
+  { "FAULTS",  SYM(FAULTS_SYM)},
   { "FETCH",            SYM(FETCH_SYM)},
   { "FIELDS",		SYM(COLUMNS)},
   { "FILE",		SYM(FILE_SYM)},
@@ -252,7 +256,9 @@ static SYMBOL symbols[] = {
   { "INTEGER",		SYM(INT_SYM)},
   { "INTERVAL",		SYM(INTERVAL_SYM)},
   { "INTO",		SYM(INTO)},
+  { "IO",     SYM(IO_SYM)},
   { "IO_THREAD",        SYM(RELAY_THREAD)},
+  { "IPC",    SYM(IPC_SYM)},
   { "IS",		SYM(IS)},
   { "ISOLATION",	SYM(ISOLATION)},
   { "ISSUER",		SYM(ISSUER_SYM)},
@@ -310,6 +316,7 @@ static SYMBOL symbols[] = {
   { "MEDIUMBLOB",	SYM(MEDIUMBLOB)},
   { "MEDIUMINT",	SYM(MEDIUMINT)},
   { "MEDIUMTEXT",	SYM(MEDIUMTEXT)},
+  { "MEMORY",     SYM(MEMORY_SYM)},
   { "MERGE",		SYM(MERGE_SYM)},
   { "MICROSECOND",	SYM(MICROSECOND_SYM)},
   { "MIDDLEINT",	SYM(MEDIUMINT)},	/* For powerbuilder */
@@ -357,6 +364,7 @@ static SYMBOL symbols[] = {
   { "OUT",              SYM(OUT_SYM)},
   { "OUTER",		SYM(OUTER)},
   { "OUTFILE",		SYM(OUTFILE)},
+  { "PAGE",		SYM(PAGE_SYM)},
   { "PACK_KEYS",	SYM(PACK_KEYS_SYM)},
   { "PARTIAL",		SYM(PARTIAL)},
   { "PASSWORD",		SYM(PASSWORD)},
@@ -371,6 +379,8 @@ static SYMBOL symbols[] = {
   { "PROCEDURE",	SYM(PROCEDURE)},
   { "PROCESS"	,	SYM(PROCESS)},
   { "PROCESSLIST",	SYM(PROCESSLIST_SYM)},
+  { "PROFILE",    SYM(PROFILE_SYM)},
+  { "PROFILES",   SYM(PROFILES_SYM)},
   { "PURGE",		SYM(PURGE)},
   { "QUARTER",          SYM(QUARTER_SYM)},
   { "QUERY",		SYM(QUERY_SYM)},
@@ -438,6 +448,7 @@ static SYMBOL symbols[] = {
   { "SOME",             SYM(ANY_SYM)},
   { "SONAME",		SYM(UDF_SONAME_SYM)},
   { "SOUNDS",		SYM(SOUNDS_SYM)},
+  { "SOURCE",   SYM(SOURCE_SYM)},
   { "SPATIAL",		SYM(SPATIAL_SYM)},
   { "SPECIFIC",         SYM(SPECIFIC_SYM)},
   { "SQL",              SYM(SQL_SYM)},
@@ -472,6 +483,8 @@ static SYMBOL symbols[] = {
   { "SUBJECT",		SYM(SUBJECT_SYM)},
   { "SUPER",		SYM(SUPER_SYM)},
   { "SUSPEND",          SYM(SUSPEND_SYM)},
+  { "SWAPS",      SYM(SWAPS_SYM)},
+  { "SWITCHES",   SYM(SWITCHES_SYM)},
   { "TABLE",		SYM(TABLE_SYM)},
   { "TABLES",		SYM(TABLES)},
   { "TABLESPACE",	SYM(TABLESPACE)},

--- 1.90/sql/lock.cc	2007-01-03 17:15:17 -05:00
+++ 1.91/sql/lock.cc	2007-01-03 17:15:17 -05:00
@@ -151,7 +151,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, 
       }
     }
 
-    thd->proc_info="System lock";
+    THD_PROC_INFO(thd, "System lock");
     if (lock_external(thd, tables, count))
     {
       /* Clear the lock type of all lock data to avoid reusage. */
@@ -160,7 +160,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, 
       sql_lock=0;
       break;
     }
-    thd->proc_info="Table lock";
+    THD_PROC_INFO(thd, "Table lock");
     thd->locked=1;
     /* Copy the lock data array. thr_multi_lock() reorders its contens. */
     memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
@@ -194,7 +194,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, 
       thd->locked=0;
       break;
     }
-    thd->proc_info=0;
+    THD_PROC_INFO(thd, 0);
 
     /* some table was altered or deleted. reopen tables marked deleted */
     mysql_unlock_tables(thd,sql_lock);
@@ -209,7 +209,7 @@ retry:
     if (wait_for_tables(thd))
       break;					// Couldn't open tables
   }
-  thd->proc_info=0;
+  THD_PROC_INFO(thd, 0);
   if (thd->killed)
   {
     thd->send_kill_message();

--- 1.216/sql/log_event.cc	2007-01-03 17:15:17 -05:00
+++ 1.217/sql/log_event.cc	2007-01-03 17:15:17 -05:00
@@ -4266,7 +4266,7 @@ int Create_file_log_event::exec_event(st
   bzero((char*)&file, sizeof(file));
   fname_buf= strmov(proc_info, "Making temp file ");
   ext= slave_load_file_stem(fname_buf, file_id, server_id, ".info");
-  thd->proc_info= proc_info;
+  THD_PROC_INFO(thd, proc_info);
   my_delete(fname_buf, MYF(0)); // old copy may exist already
   if ((fd= my_create(fname_buf, CREATE_MODE,
 		     O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
@@ -4320,7 +4320,7 @@ err:
     end_io_cache(&file);
   if (fd >= 0)
     my_close(fd, MYF(0));
-  thd->proc_info= 0;
+  THD_PROC_INFO(thd, 0);
   return error ? 1 : Log_event::exec_event(rli);
 }
 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
@@ -4440,7 +4440,7 @@ int Append_block_log_event::exec_event(s
 
   fname= strmov(proc_info, "Making temp file ");
   slave_load_file_stem(fname, file_id, server_id, ".data");
-  thd->proc_info= proc_info;
+  THD_PROC_INFO(thd, proc_info);
   if (get_create_or_append())
   {
     my_delete(fname, MYF(0)); // old copy may exist already
@@ -4474,7 +4474,7 @@ int Append_block_log_event::exec_event(s
 err:
   if (fd >= 0)
     my_close(fd, MYF(0));
-  thd->proc_info= 0;
+  THD_PROC_INFO(thd, 0);
   DBUG_RETURN(error ? error : Log_event::exec_event(rli));
 }
 #endif

--- 1.424/sql/mysql_priv.h	2007-01-03 17:15:17 -05:00
+++ 1.425/sql/mysql_priv.h	2007-01-03 17:15:17 -05:00
@@ -174,6 +174,8 @@ MY_LOCALE *my_locale_by_name(const char 
 #define BDB_LOG_ALLOC_BLOCK_SIZE	1024
 #define WARN_ALLOC_BLOCK_SIZE		2048
 #define WARN_ALLOC_PREALLOC_SIZE	1024
+#define PROFILE_ALLOC_BLOCK_SIZE  2048
+#define PROFILE_ALLOC_PREALLOC_SIZE 1024
 
 /*
   The following parameters is to decide when to use an extra cache to
@@ -542,6 +544,8 @@ typedef my_bool (*qc_engine_callback)(TH
 #include "field.h"				/* Field definitions */
 #include "protocol.h"
 #include "sql_udf.h"
+#include "sql_profile.h"
+
 class user_var_entry;
 class Security_context;
 enum enum_var_type

--- 1.286/sql/slave.cc	2007-01-03 17:15:17 -05:00
+++ 1.287/sql/slave.cc	2007-01-03 17:15:17 -05:00
@@ -2925,9 +2925,9 @@ static int init_slave_thread(THD* thd, S
 #endif
 
   if (thd_type == SLAVE_THD_SQL)
-    thd->proc_info= "Waiting for the next event in relay log";
+    THD_PROC_INFO(thd, "Waiting for the next event in relay log");
   else
-    thd->proc_info= "Waiting for master update";
+    THD_PROC_INFO(thd, "Waiting for master update");
   thd->version=refresh_version;
   thd->set_time();
   DBUG_RETURN(0);
@@ -3546,7 +3546,7 @@ dump");
       }
 
       mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
-      thd->proc_info= "Waiting to reconnect after a failed binlog dump request";
+      THD_PROC_INFO(thd, "Waiting to reconnect after a failed binlog dump request");
 #ifdef SIGNAL_WITH_VIO_CLOSE
       thd->clear_active_vio();
 #endif

--- 1.358/sql/sql_base.cc	2007-01-03 17:15:17 -05:00
+++ 1.359/sql/sql_base.cc	2007-01-03 17:15:17 -05:00
@@ -309,7 +309,7 @@ bool close_cached_tables(THD *thd, bool 
     */
     thd->mysys_var->current_mutex= &LOCK_open;
     thd->mysys_var->current_cond= &COND_refresh;
-    thd->proc_info="Flushing tables";
+    THD_PROC_INFO(thd, "Flushing tables");
 
     close_old_data_files(thd,thd->open_tables,1,1);
     mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL,
@@ -351,7 +351,7 @@ bool close_cached_tables(THD *thd, bool 
     pthread_mutex_lock(&thd->mysys_var->mutex);
     thd->mysys_var->current_mutex= 0;
     thd->mysys_var->current_cond= 0;
-    thd->proc_info=0;
+    THD_PROC_INFO(thd, 0);
     pthread_mutex_unlock(&thd->mysys_var->mutex);
   }
   DBUG_RETURN(result);
@@ -1065,7 +1065,7 @@ void wait_for_refresh(THD *thd)
   thd->mysys_var->current_mutex= &LOCK_open;
   thd->mysys_var->current_cond= &COND_refresh;
   proc_info=thd->proc_info;
-  thd->proc_info="Waiting for table";
+  THD_PROC_INFO(thd, "Waiting for table");
   if (!thd->killed)
     (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
 
@@ -1073,7 +1073,7 @@ void wait_for_refresh(THD *thd)
   pthread_mutex_lock(&thd->mysys_var->mutex);
   thd->mysys_var->current_mutex= 0;
   thd->mysys_var->current_cond= 0;
-  thd->proc_info= proc_info;
+  THD_PROC_INFO(thd,  proc_info);
   pthread_mutex_unlock(&thd->mysys_var->mutex);
   DBUG_VOID_RETURN;
 }
@@ -1778,7 +1778,7 @@ bool wait_for_tables(THD *thd)
   bool result;
   DBUG_ENTER("wait_for_tables");
 
-  thd->proc_info="Waiting for tables";
+  THD_PROC_INFO(thd, "Waiting for tables");
   pthread_mutex_lock(&LOCK_open);
   while (!thd->killed)
   {
@@ -1794,12 +1794,12 @@ bool wait_for_tables(THD *thd)
   else
   {
     /* Now we can open all tables without any interference */
-    thd->proc_info="Reopen tables";
+    THD_PROC_INFO(thd, "Reopen tables");
     thd->version= refresh_version;
     result=reopen_tables(thd,0,0);
   }
   pthread_mutex_unlock(&LOCK_open);
-  thd->proc_info=0;
+  THD_PROC_INFO(thd, 0);
   DBUG_RETURN(result);
 }
 
@@ -2098,7 +2098,7 @@ int open_tables(THD *thd, TABLE_LIST **s
  restart:
   *counter= 0;
   query_tables_last_own= 0;
-  thd->proc_info="Opening tables";
+  THD_PROC_INFO(thd, "Opening tables");
 
   /*
     If we are not already executing prelocked statement and don't have
@@ -2278,7 +2278,7 @@ process_view_routines:
   }
 
  err:
-  thd->proc_info=0;
+  THD_PROC_INFO(thd, 0);
   free_root(&new_frm_mem, MYF(0));              // Free pre-alloced block
 
   if (query_tables_last_own)
@@ -2352,7 +2352,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST 
   bool refresh;
   DBUG_ENTER("open_ltable");
 
-  thd->proc_info="Opening table";
+  THD_PROC_INFO(thd, "Opening table");
   thd->current_tablenr= 0;
   /* open_ltable can be used only for BASIC TABLEs */
   table_list->required_type= FRMTYPE_TABLE;
@@ -2386,7 +2386,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST 
 	  table= 0;
     }
   }
-  thd->proc_info=0;
+  THD_PROC_INFO(thd, 0);
   DBUG_RETURN(table);
 }
 
@@ -5387,7 +5387,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX *s
     List_iterator<Item_func_match> li(*(select_lex->ftfunc_list));
     Item_func_match *ifm;
     DBUG_PRINT("info",("Performing FULLTEXT search"));
-    thd->proc_info="FULLTEXT initialization";
+    THD_PROC_INFO(thd, "FULLTEXT initialization");
 
     while ((ifm=li++))
       ifm->init_search(no_order);

--- 1.96/sql/sql_cache.cc	2007-01-03 17:15:17 -05:00
+++ 1.97/sql/sql_cache.cc	2007-01-03 17:15:17 -05:00
@@ -670,6 +670,7 @@ void query_cache_insert(NET *net, const 
 void query_cache_abort(NET *net)
 {
   DBUG_ENTER("query_cache_abort");
+  THD *thd= current_thd;
 
   /* See the comment on double-check locking usage above. */
   if (net->query_cache_query == 0)
@@ -688,6 +689,7 @@ void query_cache_abort(NET *net)
                                    net->query_cache_query);
   if (query_block)			// Test if changed by other thread
   {
+    THD_PROC_INFO(thd, "storing result in query cache");
     DUMP(&query_cache);
     BLOCK_LOCK_WR(query_block);
     // The following call will remove the lock on query_block
@@ -725,6 +727,7 @@ void query_cache_end_of_result(THD *thd)
   query_block= ((Query_cache_block*) thd->net.query_cache_query);
   if (query_block)
   {
+    THD_PROC_INFO(thd, "storing result in query cache");
     DUMP(&query_cache);
     BLOCK_LOCK_WR(query_block);
     Query_cache_query *header= query_block->query();
@@ -1089,6 +1092,8 @@ Query_cache::send_result_to_client(THD *
     DBUG_PRINT("qcache", ("No active database"));
   }
 
+  THD_PROC_INFO(thd, "checking query cache for query");
+
   // fill all gaps between fields with 0 to get repeatable key
   bzero(&flags, QUERY_CACHE_FLAGS_SIZE);
   flags.client_long_flag= test(thd->client_capabilities & CLIENT_LONG_FLAG);
@@ -1163,6 +1168,7 @@ sql mode: 0x%lx, sort len: %lu, conncat 
   }
       
   // Check access;
+  THD_PROC_INFO(thd, "checking privileges on cached query");
   block_table= query_block->table(0);
   block_table_end= block_table+query_block->n_tables;
   for (; block_table != block_table_end; block_table++)
@@ -1255,6 +1261,7 @@ sql mode: 0x%lx, sort len: %lu, conncat 
     Send cached result to client
   */
 #ifndef EMBEDDED_LIBRARY
+  THD_PROC_INFO(thd, "sending cached result to client");
   do
   {
     DBUG_PRINT("qcache", ("Results  (len: %lu  used: %lu  headers: %lu)",
@@ -1332,9 +1339,11 @@ void Query_cache::invalidate(THD *thd, T
 
 void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
 {
+  THD *thd= current_thd;
   DBUG_ENTER("Query_cache::invalidate (changed table list)");
   if (tables_used)
   {
+    THD_PROC_INFO(thd, "invalidating query cache entries (table list)");
     STRUCT_LOCK(&structure_guard_mutex);
     if (query_cache_size > 0 && !flush_in_progress)
     {
@@ -1365,9 +1374,11 @@ void Query_cache::invalidate(CHANGED_TAB
 */
 void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
 {
+  THD *thd= current_thd;
   DBUG_ENTER("Query_cache::invalidate_locked_for_write");
   if (tables_used)
   {
+    THD_PROC_INFO(thd, "invalidating query cache entries (table)");
     STRUCT_LOCK(&structure_guard_mutex);
     if (query_cache_size > 0 && !flush_in_progress)
     {
@@ -1417,6 +1428,7 @@ void Query_cache::invalidate(THD *thd, c
   STRUCT_LOCK(&structure_guard_mutex);
   if (query_cache_size > 0 && !flush_in_progress)
   {
+    THD_PROC_INFO(thd, "invalidating query cache entries (key)");
     using_transactions= using_transactions &&
       (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
     if (using_transactions) // used for innodb => has_transactions() is TRUE

--- 1.254/sql/sql_class.cc	2007-01-03 17:15:17 -05:00
+++ 1.255/sql/sql_class.cc	2007-01-03 17:15:17 -05:00
@@ -248,6 +248,7 @@ THD::THD()
   init();
   /* Initialize sub structures */
   init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
+  profiling.set_thd(this);
   user_connect=(USER_CONN *)0;
   hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
 	    (hash_get_key) get_var_key,
@@ -330,6 +331,7 @@ void THD::init_for_queries()
                       variables.trans_alloc_block_size,
                       variables.trans_prealloc_size);
 #endif
+  profiling.reset();
   transaction.xid_state.xid.null();
   transaction.xid_state.in_thd=1;
 }

--- 1.312/sql/sql_class.h	2007-01-03 17:15:17 -05:00
+++ 1.313/sql/sql_class.h	2007-01-03 17:15:17 -05:00
@@ -1309,6 +1309,9 @@ public:
   List	     <MYSQL_ERROR> warn_list;
   uint	     warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
   uint	     total_warn_count;
+  
+  PROFILING  profiling;
+
   /*
     Id of current query. Statement can be reused to execute several queries
     query_id is global in context of the whole MySQL server.

--- 1.187/sql/sql_delete.cc	2007-01-03 17:15:17 -05:00
+++ 1.188/sql/sql_delete.cc	2007-01-03 17:15:17 -05:00
@@ -55,7 +55,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
     table->file->print_error(error, MYF(0));
     DBUG_RETURN(error);
   }
-  thd->proc_info="init";
+  THD_PROC_INFO(thd, "init");
   table->map=1;
 
   if (mysql_prepare_delete(thd, table_list, &conds))
@@ -206,7 +206,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
 
   deleted=0L;
   init_ftfuncs(thd, select_lex, 1);
-  thd->proc_info="updating";
+  THD_PROC_INFO(thd, "updating");
 
   if (table->triggers)
     table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
@@ -262,7 +262,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
   }
   if (thd->killed && !error)
     error= 1;					// Aborted
-  thd->proc_info="end";
+  THD_PROC_INFO(thd,  "end");
   end_read_record(&info);
   free_io_cache(table);				// Will not do any harm
   if (options & OPTION_QUICK)
@@ -486,7 +486,7 @@ multi_delete::prepare(List<Item> &values
   DBUG_ENTER("multi_delete::prepare");
   unit= u;
   do_delete= 1;
-  thd->proc_info="deleting from main table";
+  THD_PROC_INFO(thd, "deleting from main table");
   DBUG_RETURN(0);
 }
 
@@ -750,7 +750,7 @@ int multi_delete::do_deletes()
 
 bool multi_delete::send_eof()
 {
-  thd->proc_info="deleting from reference tables";
+  THD_PROC_INFO(thd, "deleting from reference tables");
 
   /* Does deletes for the last n - 1 tables, returns 0 if ok */
   int local_error= do_deletes();		// returns 0 if success
@@ -759,7 +759,7 @@ bool multi_delete::send_eof()
   local_error= local_error || error;
 
   /* reset used flags */
-  thd->proc_info="end";
+  THD_PROC_INFO(thd, "end");
 
   /*
     We must invalidate the query cache before binlog writing and

--- 1.206/sql/sql_insert.cc	2007-01-03 17:15:17 -05:00
+++ 1.207/sql/sql_insert.cc	2007-01-03 17:15:17 -05:00
@@ -398,7 +398,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   if (res || thd->is_fatal_error)
     DBUG_RETURN(TRUE);
 
-  thd->proc_info="init";
+  THD_PROC_INFO(thd, "init");
   thd->used_tables=0;
   values= its++;
 
@@ -471,7 +471,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
 
   error=0;
   id=0;
-  thd->proc_info="update";
+  THD_PROC_INFO(thd, "update");
   if (duplic != DUP_ERROR || ignore)
     table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
   if (duplic == DUP_REPLACE)
@@ -677,7 +677,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
       thd->lock=0;
     }
   }
-  thd->proc_info="end";
+  THD_PROC_INFO(thd, "end");
   table->next_number_field=0;
   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
   thd->next_insert_id=0;			// Reset this if wrongly used
@@ -1408,7 +1408,7 @@ I_List<delayed_insert> delayed_threads;
 
 delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list)
 {
-  thd->proc_info="waiting for delay_list";
+  THD_PROC_INFO(thd, "waiting for delay_list");
   pthread_mutex_lock(&LOCK_delayed_insert);	// Protect master list
   I_List_iterator<delayed_insert> it(delayed_threads);
   delayed_insert *tmp;
@@ -1445,7 +1445,7 @@ static TABLE *delayed_get_table(THD *thd
     */
     if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads)
       DBUG_RETURN(0);
-    thd->proc_info="Creating delayed handler";
+    THD_PROC_INFO(thd, "Creating delayed handler");
     pthread_mutex_lock(&LOCK_delayed_create);
     /*
       The first search above was done without LOCK_delayed_create.
@@ -1487,13 +1487,13 @@ static TABLE *delayed_get_table(THD *thd
       }
 
       /* Wait until table is open */
-      thd->proc_info="waiting for handler open";
+      THD_PROC_INFO(thd, "waiting for handler open");
       while (!tmp->thd.killed && !tmp->table && !thd->killed)
       {
 	pthread_cond_wait(&tmp->cond_client,&tmp->mutex);
       }
       pthread_mutex_unlock(&tmp->mutex);
-      thd->proc_info="got old table";
+      THD_PROC_INFO(thd, "got old table");
       if (tmp->thd.killed)
       {
 	if (tmp->thd.is_fatal_error)
@@ -1553,13 +1553,13 @@ TABLE *delayed_insert::get_local_table(T
   tables_in_use++;
   if (!thd.lock)				// Table is not locked
   {
-    client_thd->proc_info="waiting for handler lock";
+    THD_PROC_INFO(client_thd, "waiting for handler lock");
     pthread_cond_signal(&cond);			// Tell handler to lock table
     while (!dead && !thd.lock && ! client_thd->killed)
     {
       pthread_cond_wait(&cond_client,&mutex);
     }
-    client_thd->proc_info="got handler lock";
+    THD_PROC_INFO(client_thd, "got handler lock");
     if (client_thd->killed)
       goto error;
     if (dead)
@@ -1577,7 +1577,7 @@ TABLE *delayed_insert::get_local_table(T
     bytes. Since the table copy is used for creating one record only,
     the other record buffers and alignment are unnecessary.
   */
-  client_thd->proc_info="allocating local table";
+  THD_PROC_INFO(client_thd, "allocating local table");
   copy= (TABLE*) client_thd->alloc(sizeof(*copy)+
 				   (table->s->fields+1)*sizeof(Field**)+
 				   table->s->reclength);
@@ -1657,11 +1657,11 @@ static int write_delayed(THD *thd,TABLE 
   delayed_insert *di=thd->di;
   DBUG_ENTER("write_delayed");
 
-  thd->proc_info="waiting for handler insert";
+  THD_PROC_INFO(thd, "waiting for handler insert");
   pthread_mutex_lock(&di->mutex);
   while (di->stacked_inserts >= delayed_queue_size && !thd->killed)
     pthread_cond_wait(&di->cond_client,&di->mutex);
-  thd->proc_info="storing row into queue";
+  THD_PROC_INFO(thd, "storing row into queue");
 
   if (thd->killed || !(row= new delayed_row(duplic, ignore, log_on)))
     goto err;
@@ -1873,7 +1873,7 @@ pthread_handler_t handle_delayed_insert(
       /* Information for pthread_kill */
       di->thd.mysys_var->current_mutex= &di->mutex;
       di->thd.mysys_var->current_cond= &di->cond;
-      di->thd.proc_info="Waiting for INSERT";
+      THD_PROC_INFO(&(di->thd), "Waiting for INSERT");
 
       DBUG_PRINT("info",("Waiting for someone to insert rows"));
       while (!thd->killed)
@@ -1908,7 +1908,7 @@ pthread_handler_t handle_delayed_insert(
       pthread_mutex_unlock(&di->thd.mysys_var->mutex);
       pthread_mutex_lock(&di->mutex);
     }
-    di->thd.proc_info=0;
+    THD_PROC_INFO(&(di->thd), 0);
 
     if (di->tables_in_use && ! thd->lock)
     {
@@ -2027,7 +2027,7 @@ bool delayed_insert::handle_inserts(void
 
   table->next_number_field=table->found_next_number_field;
 
-  thd.proc_info="upgrading lock";
+  THD_PROC_INFO(&thd, "upgrading lock");
   if (thr_upgrade_write_delay_lock(*thd.lock->locks))
   {
     /* This can only happen if thread is killed by shutdown */
@@ -2035,7 +2035,7 @@ bool delayed_insert::handle_inserts(void
     goto err;
   }
 
-  thd.proc_info="insert";
+  THD_PROC_INFO(&thd, "insert");
   max_rows= delayed_insert_limit;
   if (thd.killed || table->s->version != refresh_version)
   {
@@ -2153,7 +2153,7 @@ bool delayed_insert::handle_inserts(void
       {
 	if (tables_in_use)
 	  pthread_cond_broadcast(&cond_client); // If waiting clients
-	thd.proc_info="reschedule";
+	THD_PROC_INFO(&thd, "reschedule");
 	pthread_mutex_unlock(&mutex);
 	if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
 	{
@@ -2172,14 +2172,14 @@ bool delayed_insert::handle_inserts(void
 	if (!using_bin_log)
 	  table->file->extra(HA_EXTRA_WRITE_CACHE);
 	pthread_mutex_lock(&mutex);
-	thd.proc_info="insert";
+	THD_PROC_INFO(&thd, "insert");
       }
       if (tables_in_use)
 	pthread_cond_broadcast(&cond_client);	// If waiting clients
     }
   }
 
-  thd.proc_info=0;
+  THD_PROC_INFO(&thd, 0);
   table->next_number_field=0;
   pthread_mutex_unlock(&mutex);
   if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))

--- 1.206/sql/sql_lex.cc	2007-01-03 17:15:17 -05:00
+++ 1.207/sql/sql_lex.cc	2007-01-03 17:15:17 -05:00
@@ -174,6 +174,7 @@ void lex_start(THD *thd, uchar *buf,uint
   lex->proc_list.first= 0;
   lex->escape_used= FALSE;
   lex->reset_query_tables_list(FALSE);
+  lex->profile_options= PROFILE_NONE;
 
   lex->nest_level=0 ;
   lex->allow_sum_func= 0;

--- 1.233/sql/sql_lex.h	2007-01-03 17:15:17 -05:00
+++ 1.234/sql/sql_lex.h	2007-01-03 17:15:17 -05:00
@@ -95,6 +95,7 @@ enum enum_sql_command {
   SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
   SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
   SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
+  SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
   /* This should be the last !!! */
 
   SQLCOM_END
@@ -940,6 +941,8 @@ typedef struct st_lex : public Query_tab
   enum enum_var_type option_type;
   enum enum_view_create_mode create_view_mode;
   enum enum_drop_mode drop_mode;
+  uint profile_options;
+  uint profile_query_id;
   uint uint_geom_type;
   uint grant, grant_tot_col, which_columns;
   uint fk_delete_opt, fk_update_opt, fk_match_option;

--- 1.591/sql/sql_parse.cc	2007-01-03 17:15:17 -05:00
+++ 1.592/sql/sql_parse.cc	2007-01-03 17:15:17 -05:00
@@ -1059,7 +1059,7 @@ void execute_init_command(THD *thd, sys_
   Vio* save_vio;
   ulong save_client_capabilities;
 
-  thd->proc_info= "Execution of init_command";
+  THD_PROC_INFO(thd, "Execution of init_command");
   /*
     We need to lock init_command_var because
     during execution of init_command_var query
@@ -1159,7 +1159,7 @@ pthread_handler_t handle_one_connection(
       net->compress=1;				// Use compression
 
     thd->version= refresh_version;
-    thd->proc_info= 0;
+    THD_PROC_INFO(thd, 0);
     thd->command= COM_SLEEP;
     thd->set_time();
     thd->init_for_queries();
@@ -1176,7 +1176,7 @@ pthread_handler_t handle_one_connection(
                           sctx->host_or_ip, "init_connect command failed");
         sql_print_warning("%s", net->last_error);
       }
-      thd->proc_info=0;
+      THD_PROC_INFO(thd, 0);
       thd->set_time();
       thd->init_for_queries();
     }
@@ -1259,7 +1259,7 @@ pthread_handler_t handle_bootstrap(void 
   if (thd->variables.max_join_size == HA_POS_ERROR)
     thd->options |= OPTION_BIG_SELECTS;
 
-  thd->proc_info=0;
+  THD_PROC_INFO(thd, 0);
   thd->version=refresh_version;
   thd->security_ctx->priv_user=
     thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
@@ -2106,7 +2106,7 @@ bool dispatch_command(enum enum_server_c
   if (thd->lock || thd->open_tables || thd->derived_tables ||
       thd->prelocked_mode)
   {
-    thd->proc_info="closing tables";
+    THD_PROC_INFO(thd, "closing tables");
     close_thread_tables(thd);			/* Free tables */
   }
   /*
@@ -2129,9 +2129,9 @@ bool dispatch_command(enum enum_server_c
 
   log_slow_statement(thd);
 
-  thd->proc_info="cleaning up";
+  THD_PROC_INFO(thd, "cleaning up");
   VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list
-  thd->proc_info=0;
+  THD_PROC_INFO(thd, 0);
   thd->command=COM_SLEEP;
   thd->query=0;
   thd->query_length=0;
@@ -2164,8 +2164,6 @@ void log_slow_statement(THD *thd)
   */
   if (thd->enable_slow_log && !thd->user_time)
   {
-    thd->proc_info="logging slow query";
-
     if ((ulong) (thd->start_time - thd->time_after_lock) >
 	thd->variables.long_query_time ||
         (thd->server_status &
@@ -2174,6 +2172,7 @@ void log_slow_statement(THD *thd)
         /* == SQLCOM_END unless this is a SHOW command */
         thd->lex->orig_sql_command == SQLCOM_END)
     {
+      THD_PROC_INFO(thd, "logging slow query");
       thd->status_var.long_query_count++;
       mysql_slow_log.write(thd, thd->query, thd->query_length, start_of_query);
     }
@@ -2697,6 +2696,20 @@ mysql_execute_command(THD *thd)
 			      (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR));
     break;
   }
+  case SQLCOM_SHOW_PROFILES:
+  {
+    thd->profiling.store();
+    thd->profiling.discard();
+    res= thd->profiling.show_profiles();
+    break;
+  }
+  case SQLCOM_SHOW_PROFILE:
+  {
+    thd->profiling.store();
+    thd->profiling.discard(); // will get re-enabled by reset()
+    res= thd->profiling.show_last(lex->profile_options);
+    break;
+  }
   case SQLCOM_SHOW_NEW_MASTER:
   {
     if (check_global_access(thd, REPL_SLAVE_ACL))
@@ -3544,7 +3557,7 @@ end_with_restore_list:
     if (add_item_to_list(thd, new Item_null()))
       goto error;
 
-    thd->proc_info="init";
+    THD_PROC_INFO(thd, "init");
     if ((res= open_and_lock_tables(thd, all_tables)))
       break;
 
@@ -4972,7 +4985,7 @@ end_with_restore_list:
     send_ok(thd);
     break;
   }
-  thd->proc_info="query end";
+  THD_PROC_INFO(thd, "query end");
   /* Two binlog-related cleanups: */
 
   /*
@@ -5143,6 +5156,8 @@ check_access(THD *thd, ulong want_access
   else
     save_priv= &dummy;
 
+  THD_PROC_INFO(thd, "checking permissions");
+
   if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
   {
     DBUG_PRINT("error",("No database"));
@@ -5630,6 +5645,7 @@ void mysql_reset_thd_for_next_command(TH
     thd->total_warn_count=0;			// Warnings for this query
     thd->rand_used= 0;
     thd->sent_row_count= thd->examined_row_count= 0;
+    thd->profiling.reset();
   }
   DBUG_VOID_RETURN;
 }
@@ -5853,7 +5869,7 @@ void mysql_parse(THD *thd, char *inBuf, 
       query_cache_abort(&thd->net);
       lex->unit.cleanup();
     }
-    thd->proc_info="freeing items";
+    THD_PROC_INFO(thd, "freeing items");
     thd->end_statement();
     thd->cleanup_after_query();
     DBUG_ASSERT(thd->change_list.is_empty());

--- 1.478/sql/sql_select.cc	2007-01-03 17:15:17 -05:00
+++ 1.479/sql/sql_select.cc	2007-01-03 17:15:17 -05:00
@@ -599,6 +599,7 @@ JOIN::optimize()
   if (thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS)
     thd->status_var.last_query_cost= 0.0;
 
+  THD_PROC_INFO(thd, "optimizing");
   row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
 	      unit->select_limit_cnt);
   /* select_limit is used to decide if we are likely to scan the whole table */
@@ -745,7 +746,7 @@ JOIN::optimize()
   sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
 
   /* Calculate how to do the join */
-  thd->proc_info= "statistics";
+  THD_PROC_INFO(thd, "statistics");
   if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) ||
       thd->is_fatal_error)
   {
@@ -755,7 +756,7 @@ JOIN::optimize()
 
   /* Remove distinct if only const tables */
   select_distinct= select_distinct && (const_tables != tables);
-  thd->proc_info= "preparing";
+  THD_PROC_INFO(thd, "preparing");
   if (result->initialize_tables(this))
   {
     DBUG_PRINT("error",("Error: initialize_tables() failed"));
@@ -1102,9 +1103,10 @@ JOIN::optimize()
         join_tab[const_tables].type != JT_REF_OR_NULL &&
         (order && simple_order || group_list && simple_group))
     {
-      if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
+      if (add_ref_to_table_cond(thd,&join_tab[const_tables])) {
         DBUG_RETURN(1);
     }
+    }
     
     if (!(select_options & SELECT_BIG_RESULT) &&
         ((group_list &&
@@ -1161,7 +1163,7 @@ JOIN::optimize()
   if (need_tmp)
   {
     DBUG_PRINT("info",("Creating tmp table"));
-    thd->proc_info="Creating tmp table";
+    THD_PROC_INFO(thd, "creating temporary table");
 
     init_items_ref_array();
 
@@ -1190,7 +1192,9 @@ JOIN::optimize()
 			   select_options,
                            tmp_rows_limit,
 			   (char *) "")))
+		{
       DBUG_RETURN(1);
+    }
 
     /*
       We don't have to store rows in temp table that doesn't match HAVING if:
@@ -1210,27 +1214,34 @@ JOIN::optimize()
     if (group_list && simple_group)
     {
       DBUG_PRINT("info",("Sorting for group"));
-      thd->proc_info="Sorting for group";
+      THD_PROC_INFO(thd, "sorting for group");
       if (create_sort_index(thd, this, group_list,
 			    HA_POS_ERROR, HA_POS_ERROR) ||
 	  alloc_group_fields(this, group_list) ||
           make_sum_func_list(all_fields, fields_list, 1) ||
           setup_sum_funcs(thd, sum_funcs))
+      {
 	DBUG_RETURN(1);
+      }
       group_list=0;
     }
     else
     {
       if (make_sum_func_list(all_fields, fields_list, 0) ||
           setup_sum_funcs(thd, sum_funcs))
+      {
 	DBUG_RETURN(1);
+      }
+
       if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
       {
 	DBUG_PRINT("info",("Sorting for order"));
-	thd->proc_info="Sorting for order";
+        THD_PROC_INFO(thd, "Sorting for order");
 	if (create_sort_index(thd, this, order,
                               HA_POS_ERROR, HA_POS_ERROR))
+        {
 	  DBUG_RETURN(1);
+        }
 	order=0;
       }
     }
@@ -1354,6 +1365,7 @@ JOIN::exec()
   int      tmp_error;
   DBUG_ENTER("JOIN::exec");
 
+  THD_PROC_INFO(thd, "executing");
   error= 0;
   if (procedure)
   {
@@ -1493,7 +1505,7 @@ JOIN::exec()
     curr_tmp_table= exec_tmp_table1;
 
     /* Copy data to the temporary table */
-    thd->proc_info= "Copying to tmp table";
+    THD_PROC_INFO(thd, "Copying to tmp table");
     DBUG_PRINT("info", ("%s", thd->proc_info));
     if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
     {
@@ -1616,7 +1628,7 @@ JOIN::exec()
       }
       if (curr_join->group_list)
       {
-	thd->proc_info= "Creating sort index";
+	THD_PROC_INFO(thd,  "Creating sort index");
 	if (curr_join->join_tab == join_tab && save_join_tab())
 	{
 	  DBUG_VOID_RETURN;
@@ -1630,7 +1642,7 @@ JOIN::exec()
         sortorder= curr_join->sortorder;
       }
       
-      thd->proc_info="Copying to group table";
+      THD_PROC_INFO(thd, "Copying to group table");
       DBUG_PRINT("info", ("%s", thd->proc_info));
       tmp_error= -1;
       if (curr_join != this)
@@ -1686,7 +1698,7 @@ JOIN::exec()
     curr_join->join_free();			/* Free quick selects */
     if (curr_join->select_distinct && ! curr_join->group_list)
     {
-      thd->proc_info="Removing duplicates";
+      THD_PROC_INFO(thd, "Removing duplicates");
       if (curr_join->tmp_having)
 	curr_join->tmp_having->update_used_tables();
       if (remove_duplicates(curr_join, curr_tmp_table,
@@ -1747,7 +1759,7 @@ JOIN::exec()
   if (curr_join->group_list || curr_join->order)
   {
     DBUG_PRINT("info",("Sorting for send_fields"));
-    thd->proc_info="Sorting result";
+    THD_PROC_INFO(thd, "Sorting result");
     /* If we have already done the group, add HAVING to sorted table */
     if (curr_join->tmp_having && ! curr_join->group_list && 
 	! curr_join->sort_and_group)
@@ -1871,7 +1883,7 @@ JOIN::exec()
   }
   else
   {
-    thd->proc_info="Sending data";
+    THD_PROC_INFO(thd, "Sending data");
     DBUG_PRINT("info", ("%s", thd->proc_info));
     result->send_fields((procedure ? curr_join->procedure_fields_list :
                          *curr_fields_list),
@@ -2019,7 +2031,7 @@ mysql_select(THD *thd, Item ***rref_poin
   {
     if (!(join= new JOIN(thd, fields, select_options, result)))
 	DBUG_RETURN(TRUE);
-    thd->proc_info="init";
+    THD_PROC_INFO(thd, "init");
     thd->used_tables=0;                         // Updated by setup_fields
     if (err= join->prepare(rref_pointer_array, tables, wild_num,
                            conds, og_num, order, group, having, proc_param,
@@ -2064,8 +2076,9 @@ mysql_select(THD *thd, Item ***rref_poin
 err:
   if (free_join)
   {
-    thd->proc_info="end";
+    THD_PROC_INFO(thd, "cleaning up");
     err|= select_lex->cleanup();
+    THD_PROC_INFO(thd, "end");
     DBUG_RETURN(err || thd->net.report_error);
   }
   DBUG_RETURN(join->error);
@@ -9745,7 +9758,7 @@ free_tmp_table(THD *thd, TABLE *entry)
   DBUG_PRINT("enter",("table: %s",entry->alias));
 
   save_proc_info=thd->proc_info;
-  thd->proc_info="removing tmp table";
+  THD_PROC_INFO(thd, "removing tmp table");
 
   if (entry->file)
   {
@@ -9773,7 +9786,7 @@ free_tmp_table(THD *thd, TABLE *entry)
     bitmap_clear_bit(&temp_pool, entry->temp_pool_slot);
 
   free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
-  thd->proc_info=save_proc_info;
+  THD_PROC_INFO(thd, save_proc_info);
 
   DBUG_VOID_RETURN;
 }
@@ -9803,7 +9816,7 @@ bool create_myisam_from_heap(THD *thd, T
     DBUG_RETURN(1);				// End of memory
 
   save_proc_info=thd->proc_info;
-  thd->proc_info="converting HEAP to MyISAM";
+  THD_PROC_INFO(thd, "converting HEAP to MyISAM");
 
   if (create_myisam_tmp_table(&new_table,param,
 			      thd->lex->select_lex.options | thd->options))
@@ -9856,8 +9869,8 @@ bool create_myisam_from_heap(THD *thd, T
   table->s= &table->share_not_to_be_used;
   table->file->change_table_ptr(table);
   if (save_proc_info)
-    thd->proc_info= (!strcmp(save_proc_info,"Copying to tmp table") ?
-                     "Copying to tmp table on disk" : save_proc_info);
+    THD_PROC_INFO(thd, (!strcmp(save_proc_info,"Copying to tmp table") ?
+                     "Copying to tmp table on disk" : save_proc_info));
   DBUG_RETURN(0);
 
  err:
@@ -9869,7 +9882,7 @@ bool create_myisam_from_heap(THD *thd, T
   new_table.file->delete_table(new_table.s->table_name);
   delete new_table.file;
  err2:
-  thd->proc_info=save_proc_info;
+  THD_PROC_INFO(thd, save_proc_info);
   DBUG_RETURN(1);
 }
 

--- 1.333/sql/sql_show.cc	2007-01-03 17:15:17 -05:00
+++ 1.334/sql/sql_show.cc	2007-01-03 17:15:17 -05:00
@@ -1350,7 +1350,7 @@ void mysqld_list_processes(THD *thd,cons
 
 #if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
         if (pthread_kill(tmp->real_id,0))
-          tmp->proc_info="*** DEAD ***";        // This shouldn't happen
+          THD_PROC_INFO(tmp, "*** DEAD ***");        // This shouldn't happen
 #endif
 #ifdef EXTRA_DEBUG
         thd_info->start_time= tmp->time_after_lock;

--- 1.326/sql/sql_table.cc	2007-01-03 17:15:17 -05:00
+++ 1.327/sql/sql_table.cc	2007-01-03 17:15:17 -05:00
@@ -1728,7 +1728,7 @@ bool mysql_create_table(THD *thd,const c
     }
   }
 
-  thd->proc_info="creating table";
+  THD_PROC_INFO(thd, "creating table");
   create_info->table_existed= 0;		// Mark that table is created
 
   if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
@@ -1759,7 +1759,7 @@ bool mysql_create_table(THD *thd,const c
 
 end:
   VOID(pthread_mutex_unlock(&LOCK_open));
-  thd->proc_info="After create";
+  THD_PROC_INFO(thd, "After create");
   DBUG_RETURN(error);
 
 warn:
@@ -2878,7 +2878,7 @@ mysql_discard_or_import_tablespace(THD *
     ALTER TABLE
   */
 
-  thd->proc_info="discard_or_import_tablespace";
+  THD_PROC_INFO(thd, "discard_or_import_tablespace");
 
   discard= test(tablespace_op == DISCARD_TABLESPACE);
 
@@ -2895,7 +2895,7 @@ mysql_discard_or_import_tablespace(THD *
 
   error=table->file->discard_or_import_tablespace(discard);
 
-  thd->proc_info="end";
+  THD_PROC_INFO(thd, "end");
 
   if (error)
     goto err;
@@ -2958,7 +2958,7 @@ bool mysql_alter_table(THD *thd,char *ne
   frm_type_enum frm_type;
   DBUG_ENTER("mysql_alter_table");
 
-  thd->proc_info="init";
+  THD_PROC_INFO(thd, "init");
   table_name=table_list->table_name;
   alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
 
@@ -3093,7 +3093,7 @@ view_err:
     DBUG_RETURN(TRUE);
   }
   
-  thd->proc_info="setup";
+  THD_PROC_INFO(thd, "setup");
   if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
       !table->s->tmp_table) // no need to touch frm
   {
@@ -3101,7 +3101,7 @@ view_err:
     VOID(pthread_mutex_lock(&LOCK_open));
     if (new_name != table_name || new_db != db)
     {
-      thd->proc_info="rename";
+      THD_PROC_INFO(thd, "rename");
       /* Then do a 'simple' rename of the table */
       error=0;
       if (!access(new_name_buff,F_OK))
@@ -3573,7 +3573,7 @@ view_err:
   /* We don't want update TIMESTAMP fields during ALTER TABLE. */
   thd->count_cuted_fields= CHECK_FIELD_WARN;	// calc cuted fields
   thd->cuted_fields=0L;
-  thd->proc_info="copy to tmp table";
+  THD_PROC_INFO(thd, "copy to tmp table");
   next_insert_id=thd->next_insert_id;		// Remember for logging
   copied=deleted=0;
   if (new_table && !new_table->s->is_view)
@@ -3645,7 +3645,7 @@ view_err:
     from the cache, free all locks, close the old table and remove it.
   */
 
-  thd->proc_info="rename result table";
+  THD_PROC_INFO(thd, "rename result table");
   my_snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
 	      current_pid, thd->thread_id);
   if (lower_case_table_names)
@@ -3756,7 +3756,7 @@ view_err:
     broadcast_refresh();
     goto err;
   }
-  thd->proc_info="end";
+  THD_PROC_INFO(thd, "end");
   if (mysql_bin_log.is_open())
   {
     thd->clear_error();

--- 1.205/sql/sql_update.cc	2007-01-03 17:15:17 -05:00
+++ 1.206/sql/sql_update.cc	2007-01-03 17:15:17 -05:00
@@ -167,7 +167,7 @@ int mysql_update(THD *thd,
        mysql_handle_derived(thd->lex, &mysql_derived_filling)))
     DBUG_RETURN(1);
 
-  thd->proc_info="init";
+  THD_PROC_INFO(thd, "init");
   table= table_list->table;
   table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
@@ -359,7 +359,7 @@ int mysql_update(THD *thd,
       else
         init_read_record_idx(&info, thd, table, 1, used_index);
 
-      thd->proc_info="Searching rows for update";
+      THD_PROC_INFO(thd, "Searching rows for update");
       uint tmp_limit= limit;
 
       while (!(error=info.read_record(&info)) && !thd->killed)
@@ -424,7 +424,7 @@ int mysql_update(THD *thd,
   updated= found= 0;
   thd->count_cuted_fields= CHECK_FIELD_WARN;		/* calc cuted fields */
   thd->cuted_fields=0L;
-  thd->proc_info="Updating";
+  THD_PROC_INFO(thd, "Updating");
   query_id=thd->query_id;
 
   transactional_table= table->file->has_transactions();
@@ -512,7 +512,7 @@ int mysql_update(THD *thd,
   end_read_record(&info);
   free_io_cache(table);				// If ORDER BY
   delete select;
-  thd->proc_info="end";
+  THD_PROC_INFO(thd, "end");
   VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
 
   /*
@@ -960,7 +960,7 @@ int multi_update::prepare(List<Item> &no
 
   thd->count_cuted_fields= CHECK_FIELD_WARN;
   thd->cuted_fields=0L;
-  thd->proc_info="updating main table";
+  THD_PROC_INFO(thd, "updating main table");
 
   tables_to_update= get_table_map(fields);
 
@@ -1512,11 +1512,11 @@ err2:
 bool multi_update::send_eof()
 {
   char buff[STRING_BUFFER_USUAL_SIZE];
-  thd->proc_info="updating reference tables";
+  THD_PROC_INFO(thd, "updating reference tables");
 
   /* Does updates for the last n - 1 tables, returns 0 if ok */
   int local_error = (table_count) ? do_updates(0) : 0;
-  thd->proc_info= "end";
+  THD_PROC_INFO(thd, "end");
 
   /* We must invalidate the query cache before binlog writing and
   ha_autocommit_... */

--- 1.498/sql/sql_yacc.yy	2007-01-03 17:15:17 -05:00
+++ 1.499/sql/sql_yacc.yy	2007-01-03 17:15:17 -05:00
@@ -181,6 +181,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  BIT_SYM
 %token  BIT_XOR
 %token  BLOB_SYM
+%token  BLOCK_SYM
 %token  BOOLEAN_SYM
 %token  BOOL_SYM
 %token  BOTH
@@ -221,10 +222,12 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  CONSISTENT_SYM
 %token  CONSTRAINT
 %token  CONTAINS_SYM
+%token  CONTEXT_SYM
 %token  CONTINUE_SYM
 %token  CONVERT_SYM
 %token  CONVERT_TZ_SYM
 %token  COUNT_SYM
+%token  CPU_SYM
 %token  CREATE
 %token  CROSS
 %token  CUBE_SYM
@@ -298,6 +301,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  EXTRACT_SYM
 %token  FALSE_SYM
 %token  FAST_SYM
+%token  FAULTS_SYM
 %token  FETCH_SYM
 %token  FIELD_FUNC
 %token  FILE_SYM
@@ -367,6 +371,8 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  INT_SYM
 %token  INVOKER_SYM
 %token  IN_SYM
+%token  IO_SYM
+%token  IPC_SYM
 %token  IS
 %token  ISOLATION
 %token  ISSUER_SYM
@@ -435,6 +441,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  MEDIUMINT
 %token  MEDIUMTEXT
 %token  MEDIUM_SYM
+%token  MEMORY_SYM
 %token  MERGE_SYM
 %token  MICROSECOND_SYM
 %token  MIGRATE_SYM
@@ -493,6 +500,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  OUTFILE
 %token  OUT_SYM
 %token  PACK_KEYS_SYM
+%token  PAGE_SYM
 %token  PARTIAL
 %token  PASSWORD
 %token  PARAM_MARKER
@@ -510,6 +518,8 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  PROCEDURE
 %token  PROCESS
 %token  PROCESSLIST_SYM
+%token  PROFILE_SYM
+%token  PROFILES_SYM
 %token  PURGE
 %token  QUARTER_SYM
 %token  QUERY_SYM
@@ -580,6 +590,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  SMALLINT
 %token  SNAPSHOT_SYM
 %token  SOUNDS_SYM
+%token  SOURCE_SYM
 %token  SPATIAL_SYM
 %token  SPECIFIC_SYM
 %token  SQLEXCEPTION_SYM
@@ -610,6 +621,8 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  SUM_SYM
 %token  SUPER_SYM
 %token  SUSPEND_SYM
+%token  SWAPS_SYM
+%token  SWITCHES_SYM
 %token  SYSDATE
 %token  TABLES
 %token  TABLESPACE
@@ -735,7 +748,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
         union_opt select_derived_init option_type2
 
 %type <ulong_num>
-	ulong_num raid_types merge_insert_types
+	ulong_num raid_types merge_insert_types opt_profile_query_arg
 
 %type <ulonglong_number>
 	ulonglong_num
@@ -6472,6 +6485,48 @@ opt_table_sym:
 	/* empty */
 	| TABLE_SYM;
 
+opt_profile_defs:
+  /* empty */
+  | profile_defs
+
+profile_defs:
+  profile_def
+  | profile_defs ',' profile_def
+
+profile_def:
+  CPU_SYM
+    { Lex->profile_options|= PROFILE_CPU; }
+  | MEMORY_SYM
+    { Lex->profile_options|= PROFILE_MEMORY; }
+  | BLOCK_SYM IO_SYM
+    { Lex->profile_options|= PROFILE_BLOCK_IO; }
+  | CONTEXT_SYM SWITCHES_SYM
+    { Lex->profile_options|= PROFILE_CONTEXT; }
+  | PAGE_SYM FAULTS_SYM
+    { Lex->profile_options|= PROFILE_PAGE_FAULTS; }
+  | IPC_SYM
+    { Lex->profile_options|= PROFILE_IPC; }
+  | SWAPS_SYM
+    { Lex->profile_options|= PROFILE_SWAPS; }
+  | SOURCE_SYM
+    { Lex->profile_options|= PROFILE_SOURCE; }
+  | ALL
+    { Lex->profile_options|= PROFILE_ALL; }
+  ;
+
+opt_profile_query_arg:
+  /* empty */
+    { $$= 0; }
+  | QUERY_SYM NUM
+    { $$= atoi($2.str); }
+  ;
+
+opt_profile_args:
+  /* empty */
+  | FOR_SYM opt_profile_query_arg
+    { Lex->profile_query_id = $2; }
+  ;
+
 /* Show things */
 
 show:	SHOW
@@ -6607,6 +6662,10 @@ show_param:
           { Lex->sql_command = SQLCOM_SHOW_WARNS;}
         | ERRORS opt_limit_clause_init
           { Lex->sql_command = SQLCOM_SHOW_ERRORS;}
+        | PROFILES_SYM
+          { Lex->sql_command = SQLCOM_SHOW_PROFILES; }
+        | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause_init
+          { Lex->sql_command = SQLCOM_SHOW_PROFILE; }
         | opt_var_type STATUS_SYM wild_and_where
           {
             LEX *lex= Lex;
@@ -7698,6 +7757,7 @@ keyword_sp:
 	| BERKELEY_DB_SYM	{}
 	| BINLOG_SYM		{}
 	| BIT_SYM		{}
+	| BLOCK_SYM {}
 	| BOOL_SYM		{}
 	| BOOLEAN_SYM		{}
 	| BTREE_SYM		{}
@@ -7714,6 +7774,8 @@ keyword_sp:
 	| COMPRESSED_SYM	{}
 	| CONCURRENT		{}
 	| CONSISTENT_SYM	{}
+	| CONTEXT_SYM     {}
+	| CPU_SYM     {}
 	| CUBE_SYM		{}
 	| DATA_SYM		{}
 	| DATETIME		{}
@@ -7736,6 +7798,7 @@ keyword_sp:
         | EXPANSION_SYM         {}
 	| EXTENDED_SYM		{}
 	| FAST_SYM		{}
+	| FAULTS_SYM  {}
 	| FOUND_SYM		{}
 	| DISABLE_SYM		{}
 	| ENABLE_SYM		{}
@@ -7760,6 +7823,8 @@ keyword_sp:
 	| ISSUER_SYM		{}
 	| INNOBASE_SYM		{}
 	| INSERT_METHOD		{}
+	| IO_SYM          {}
+	| IPC_SYM         {}
 	| RELAY_THREAD		{}
 	| LAST_SYM		{}
 	| LEAVES                {}
@@ -7789,6 +7854,7 @@ keyword_sp:
 	| MAX_UPDATES_PER_HOUR	{}
 	| MAX_USER_CONNECTIONS_SYM {}
 	| MEDIUM_SYM		{}
+	| MEMORY_SYM    {}
 	| MERGE_SYM		{}
 	| MICROSECOND_SYM	{}
         | MIGRATE_SYM           {}
@@ -7815,6 +7881,7 @@ keyword_sp:
 	| ONE_SHOT_SYM		{}
         | ONE_SYM               {}
 	| PACK_KEYS_SYM		{}
+	| PAGE_SYM        {}
 	| PARTIAL		{}
 	| PASSWORD		{}
         | PHASE_SYM             {}
@@ -7824,6 +7891,8 @@ keyword_sp:
         | PRIVILEGES            {}
 	| PROCESS		{}
 	| PROCESSLIST_SYM	{}
+	| PROFILE_SYM {}
+	| PROFILES_SYM {}
 	| QUARTER_SYM		{}
 	| QUERY_SYM		{}
 	| QUICK			{}
@@ -7857,6 +7926,7 @@ keyword_sp:
 	| SHUTDOWN		{}
 	| SNAPSHOT_SYM		{}
 	| SOUNDS_SYM		{}
+	| SOURCE_SYM    {}
 	| SQL_CACHE_SYM		{}
 	| SQL_BUFFER_RESULT	{}
 	| SQL_NO_CACHE_SYM	{}
@@ -7868,6 +7938,8 @@ keyword_sp:
 	| SUBJECT_SYM		{}
 	| SUPER_SYM		{}
         | SUSPEND_SYM           {}
+  | SWAPS_SYM           {}
+	| SWITCHES_SYM    {}
         | TABLES                {}
 	| TABLESPACE		{}
 	| TEMPORARY		{}

--- 1.100/sql/sql_view.cc	2007-01-03 17:15:17 -05:00
+++ 1.101/sql/sql_view.cc	2007-01-03 17:15:17 -05:00
@@ -589,7 +589,7 @@ bool mysql_create_view(THD *thd, TABLE_L
   DBUG_RETURN(0);
 
 err:
-  thd->proc_info= "end";
+  THD_PROC_INFO(thd, "end");
   lex->link_first_table_back(view, link_to_local);
   unit->cleanup();
   DBUG_RETURN(res || thd->net.report_error);

--- 1.78/sql/ha_archive.cc	2007-01-03 17:15:18 -05:00
+++ 1.79/sql/ha_archive.cc	2007-01-03 17:15:18 -05:00
@@ -1206,7 +1206,7 @@ int ha_archive::check(THD* thd, HA_CHECK
   ha_rows count= share->rows_recorded;
   DBUG_ENTER("ha_archive::check");
 
-  thd->proc_info= "Checking table";
+  THD_PROC_INFO(thd, "Checking table");
   /* Flush any waiting data */
   gzflush(share->archive_write, Z_SYNC_FLUSH);
 
@@ -1230,7 +1230,7 @@ int ha_archive::check(THD* thd, HA_CHECK
 
   my_free((char*)buf, MYF(0));
 
-  thd->proc_info= old_proc_info;
+  THD_PROC_INFO(thd, old_proc_info);
 
   if ((rc && rc != HA_ERR_END_OF_FILE) || count)  
   {
--- New file ---
+++ mysql-test/r/profile.result	07/01/03 17:15:08
create table t1 (
a int,
b int
);
insert into t1 values (1,1), (2,null), (3, 4);
insert into t1 values (5,1), (6,null), (7, 4);
insert into t1 values (1,1), (2,null), (3, 4);
insert into t1 values (5,1), (6,null), (7, 4);
insert into t1 values (5,1), (6,null), (7, 4);
select sum(a) from t1;
select sum(a) from t1 group by b;
select sum(a) + sum(b) from t1 group by b;
select max(x) from (select sum(a) as x from t1 group by b) as teeone;
show profiles;
show profile for query 8;
show profile cpu, block io for query 8;
show profile cpu for query 8;
show profile cpu for query 9 limit 2 offset 2;
show profile cpu for query 10 limit 0;
show profile cpu for query 65534;
show profile memory;
show profile block io;
show profile context switches;
show profile page faults;
show profile ipc;
show profile swaps limit 1 offset 2;
show profile source;
show profile all for query 0 limit 0;
drop table t1;
End of 5.0 tests

--- New file ---
+++ mysql-test/t/profile.test	07/01/03 17:15:08

create table t1 (
  a int,
  b int
);
--disable_result_log
insert into t1 values (1,1), (2,null), (3, 4);
insert into t1 values (5,1), (6,null), (7, 4);
insert into t1 values (1,1), (2,null), (3, 4);
insert into t1 values (5,1), (6,null), (7, 4);
insert into t1 values (5,1), (6,null), (7, 4);
select sum(a) from t1;
select sum(a) from t1 group by b;
select sum(a) + sum(b) from t1 group by b;
select max(x) from (select sum(a) as x from t1 group by b) as teeone;

# Merely verify that commands work.  Checking values is impossible, right?
show profiles;
show profile for query 8;
show profile cpu, block io for query 8;
show profile cpu for query 8;
show profile cpu for query 9 limit 2 offset 2;
show profile cpu for query 10 limit 0;
show profile cpu for query 65534;
show profile memory;
show profile block io;
show profile context switches;
show profile page faults;
show profile ipc;
show profile swaps limit 1 offset 2;
show profile source;
show profile all for query 0 limit 0;
--enable_result_log

drop table t1;


##
--echo End of 5.0 tests

--- New file ---
+++ sql/sql_profile.cc	07/01/03 17:15:08
/* Copyright (C) 2005 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */

#include "mysql_priv.h"
#include "sp_rcontext.h"

#define RUSAGE_USEC(tv)  ((tv).tv_sec*1000000 + (tv).tv_usec)
#define RUSAGE_DIFF_USEC(tv1, tv2) (RUSAGE_USEC((tv1))-RUSAGE_USEC((tv2)))

PROFILE_ENTRY::PROFILE_ENTRY()
  :status(NULL), time(0), function(NULL), file(NULL), line(0)
{
  collect();
}

PROFILE_ENTRY::PROFILE_ENTRY(PROFILE *profile_arg, const char *status_arg)
  :profile(profile_arg), function(NULL), file(NULL), line(0)
{
  collect();
  if (status_arg)
    set_status(status_arg);
}

PROFILE_ENTRY::PROFILE_ENTRY(PROFILE *profile_arg, const char *status_arg,
                             const char *function_arg,
                             const char *file_arg, unsigned int line_arg)
  :profile(profile_arg)
{
  collect();
  if (status_arg)
    set_status(status_arg);
  if (function_arg)
    function= strdup_root(&profile->profiling->root, function_arg);
  if (file_arg)
    file= strdup_root(&profile->profiling->root, file_arg);
  line= line_arg;
}

PROFILE_ENTRY::~PROFILE_ENTRY()
{
  if (status)
    free(status);
  if (function)
    free(function);
  if (file)
    free(file);
}
  
void PROFILE_ENTRY::set_status(const char *status_arg)
{
  status= strdup_root(&profile->profiling->root, status_arg);
}

void PROFILE_ENTRY::collect()
{
  time= my_getsystime();
  getrusage(RUSAGE_SELF, &rusage);
}

PROFILE::PROFILE(PROFILING *profiling_arg)
  :profiling(profiling_arg)
{
  profile_end= &profile_start;
}

PROFILE::~PROFILE()
{
  entries.empty();
}

void PROFILE::status(const char *status_arg,
                     const char *function_arg=NULL,
                     const char *file_arg=NULL, unsigned int line_arg=0)
{
  PROFILE_ENTRY *prof= NULL;
  MEM_ROOT *old_root= NULL;
  THD *thd= profiling->thd;

  DBUG_ENTER("PROFILE::status");

  /* Blank status.  Just return, and thd->proc_info will be set blank later. */
  if (unlikely(!status_arg))
    DBUG_VOID_RETURN;

  /* If thd->proc_info is currently set to status_arg, don't profile twice. */
  if (unlikely(thd->proc_info && !(strcmp(thd->proc_info, status_arg))))
    DBUG_VOID_RETURN;

  /* Is this the same query as our profile currently contains? */
  if (unlikely(thd->query_id != query_id && !thd->spcont))
    reset();
    
  /*
    In order to keep the profile information between queries (i.e. from
    SELECT to the following SHOW PROFILE command) the following code is
    necessary to keep the profile from getting freed automatically when
    mysqld cleans up after the query.  This code is shamelessly stolen
    from SHOW WARNINGS.
    
    The thd->mem_root structure is freed after each query is completed,
    so temporarily override it.
  */
  old_root= thd->mem_root;
  thd->mem_root= &profiling->root;
  if (function_arg && file_arg) {
    if ((profile_end= prof= new PROFILE_ENTRY(this, status_arg, function_arg, file_arg, line_arg)))
      entries.push_back(prof);
  } else {
    if ((profile_end= prof= new PROFILE_ENTRY(this, status_arg)))
      entries.push_back(prof);
  }
  thd->mem_root= old_root;

  DBUG_VOID_RETURN;
}

void PROFILE::reset()
{
  DBUG_ENTER("PROFILE::reset");
  if (profiling->thd->query_id != query_id)
  {
    query_id= profiling->thd->query_id;
    profile_start.collect();
    entries.empty();
  }
  DBUG_VOID_RETURN;
}

bool PROFILE::show(uint options)
{  
  PROFILE_ENTRY *prof;
  THD *thd= profiling->thd;
  PROFILE_ENTRY *ps= &profile_start;
  List<Item> field_list;
  DBUG_ENTER("PROFILE::show");

  field_list.push_back(new Item_empty_string("Status", MYSQL_ERRMSG_SIZE));
  field_list.push_back(new Item_return_int("Time_elapsed", 20,
                                           MYSQL_TYPE_LONGLONG));

  if (options & PROFILE_CPU)
  {
    field_list.push_back(new Item_return_int("CPU_user", 20,
                                             MYSQL_TYPE_LONGLONG));
    field_list.push_back(new Item_return_int("CPU_system", 20, 
                                             MYSQL_TYPE_LONGLONG));
  }
  
  if (options & PROFILE_MEMORY)
  {
  }
  
  if (options & PROFILE_CONTEXT)
  {
    field_list.push_back(new Item_return_int("Context_voluntary", 10,
                                             MYSQL_TYPE_LONG));
    field_list.push_back(new Item_return_int("Context_involuntary", 10,
                                             MYSQL_TYPE_LONG));
  }

  if (options & PROFILE_BLOCK_IO)
  {
    field_list.push_back(new Item_return_int("Block_ops_in", 10,
                                             MYSQL_TYPE_LONG));
    field_list.push_back(new Item_return_int("Block_ops_out", 10,
                                             MYSQL_TYPE_LONG));
  }
  
  if (options & PROFILE_IPC)
  {
    field_list.push_back(new Item_return_int("Messages_sent", 10,
                                             MYSQL_TYPE_LONG));
    field_list.push_back(new Item_return_int("Messages_received", 10,
                                             MYSQL_TYPE_LONG));
  }
  
  if (options & PROFILE_PAGE_FAULTS)
  {
    field_list.push_back(new Item_return_int("Page_faults_major", 10,
                                             MYSQL_TYPE_LONG));
    field_list.push_back(new Item_return_int("Page_faults_minor", 10,
                                             MYSQL_TYPE_LONG));
  }
  
  if (options & PROFILE_SWAPS)
  {
    field_list.push_back(new Item_return_int("Swaps", 10, MYSQL_TYPE_LONG));
  }
  
  if(options & PROFILE_SOURCE)
  {
    field_list.push_back(new Item_empty_string("Source_function",
                                               MYSQL_ERRMSG_SIZE));  
    field_list.push_back(new Item_empty_string("Source_file",
                                               MYSQL_ERRMSG_SIZE));
    field_list.push_back(new Item_return_int("Source_line", 10,
                                             MYSQL_TYPE_LONG));
  }
  
  if (thd->protocol->send_fields(&field_list,
                                 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
    DBUG_RETURN(TRUE);

  SELECT_LEX *sel= &thd->lex->select_lex;
  SELECT_LEX_UNIT *unit= &thd->lex->unit;
  ha_rows idx= 0;
  Protocol *protocol=thd->protocol;

  unit->set_limit(sel);

  List_iterator<PROFILE_ENTRY> it(entries);
  ulonglong last_time= ps->time;
  while ((prof= it++))
  {
    if (++idx <= unit->offset_limit_cnt)
      continue;
    if (idx > unit->select_limit_cnt)
      break;

    protocol->prepare_for_resend();
    protocol->store(prof->status, strlen(prof->status), system_charset_info);
    protocol->store((ulonglong)(prof->time - ps->time)/10);

    if (options & PROFILE_CPU)
    {
      protocol->store((ulonglong)RUSAGE_DIFF_USEC(prof->rusage.ru_utime,
                                                  ps->rusage.ru_utime));
      protocol->store((ulonglong)RUSAGE_DIFF_USEC(prof->rusage.ru_stime,
                                                  ps->rusage.ru_stime));
    }
    
    if (options & PROFILE_CONTEXT)
    {
      protocol->store((uint32)(prof->rusage.ru_nvcsw - ps->rusage.ru_nvcsw));
      protocol->store((uint32)(prof->rusage.ru_nivcsw - ps->rusage.ru_nivcsw));
    }

    if (options & PROFILE_BLOCK_IO)
    {
      protocol->store((uint32)(prof->rusage.ru_inblock-ps->rusage.ru_inblock));
      protocol->store((uint32)(prof->rusage.ru_oublock-ps->rusage.ru_oublock));
    }
    
    if (options & PROFILE_IPC)
    {
      protocol->store((uint32)(prof->rusage.ru_msgsnd - ps->rusage.ru_msgsnd));
      protocol->store((uint32)(prof->rusage.ru_msgrcv - ps->rusage.ru_msgrcv));
    }
    
    if (options & PROFILE_PAGE_FAULTS)
    {
      protocol->store((uint32)(prof->rusage.ru_majflt - ps->rusage.ru_majflt));
      protocol->store((uint32)(prof->rusage.ru_minflt - ps->rusage.ru_minflt));
    }

    if (options & PROFILE_SWAPS)
    {
      protocol->store((uint32)(prof->rusage.ru_nswap - ps->rusage.ru_nswap));
    }
    
    if (options & PROFILE_SOURCE)
    {
      if(prof->function && prof->file)
      {
        protocol->store(prof->function, strlen(prof->function), system_charset_info);        
        protocol->store(prof->file, strlen(prof->file), system_charset_info);
        protocol->store(prof->line);
      } else {
        protocol->store("(unknown)", 10, system_charset_info);
        protocol->store("(unknown)", 10, system_charset_info);
        protocol->store((uint32) 0);
      }
    }

    if (protocol->write())
      DBUG_RETURN(TRUE);
    last_time= prof->time;
  }
  send_eof(thd);
  DBUG_RETURN(FALSE);
}

/* XXX: enabled should be set to the current global profiling setting */
PROFILING::PROFILING()
  :enabled(1), keeping(1), current(NULL), last(NULL)
{
  init_sql_alloc(&root,
                 PROFILE_ALLOC_BLOCK_SIZE,
                 PROFILE_ALLOC_PREALLOC_SIZE);
}

PROFILING::~PROFILING()
{
  free_root(&root, MYF(0));
}

void PROFILING::status(const char *status_arg,
                       const char *function_arg,
                       const char *file_arg, unsigned int line_arg)
{
  DBUG_ENTER("PROFILING::status");
  
  if(!current)
    reset();

  if(unlikely(enabled))
    current->status(status_arg, function_arg, file_arg, line_arg);
  
  thd->proc_info= status_arg;
  
  DBUG_VOID_RETURN;
}

void PROFILING::store()
{
  MEM_ROOT *old_root;
  DBUG_ENTER("PROFILING::store");

  if (last && current && (last->query_id == current->query_id))
    DBUG_VOID_RETURN;

  if (history.elements > 10)  /* XXX: global/session var */
  {
    PROFILE *tmp= history.pop();
    delete tmp;
  }

  old_root= thd->mem_root;
  thd->mem_root= &root;
  
  if (current)
  {
    if (keeping && (!current->entries.is_empty())) {
      last= current;
      history.push_back(current);
      current= NULL;
    } else {
      delete current;
    }
  }
  
  current= new PROFILE(this);
  thd->mem_root= old_root;

  DBUG_VOID_RETURN;
}

void PROFILING::reset()
{
  DBUG_ENTER("PROFILING::reset");

  store();

  current->reset();
  /*free_root(&root, MYF(0));*/
  keep();

  DBUG_VOID_RETURN;
}

bool PROFILING::show_profiles()
{
  PROFILE *prof;
  List<Item> field_list;
  DBUG_ENTER("PROFILING::list_all");

  field_list.push_back(new Item_return_int("Query_ID", 10,
                                           MYSQL_TYPE_LONG));
  field_list.push_back(new Item_return_int("Time", 20,
                                           MYSQL_TYPE_LONGLONG));
  /* TODO: Add another field that lists the query. */
                                           
  if (thd->protocol->send_fields(&field_list,
                                 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
    DBUG_RETURN(TRUE);
    
  SELECT_LEX *sel= &thd->lex->select_lex;
  SELECT_LEX_UNIT *unit= &thd->lex->unit;
  ha_rows idx= 0;
  Protocol *protocol=thd->protocol;

  unit->set_limit(sel);
  
  List_iterator<PROFILE> it(history);
  while ((prof= it++))
  {
    PROFILE_ENTRY *ps= &prof->profile_start;
    PROFILE_ENTRY *pe=  prof->profile_end;

    if (++idx <= unit->offset_limit_cnt)
      continue;
    if (idx > unit->select_limit_cnt)
      break;

    protocol->prepare_for_resend();
    protocol->store((uint32)(prof->query_id));
    protocol->store((ulonglong)((pe->time - ps->time)/10));
    
    if (protocol->write())
      DBUG_RETURN(TRUE);
  }
  send_eof(thd);
  DBUG_RETURN(FALSE);
}

bool PROFILING::show(uint options, uint query_id)
{
  DBUG_ENTER("PROFILING::show");
  PROFILE *prof;

  List_iterator<PROFILE> it(history);
  while ((prof= it++))
  {
    if(prof->query_id == query_id)
      prof->show(options);
  }

  DBUG_RETURN(TRUE);
}

bool PROFILING::show_last(uint options)
{
  DBUG_ENTER("PROFILING::show_last");
  if (!history.is_empty()) {
    DBUG_RETURN(last->show(options));
  }
  DBUG_RETURN(TRUE);
}

--- New file ---
+++ sql/sql_profile.h	07/01/03 17:15:08
/* Copyright (C) 2005 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef SQL_PROFILE_H
#define SQL_PROFILE_H

#include <sys/time.h>
#include <sys/resource.h>

#if 1
#define THD_PROC_INFO(thd, msg) do { if(unlikely((thd)->profiling.enabled)) { (thd)->profiling.status((msg), __FUNCTION__, __FILE__, __LINE__); } else { (thd)->proc_info= (msg); } } while (0)
#else
#define THD_PROC_INFO(thd, msg) do { (thd)->proc_info= (msg); } while (0)
#endif

#if 0

     struct rusage {
             struct timeval ru_utime; /* user time used */
             struct timeval ru_stime; /* system time used */
             long ru_maxrss;          /* integral max resident set size */
             long ru_ixrss;           /* integral shared text memory size */
             long ru_idrss;           /* integral unshared data size */
             long ru_isrss;           /* integral unshared stack size */
             long ru_minflt;          /* page reclaims */
             long ru_majflt;          /* page faults */
             long ru_nswap;           /* swaps */
             long ru_inblock;         /* block input operations */
             long ru_oublock;         /* block output operations */
             long ru_msgsnd;          /* messages sent */
             long ru_msgrcv;          /* messages received */
             long ru_nsignals;        /* signals received */
             long ru_nvcsw;           /* voluntary context switches */
             long ru_nivcsw;          /* involuntary context switches */
     };

#endif

#define PROFILE_NONE         0
#define PROFILE_CPU          1
#define PROFILE_MEMORY       2
#define PROFILE_BLOCK_IO     4
#define PROFILE_CONTEXT      8
#define PROFILE_PAGE_FAULTS  16
#define PROFILE_IPC          32
#define PROFILE_SWAPS        64
#define PROFILE_SOURCE       16384
#define PROFILE_ALL          32767

class PROFILE_ENTRY;
class PROFILE;
class PROFILING;

/*
  A single entry in a single profile.
*/

class PROFILE_ENTRY: public Sql_alloc
{
public:
  PROFILE   *profile;
  char      *status;
  ulonglong time;
  struct rusage rusage;

  char *function;
  char *file;
  unsigned int line;
  
  PROFILE_ENTRY();
  PROFILE_ENTRY(PROFILE *profile_arg, const char *status_arg);
  PROFILE_ENTRY(PROFILE *profile_arg, const char *status_arg,
                const char *function_arg,
                const char *file_arg, unsigned int line_arg);
  ~PROFILE_ENTRY();

  void set_status(const char *status_arg);
  void collect();
};

/*
  The full profile for a single query.  Includes multiple PROFILE_ENTRY
  objects.
*/

class PROFILE: public Sql_alloc
{
public:
  PROFILING *profiling;
  query_id_t query_id;
  PROFILE_ENTRY profile_start;
  PROFILE_ENTRY *profile_end;
  List<PROFILE_ENTRY> entries;

  PROFILE(PROFILING *profiling_arg);
  ~PROFILE();

  /* Add a profile status change to the current profile. */
  void status(const char *status_arg,
              const char *function_arg,
              const char *file_arg, unsigned int line_arg);

  /* Reset the contents of this profile entry. */
  void reset();

  /* Show this profile.  This is called by PROFILING. */
  bool show(uint options);
};

/*
  Profiling state for a single THD.  Contains multiple PROFILE objects.
*/

class PROFILING: public Sql_alloc
{
public:
  MEM_ROOT root;
  THD *thd;
  bool enabled;
  bool keeping;

  PROFILE       *current;
  PROFILE       *last;
  List<PROFILE> history;

  PROFILING();
  ~PROFILING();

  inline void set_thd(THD *thd_arg) { thd= thd_arg; };

  /*
    Should we try to collect profiling information at all?
    
    If we disable profiling, we cannot later decide to turn it back
    on for the same query.
  */
  inline void enable()  { enabled= 1; };
  inline void disable() { enabled= 0; };

  /*
    Do we intend to keep the currently collected profile?
    
    We don't keep profiles for some commands, such as SHOW PROFILE,
    SHOW PROFILES, and some SQLCOM commands which aren't useful to
    profile.  The keep() and discard() functions can be called many
    times, only the final setting when the query finishes is used
    to decide whether to discard the profile.
    
    The default is to keep the profile for all queries.
  */
  inline void keep()    { keeping= 1; };
  inline void discard() { keeping= 0; };

  void status(const char *status_arg,
              const char *function_arg,
              const char *file_arg, unsigned int line_arg);

  /* Stash this profile in the profile history. */
  void store();
  
  /* Reset the current profile and state of profiling for the next query. */
  void reset();

  /* SHOW PROFILES */
  bool show_profiles();

  /* SHOW PROFILE FOR QUERY query_id */
  bool show(uint options, uint query_id);

  /* SHOW PROFILE */
  bool show_last(uint options);
};

#endif /* SQL_PROFILE_H */


--- 1.14/BitKeeper/etc/collapsed	2007-01-03 17:15:18 -05:00
+++ 1.15/BitKeeper/etc/collapsed	2007-01-03 17:15:18 -05:00
@@ -19,3 +19,6 @@
 4538a7b0EbDHHkWPbIwxO6ZIDdg6Dg
 454a7ef8gdvE_ddMlJyghvOAkKPNOQ
 454f8960jsVT_kMKJtZ9OCgXoba0xQ
+459c03b9N_mqF2XJKK6DwSrIt7e6_g
+459c1965_BQMBzBO8S_gVqjTHYQrmw
+459c2098XoAUsUn8N07IVRDD6CTM-A

--- 1.70/libmysqld/Makefile.am	2007-01-03 17:15:18 -05:00
+++ 1.71/libmysqld/Makefile.am	2007-01-03 17:15:18 -05:00
@@ -53,6 +53,7 @@ sqlsources = derror.cc field.cc field_co
 	protocol.cc net_serv.cc opt_range.cc \
 	opt_sum.cc procedure.cc records.cc sql_acl.cc \
 	sql_load.cc discover.cc sql_locale.cc \
+	sql_profile.cc \
 	sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
 	sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
 	sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \

--- 1.226/sql/sp_head.cc	2007-01-03 17:15:18 -05:00
+++ 1.227/sql/sp_head.cc	2007-01-03 17:15:18 -05:00
@@ -2372,9 +2372,9 @@ sp_lex_keeper::reset_lex_and_exec_core(T
 
   m_lex->unit.cleanup();
 
-  thd->proc_info="closing tables";
+  THD_PROC_INFO(thd, "closing tables");
   close_thread_tables(thd);
-  thd->proc_info= 0;
+  THD_PROC_INFO(thd, 0);
 
   if (m_lex->query_tables_own_last)
   {

--- 1.61/sql/repl_failsafe.cc	2007-01-03 17:15:18 -05:00
+++ 1.62/sql/repl_failsafe.cc	2007-01-03 17:15:18 -05:00
@@ -92,7 +92,7 @@ static int init_failsafe_rpl_thread(THD*
   if (thd->variables.max_join_size == HA_POS_ERROR)
     thd->options|= OPTION_BIG_SELECTS;
 
-  thd->proc_info="Thread initialized";
+  THD_PROC_INFO(thd, "Thread initialized");
   thd->version=refresh_version;
   thd->set_time();
   DBUG_RETURN(0);
@@ -598,7 +598,7 @@ pthread_handler_t handle_failsafe_rpl(vo
   {
     bool break_req_chain = 0;
     pthread_cond_wait(&COND_rpl_status, &LOCK_rpl_status);
-    thd->proc_info="Processing request";
+    THD_PROC_INFO(thd, "Processing request");
     while (!break_req_chain)
     {
       switch (rpl_status) {
@@ -942,7 +942,7 @@ bool load_master_data(THD* thd)
       goto err;
     }
   }
-  thd->proc_info="purging old relay logs";
+  THD_PROC_INFO(thd, "purging old relay logs");
   if (purge_relay_logs(&active_mi->rli,thd,
 		       0 /* not only reset, but also reinit */,
 		       &errmsg))

--- 1.153/sql/sql_repl.cc	2007-01-03 17:15:18 -05:00
+++ 1.154/sql/sql_repl.cc	2007-01-03 17:15:18 -05:00
@@ -1197,7 +1197,7 @@ bool change_master(THD* thd, MASTER_INFO
   if (need_relay_log_purge)
   {
     relay_log_purge= 1;
-    thd->proc_info="Purging old relay logs";
+    THD_PROC_INFO(thd, "Purging old relay logs");
     if (purge_relay_logs(&mi->rli, thd,
 			 0 /* not only reset, but also reinit */,
 			 &errmsg))
Thread
bk commit into 5.0 tree (cmiller:1.2326)Chad MILLER3 Jan