Below is the list of changes that have just been committed into a local
5.0-community 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-07-02 07:27:39-04:00, cmiller@stripped +8 -0
Unify profiling SHOW code and INFORMATION_SCHEMA code for
profiling. Also,
Bug#26938: profiling client hang if used before enabled
In the SHOW command, not sending header data because we had no
rows to send was a protocol violation. Porting the SHOW PROFILE
command to use the Information Schema table avoids that problem.
mysql-test/r/profiling.result@stripped, 2007-07-02 07:27:23-04:00, cmiller@stripped +4 -0
Add headers of pre-profile SHOW test.
mysql-test/t/profiling.test@stripped, 2007-07-02 07:27:23-04:00, cmiller@stripped +5 -0
Verify that the protocol isn't violated if we ask for profiling
info before profiling has recorded anything.
sql/sql_parse.cc@stripped, 2007-07-02 07:27:23-04:00, cmiller@stripped +9 -17
Remove SQLCOM_SHOW_PROFILE and add a I_S schema table entry.
sql/sql_profile.cc@stripped, 2007-07-02 07:27:23-04:00, cmiller@stripped +95 -253
Add SHOW column-names and a new function that takes profile options
set in the parser and packs a list of selected fields from the
I_S table implementation.
sql/sql_profile.h@stripped, 2007-07-02 07:27:23-04:00, cmiller@stripped +1 -6
Remove unused functions and add a new function.
sql/sql_show.cc@stripped, 2007-07-02 07:27:24-04:00, cmiller@stripped +2 -1
Add a pointer to the function that selects fields from I_S table
for SHOW command.
sql/sql_yacc.yy@stripped, 2007-07-02 07:27:24-04:00, cmiller@stripped +7 -1
Prepare an I_S table for SHOW PROFILE.
sql/table.h@stripped, 2007-07-02 07:27:24-04:00, cmiller@stripped +1 -1
Rename to match the intention.
# 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
--- 1.599/sql/sql_parse.cc 2007-04-26 11:49:47 -04:00
+++ 1.600/sql/sql_parse.cc 2007-07-02 07:27:23 -04:00
@@ -2315,6 +2315,15 @@ int prepare_schema_table(THD *thd, LEX *
break;
}
#endif
+ case SCH_PROFILES:
+ /*
+ Mark this current profiling record to be discarded. We don't
+ wish to have SHOW commands show up in profiling.
+ */
+#ifdef ENABLED_PROFILING
+ thd->profiling.discard();
+#endif
+ break;
case SCH_OPEN_TABLES:
case SCH_VARIABLES:
case SCH_STATUS:
@@ -2754,23 +2763,6 @@ mysql_execute_command(THD *thd)
goto error;
#else
my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILES", "enable-profiling");
- goto error;
-#endif
- break;
- }
- case SQLCOM_SHOW_PROFILE:
- {
-#ifdef ENABLED_PROFILING
- thd->profiling.store();
- thd->profiling.discard(); // will get re-enabled by reset()
- if (lex->profile_query_id != 0)
- res= thd->profiling.show(lex->profile_options, lex->profile_query_id);
- else
- res= thd->profiling.show_last(lex->profile_options);
- if (res)
- goto error;
-#else
- my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILE", "enable-profiling");
goto error;
#endif
break;
--- 1.346/sql/sql_show.cc 2007-04-26 11:49:48 -04:00
+++ 1.347/sql/sql_show.cc 2007-07-02 07:27:24 -04:00
@@ -4344,7 +4344,8 @@ ST_SCHEMA_TABLE schema_tables[]=
{"OPEN_TABLES", open_tables_fields_info, create_schema_table,
fill_open_tables, make_old_format, 0, -1, -1, 1},
{"PROFILING", query_profile_statistics_info, create_schema_table,
- fill_query_profile_statistics_info, NULL, NULL, -1, -1, false},
+ fill_query_profile_statistics_info, make_profile_table_for_show,
+ NULL, -1, -1, false},
{"ROUTINES", proc_fields_info, create_schema_table,
fill_schema_proc, make_proc_old_format, 0, -1, -1, 0},
{"SCHEMATA", schema_fields_info, create_schema_table,
--- 1.515/sql/sql_yacc.yy 2007-04-26 11:49:49 -04:00
+++ 1.516/sql/sql_yacc.yy 2007-07-02 07:27:24 -04:00
@@ -7044,7 +7044,13 @@ show_param:
| 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; }
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_PROFILE;
+ if (prepare_schema_table(YYTHD, lex, NULL, SCH_PROFILES) != 0)
+ YYABORT;
+ }
| opt_var_type STATUS_SYM wild_and_where
{
LEX *lex= Lex;
--- 1.141/sql/table.h 2007-04-26 11:49:49 -04:00
+++ 1.142/sql/table.h 2007-07-02 07:27:24 -04:00
@@ -320,7 +320,7 @@ enum enum_schema_tables
SCH_COLUMN_PRIVILEGES,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
- SCH_PROFILING,
+ SCH_PROFILES,
SCH_PROCEDURES,
SCH_SCHEMATA,
SCH_SCHEMA_PRIVILEGES,
--- 1.5/mysql-test/r/profiling.result 2007-04-06 09:15:16 -04:00
+++ 1.6/mysql-test/r/profiling.result 2007-07-02 07:27:23 -04:00
@@ -1,3 +1,7 @@
+show profiles;
+Query_ID Duration Query
+show profile all;
+Status Duration CPU_user CPU_system Context_voluntary Context_involuntary Block_ops_in Block_ops_out Messages_sent Messages_received Page_faults_major Page_faults_minor Swaps Source_function Source_file Source_line
show session variables like 'profil%';
Variable_name Value
profiling OFF
--- 1.2/mysql-test/t/profiling.test 2007-04-03 14:04:58 -04:00
+++ 1.3/mysql-test/t/profiling.test 2007-07-02 07:27:23 -04:00
@@ -1,3 +1,8 @@
+# Verify that the protocol isn't violated if we ask for profiling info
+# before profiling has recorded anything.
+show profiles;
+show profile all;
+
# default is OFF
show session variables like 'profil%';
select @@profiling;
--- 1.9/sql/sql_profile.cc 2007-04-06 09:15:16 -04:00
+++ 1.10/sql/sql_profile.cc 2007-07-02 07:27:23 -04:00
@@ -41,27 +41,77 @@ int fill_query_profile_statistics_info(T
ST_FIELD_INFO query_profile_statistics_info[]=
{
/* name, length, type, value, maybe_null, old_name */
- {"QUERY_ID", 20, MYSQL_TYPE_LONG, 0, false, NULL},
- {"SEQ", 20, MYSQL_TYPE_LONG, 0, false, NULL},
- {"STATE", 30, MYSQL_TYPE_STRING, 0, false, NULL},
- {"DURATION", TIME_FLOAT_DIGITS, MYSQL_TYPE_DOUBLE, 0, false, NULL},
- {"CPU_USER", TIME_FLOAT_DIGITS, MYSQL_TYPE_DOUBLE, 0, true, NULL},
- {"CPU_SYSTEM", TIME_FLOAT_DIGITS, MYSQL_TYPE_DOUBLE, 0, true, NULL},
- {"CONTEXT_VOLUNTARY", 20, MYSQL_TYPE_LONG, 0, true, NULL},
- {"CONTEXT_INVOLUNTARY", 20, MYSQL_TYPE_LONG, 0, true, NULL},
- {"BLOCK_OPS_IN", 20, MYSQL_TYPE_LONG, 0, true, NULL},
- {"BLOCK_OPS_OUT", 20, MYSQL_TYPE_LONG, 0, true, NULL},
- {"MESSAGES_SENT", 20, MYSQL_TYPE_LONG, 0, true, NULL},
- {"MESSAGES_RECEIVED", 20, MYSQL_TYPE_LONG, 0, true, NULL},
- {"PAGE_FAULTS_MAJOR", 20, MYSQL_TYPE_LONG, 0, true, NULL},
- {"PAGE_FAULTS_MINOR", 20, MYSQL_TYPE_LONG, 0, true, NULL},
- {"SWAPS", 20, MYSQL_TYPE_LONG, 0, true, NULL},
- {"SOURCE_FUNCTION", 30, MYSQL_TYPE_STRING, 0, true, NULL},
- {"SOURCE_FILE", 20, MYSQL_TYPE_STRING, 0, true, NULL},
- {"SOURCE_LINE", 20, MYSQL_TYPE_LONG, 0, true, NULL},
+ {"QUERY_ID", 20, MYSQL_TYPE_LONG, 0, false, "Query_id"},
+ {"SEQ", 20, MYSQL_TYPE_LONG, 0, false, "Seq"},
+ {"STATE", 30, MYSQL_TYPE_STRING, 0, false, "Status"},
+ {"DURATION", TIME_FLOAT_DIGITS, MYSQL_TYPE_DOUBLE, 0, false, "Duration"},
+ {"CPU_USER", TIME_FLOAT_DIGITS, MYSQL_TYPE_DOUBLE, 0, true, "CPU_user"},
+ {"CPU_SYSTEM", TIME_FLOAT_DIGITS, MYSQL_TYPE_DOUBLE, 0, true, "CPU_system"},
+ {"CONTEXT_VOLUNTARY", 20, MYSQL_TYPE_LONG, 0, true, "Context_voluntary"},
+ {"CONTEXT_INVOLUNTARY", 20, MYSQL_TYPE_LONG, 0, true, "Context_involuntary"},
+ {"BLOCK_OPS_IN", 20, MYSQL_TYPE_LONG, 0, true, "Block_ops_in"},
+ {"BLOCK_OPS_OUT", 20, MYSQL_TYPE_LONG, 0, true, "Block_ops_out"},
+ {"MESSAGES_SENT", 20, MYSQL_TYPE_LONG, 0, true, "Messages_sent"},
+ {"MESSAGES_RECEIVED", 20, MYSQL_TYPE_LONG, 0, true, "Messages_received"},
+ {"PAGE_FAULTS_MAJOR", 20, MYSQL_TYPE_LONG, 0, true, "Page_faults_major"},
+ {"PAGE_FAULTS_MINOR", 20, MYSQL_TYPE_LONG, 0, true, "Page_faults_minor"},
+ {"SWAPS", 20, MYSQL_TYPE_LONG, 0, true, "Swaps"},
+ {"SOURCE_FUNCTION", 30, MYSQL_TYPE_STRING, 0, true, "Source_function"},
+ {"SOURCE_FILE", 20, MYSQL_TYPE_STRING, 0, true, "Source_file"},
+ {"SOURCE_LINE", 20, MYSQL_TYPE_LONG, 0, true, "Source_line"},
{NULL, 0, MYSQL_TYPE_STRING, 0, true, NULL}
};
+
+int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ int profile_options = thd->lex->profile_options;
+ int fields_include_condition_truth_values[]= {
+ FALSE, /* Query_id */
+ FALSE, /* Seq */
+ TRUE, /* Status */
+ TRUE, /* Duration */
+ profile_options & PROFILE_CPU, /* CPU_user */
+ profile_options & PROFILE_CPU, /* CPU_system */
+ profile_options & PROFILE_CONTEXT, /* Context_voluntary */
+ profile_options & PROFILE_CONTEXT, /* Context_involuntary */
+ profile_options & PROFILE_BLOCK_IO, /* Block_ops_in */
+ profile_options & PROFILE_BLOCK_IO, /* Block_ops_out */
+ profile_options & PROFILE_IPC, /* Messages_sent */
+ profile_options & PROFILE_IPC, /* Messages_received */
+ profile_options & PROFILE_PAGE_FAULTS, /* Page_faults_major */
+ profile_options & PROFILE_PAGE_FAULTS, /* Page_faults_minor */
+ profile_options & PROFILE_SWAPS, /* Swaps */
+ profile_options & PROFILE_SOURCE, /* Source_function */
+ profile_options & PROFILE_SOURCE, /* Source_file */
+ profile_options & PROFILE_SOURCE, /* Source_line */
+ };
+
+ ST_FIELD_INFO *field_info;
+ Name_resolution_context *context= &thd->lex->select_lex.context;
+ int i;
+
+ for (i= 0; schema_table->fields_info[i].field_name != NULL; i++)
+ {
+ if (! fields_include_condition_truth_values[i])
+ continue;
+
+ field_info= &schema_table->fields_info[i];
+ Item_field *field= new Item_field(context,
+ NullS, NullS, field_info->field_name);
+ if (field)
+ {
+ field->set_name(field_info->old_name,
+ strlen(field_info->old_name),
+ system_charset_info);
+ if (add_item_to_list(thd, field))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
#ifdef ENABLED_PROFILING
#define RUSAGE_USEC(tv) ((tv).tv_sec*1000*1000 + (tv).tv_usec)
@@ -242,212 +292,6 @@ void QUERY_PROFILE::reset()
DBUG_VOID_RETURN;
}
-bool QUERY_PROFILE::show(uint options)
-{
- THD *thd= profiling->thd;
- List<Item> field_list;
- DBUG_ENTER("QUERY_PROFILE::show");
-
- field_list.push_back(new Item_empty_string("Status", MYSQL_ERRMSG_SIZE));
- field_list.push_back(new Item_return_int("Duration", TIME_FLOAT_DIGITS,
- MYSQL_TYPE_DOUBLE));
-
- if (options & PROFILE_CPU)
- {
- field_list.push_back(new Item_return_int("CPU_user", TIME_FLOAT_DIGITS,
- MYSQL_TYPE_DOUBLE));
- field_list.push_back(new Item_return_int("CPU_system", TIME_FLOAT_DIGITS,
- MYSQL_TYPE_DOUBLE));
- }
-
- 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);
-
- Protocol *protocol= thd->protocol;
- SELECT_LEX *sel= &thd->lex->select_lex;
- SELECT_LEX_UNIT *unit= &thd->lex->unit;
- ha_rows idx= 0;
- unit->set_limit(sel);
- PROFILE_ENTRY *previous= &profile_start;
-
- PROFILE_ENTRY *entry;
- void *iterator;
- for (iterator= entries.new_iterator();
- iterator != NULL;
- iterator= entries.iterator_next(iterator))
- {
- entry= entries.iterator_value(iterator);
-
-#ifdef HAVE_GETRUSAGE
- struct rusage *rusage= &(entry->rusage);
-#endif
- String elapsed;
-
- if (++idx <= unit->offset_limit_cnt)
- continue;
- if (idx > unit->select_limit_cnt)
- break;
-
- protocol->prepare_for_resend();
-
- /*
- This entry, n, has a point in time, T(n), and a status phrase, S(n). The
- status phrase S(n) describes the period of time that begins at T(n). The
- previous status phrase S(n-1) describes the period of time that starts at
- T(n-1) and ends at T(n). Since we want to describe the time that a status
- phrase took T(n)-T(n-1), this line must describe the previous status.
- */
- protocol->store(previous->status, strlen(previous->status),
- system_charset_info);
- protocol->store((double)(entry->time_usecs -
- previous->time_usecs)/(1000.0*1000),
- (uint32) TIME_FLOAT_DIGITS-1, &elapsed);
-
- if (options & PROFILE_CPU)
- {
-#ifdef HAVE_GETRUSAGE
- String cpu_utime, cpu_stime;
- protocol->store((double)(RUSAGE_DIFF_USEC(rusage->ru_utime,
- previous->rusage.ru_utime))/(1000.0*1000),
- (uint32) TIME_FLOAT_DIGITS-1, &cpu_utime);
- protocol->store((double)(RUSAGE_DIFF_USEC(rusage->ru_stime,
- previous->rusage.ru_stime))/(1000.0*1000),
- (uint32) TIME_FLOAT_DIGITS-1, &cpu_stime);
-#else
- protocol->store_null();
- protocol->store_null();
-#endif
- }
-
- if (options & PROFILE_CONTEXT)
- {
-#ifdef HAVE_GETRUSAGE
- protocol->store((uint32)(rusage->ru_nvcsw - previous->rusage.ru_nvcsw));
- protocol->store((uint32)(rusage->ru_nivcsw - previous->rusage.ru_nivcsw));
-#else
- protocol->store_null();
- protocol->store_null();
-#endif
- }
-
- if (options & PROFILE_BLOCK_IO)
- {
-#ifdef HAVE_GETRUSAGE
- protocol->store((uint32)(rusage->ru_inblock - previous->rusage.ru_inblock));
- protocol->store((uint32)(rusage->ru_oublock - previous->rusage.ru_oublock));
-#else
- protocol->store_null();
- protocol->store_null();
-#endif
- }
-
- if (options & PROFILE_IPC)
- {
-#ifdef HAVE_GETRUSAGE
- protocol->store((uint32)(rusage->ru_msgsnd - previous->rusage.ru_msgsnd));
- protocol->store((uint32)(rusage->ru_msgrcv - previous->rusage.ru_msgrcv));
-#else
- protocol->store_null();
- protocol->store_null();
-#endif
- }
-
- if (options & PROFILE_PAGE_FAULTS)
- {
-#ifdef HAVE_GETRUSAGE
- protocol->store((uint32)(rusage->ru_majflt - previous->rusage.ru_majflt));
- protocol->store((uint32)(rusage->ru_minflt - previous->rusage.ru_minflt));
-#else
- protocol->store_null();
- protocol->store_null();
-#endif
- }
-
- if (options & PROFILE_SWAPS)
- {
-#ifdef HAVE_GETRUSAGE
- protocol->store((uint32)(rusage->ru_nswap - previous->rusage.ru_nswap));
-#else
- protocol->store_null();
-#endif
- }
-
- if (options & PROFILE_SOURCE)
- {
- if ((entry->function != NULL) && (entry->file != NULL))
- {
- protocol->store(entry->function, strlen(entry->function),
- system_charset_info);
- protocol->store(entry->file, strlen(entry->file), system_charset_info);
- protocol->store((uint32) entry->line);
- } else {
- protocol->store_null();
- protocol->store_null();
- protocol->store_null();
- }
- }
-
- if (protocol->write())
- DBUG_RETURN(TRUE);
-
- previous= entry;
- }
- send_eof(thd);
- DBUG_RETURN(FALSE);
-}
-
PROFILING::PROFILING()
:profile_id_counter(1), keeping(TRUE), enabled(FALSE), current(NULL), last(NULL)
{
@@ -630,38 +474,11 @@ void PROFILING::set_query_source(char *q
DBUG_VOID_RETURN;
}
-bool PROFILING::show(uint options, uint profiling_query_id)
-{
- DBUG_ENTER("PROFILING::show");
- QUERY_PROFILE *prof;
-
- void *iterator;
- for (iterator= history.new_iterator();
- iterator != NULL;
- iterator= history.iterator_next(iterator))
- {
- prof= history.iterator_value(iterator);
-
- if(prof->profiling_query_id == profiling_query_id)
- DBUG_RETURN(prof->show(options));
- }
-
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "SHOW PROFILE");
- 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);
-}
-
/**
Fill the information schema table, "query_profile", as defined in show.cc .
+ There are two ways to get to this function: Selecting from the information
+ schema, and a SHOW command.
*/
int PROFILING::fill_statistics_info(THD *thd, struct st_table_list *tables, Item *cond)
{
@@ -695,6 +512,31 @@ int PROFILING::fill_statistics_info(THD
seq++, previous=entry, row_number++)
{
entry= query->entries.iterator_value(entry_iterator);
+
+ if (thd->lex->orig_sql_command == SQLCOM_SHOW_PROFILE)
+ {
+ /*
+ We got here via a SHOW command. That means that we stored
+ information about the query we wish to show and that isn't
+ in a WHERE clause at a higher level to filter out rows we
+ wish to exclude.
+
+ Because that functionality isn't available in the server yet,
+ we must filter here, at the wrong level. Once one can con-
+ struct where and having conditions at the SQL layer, then this
+ condition should be ripped out.
+ */
+ if (thd->lex->profile_query_id == 0) /* 0 == show final query */
+ {
+ if (query != last)
+ continue;
+ }
+ else
+ {
+ if (thd->lex->profile_query_id != query->profiling_query_id)
+ continue;
+ }
+ }
/* Set default values for this row. */
restore_record(table, s->default_values);
--- 1.5/sql/sql_profile.h 2007-04-06 09:15:16 -04:00
+++ 1.6/sql/sql_profile.h 2007-07-02 07:27:23 -04:00
@@ -39,6 +39,7 @@ extern const char * const _unknown_func_
extern ST_FIELD_INFO query_profile_statistics_info[];
int fill_query_profile_statistics_info(THD *thd, struct st_table_list *tables, Item *cond);
+int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table);
#define PROFILE_NONE 0
@@ -331,12 +332,6 @@ public:
/* SHOW PROFILES */
bool show_profiles();
-
- /* SHOW PROFILE FOR QUERY query_id */
- bool show(uint options, uint profiling_query_id);
-
- /* SHOW PROFILE */
- bool show_last(uint options);
/* ... from INFORMATION_SCHEMA.PROFILING ... */
int fill_statistics_info(THD *thd, struct st_table_list *tables, Item *cond);
| Thread |
|---|
| • bk commit into 5.0-community tree (cmiller:1.2478) BUG#26938 | Chad MILLER | 2 Jul |