summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <cmiller@zippy.cornsilk.net>2007-02-22 10:03:08 -0500
committerunknown <cmiller@zippy.cornsilk.net>2007-02-22 10:03:08 -0500
commit607c224969df2aa13f6b236440e02713a18e6c34 (patch)
tree1bef9445e8b72c15c47554a6cfa32aef7e32ce69
parent98d31c694dc4d16420f0cc79c012c2ce13600883 (diff)
downloadmariadb-git-607c224969df2aa13f6b236440e02713a18e6c34.tar.gz
Prevent bugs by making DBUG_* expressions syntactically equivalent
to a single statement. --- Bug#24795: SHOW PROFILE Profiling is only partially functional on some architectures. Where there is no getrusage() system call, presently Null values are returned where it would be required. Notably, Windows needs some love applied to make it as useful. Syntax this adds: SHOW PROFILES SHOW PROFILE [types] [FOR QUERY n] [OFFSET n] [LIMIT n] where "n" is an integer and "types" is zero or many (comma-separated) of "CPU" "MEMORY" (not presently supported) "BLOCK IO" "CONTEXT SWITCHES" "PAGE FAULTS" "IPC" "SWAPS" "SOURCE" "ALL" It also adds a session variable (boolean) "profiling", set to "no" by default, and (integer) profiling_history_size, set to 15 by default. This patch abstracts setting THDs' "proc_info" behind a macro that can be used as a hook into the profiling code when profiling support is compiled in. All future code in this line should use that mechanism for setting thd->proc_info. --- Tests are now set to omit the statistics. --- Adds an Information_schema table, "profiling" for access to "show profile" data. --- Merge zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.0-community-3--bug24795 into zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.0-community --- Fix merge problems. --- Fixed one bug in the query_source being NULL. Updated test results. --- Include more thorough profiling tests. Improve support for prepared statements. Use session-specific query IDs, starting at zero. --- Selecting from I_S.profiling is no longer quashed in profiling, as requested by Giuseppe. Limit the size of captured query text. No longer log queries that are zero length. BitKeeper/deleted/.del-profile.result: Rename: mysql-test/r/profile.result -> BitKeeper/deleted/.del-profile.result BitKeeper/deleted/.del-profile.test: Rename: mysql-test/t/profile.test -> BitKeeper/deleted/.del-profile.test BitKeeper/deleted/.del-sql_profile.cc: Rename: sql/sql_profile.cc -> BitKeeper/deleted/.del-sql_profile.cc BitKeeper/deleted/.del-sql_profile.h: Rename: sql/sql_profile.h -> BitKeeper/deleted/.del-sql_profile.h configure.in: Add a configure-time option to enable/disable query profiling. The default is enabled. include/my_dbug.h: DBUG_* statements should be syntactically equivalent to a single statement. myisam/mi_open.c: DBUG_* statements should be syntactically equivalent to a single statement. mysql-test/r/information_schema.result: Updated (re-recorded) tests that I missed somehow. I verified these for correctness. mysql-test/r/information_schema_db.result: Updated test results I missed. mysql-test/r/mysqlshow.result: Fix merge problems. ndb/src/ndbapi/DictCache.cpp: DBUG_* statements should be syntactically equivalent to a single statement. sql/ha_archive.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/ha_berkeley.cc: Include patch backported to 5.0-global. THD::options is a ulonglong, not ulong. sql/ha_myisam.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/ha_myisammrg.cc: DBUG_* statements should be syntactically equivalent to a single statement. sql/ha_ndbcluster.cc: DBUG_* statements should be syntactically equivalent to a single statement. sql/item_cmpfunc.cc: DBUG_* statements should be syntactically equivalent to a single statement. sql/item_func.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/lock.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/log_event.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/mysql_priv.h: Use 64-bit constants for the 64-bit bit field. Add a new option bit for whether profiling is active or not. sql/mysqld.cc: Add semicolon to DBUG statement. Add a new system variable and set it. --- Set the minimum, which is zero and not 50. sql/repl_failsafe.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/set_var.cc: Make a new system global variable and session variable, to determine behavior of profiling. --- Include patch backported to 5.0-global. THD::options is a ulonglong, not ulong. sql/set_var.h: The THD::options bit field is ulonglong, not ulong. sql/slave.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. --- Include patch backported to 5.0-global. THD::options is a ulonglong, not ulong. sql/sp_head.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/sql_base.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. --- Include patch backported to 5.0-global. THD::options is a ulonglong, not ulong. sql/sql_cache.cc: DBUG_* statements should be syntactically equivalent to a single statement. --- Fix merge problems. sql/sql_class.cc: Insert a pointer to the current thread in the profiling code. --- Manual merge, undoing first patch. --- Fix merge problems. sql/sql_class.h: Create a new system variable, profiling_history_size, and add a member to THD to hold profiling information about this thread's execution. --- Manual merge, undoing first patch. sql/sql_delete.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. --- Include patch backported to 5.0-global. THD::options is a ulonglong, not ulong. sql/sql_insert.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. --- Fix merge problems. sql/sql_lex.cc: Initialize profiling options to empty. --- Manual merge, undoing first patch. sql/sql_lex.h: Add info to the lexer object so that we can hold data that comes from parsing statements. Reuse memory addresses of uints that can't occur in the same state- ment. This is dangerous because it involves knowledge of what symbols are never used together, which is information stored obliquely in another file. --- Manual merge, undoing first patch. sql/sql_parse.cc: Add hooks to the parser to jump to profiling code. If profiling is not present, then return an error message upon being used. --- Manual merge, undoing first patch. --- Fix merge problems. --- Include patch backported to 5.0-global. THD::options is a ulonglong, not ulong. sql/sql_prepare.cc: From prepared statement execution, set the query source in the profiler, as we can't get it from thd . --- Make it less expensive to limit the size of the queries. sql/sql_repl.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/sql_select.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. --- Fix merge problems. sql/sql_show.cc: Abstract setting thread-info into a function or macro. Also, remove "static" qualification on schema_table_store_record() so that external functions may use it. --- Manual merge, undoing first patch. sql/sql_table.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/sql_update.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/sql_view.cc: Abstract setting thread-info into a function or macro. --- Manual merge, undoing first patch. sql/sql_yacc.yy: Add new lexer symbols and insert new grammatical rules necessary to retreive profiling information. --- Manual merge, undoing first patch. --- Fix merge problems. sql/table.h: Add enum item for query profiling. BitKeeper/deleted/.del-profiling-master.opt: New BitKeeper file ``mysql-test/t/profiling-master.opt'' mysql-test/r/profiling.result: New BitKeeper file ``mysql-test/r/profiling.result'' --- Include more verbose that describes the queries so far. Include Giuseppe's tests. --- Selecting from I_S.profiling is no longer quashed in profiling, as requested by Giuseppe. mysql-test/t/profiling.test: New BitKeeper file ``mysql-test/t/profiling.test'' --- Include more verbose that describes the queries so far. Include Giuseppe's tests. --- Selecting from I_S.profiling is no longer quashed in profiling, as requested by Giuseppe. sql/sql_profile.cc: New BitKeeper file ``sql/sql_profile.cc'' --- If query_source is NULL, as can sometimes happen, then don't try to copy that memory. --- Make each new session use its own numbering of query_ids, and not show the global-pool numbers to the user. Provide a way for prepared statements to set the query_source. --- Selecting from I_S.profiling is no longer quashed in profiling, as requested by Giuseppe. Limit the size of captured query text. No longer log queries that are zero length. sql/sql_profile.h: New BitKeeper file ``sql/sql_profile.h'' --- Make each new session use its own numbering of query_ids, and not show the global-pool numbers to the user. Provide a way for prepared statements to set the query_source. --- Make it less expensive to limit the size of the queries.
-rw-r--r--BitKeeper/etc/collapsed9
-rw-r--r--configure.in14
-rw-r--r--include/my_dbug.h12
-rw-r--r--myisam/mi_open.c2
-rw-r--r--mysql-test/r/information_schema.result11
-rw-r--r--mysql-test/r/information_schema_db.result1
-rw-r--r--mysql-test/r/mysqlshow.result2
-rw-r--r--mysql-test/r/profile.result30
-rw-r--r--mysql-test/r/profiling.result365
-rw-r--r--mysql-test/t/profile.test39
-rw-r--r--mysql-test/t/profiling.test195
-rw-r--r--ndb/src/ndbapi/DictCache.cpp2
-rw-r--r--sql/ha_archive.cc4
-rw-r--r--sql/ha_berkeley.cc4
-rw-r--r--sql/ha_myisam.cc24
-rw-r--r--sql/ha_myisammrg.cc2
-rw-r--r--sql/ha_ndbcluster.cc4
-rw-r--r--sql/item_cmpfunc.cc2
-rw-r--r--sql/item_func.cc8
-rw-r--r--sql/lock.cc8
-rw-r--r--sql/log_event.cc8
-rw-r--r--sql/mysql_priv.h73
-rw-r--r--sql/mysqld.cc9
-rw-r--r--sql/repl_failsafe.cc10
-rw-r--r--sql/set_var.cc18
-rw-r--r--sql/set_var.h4
-rw-r--r--sql/slave.cc40
-rw-r--r--sql/sp_head.cc4
-rw-r--r--sql/sql_base.cc30
-rw-r--r--sql/sql_cache.cc22
-rw-r--r--sql/sql_class.cc3
-rw-r--r--sql/sql_class.h7
-rw-r--r--sql/sql_delete.cc14
-rw-r--r--sql/sql_insert.cc38
-rw-r--r--sql/sql_lex.cc3
-rw-r--r--sql/sql_lex.h9
-rw-r--r--sql/sql_parse.cc71
-rw-r--r--sql/sql_prepare.cc1
-rw-r--r--sql/sql_profile.cc632
-rw-r--r--sql/sql_profile.h248
-rw-r--r--sql/sql_repl.cc18
-rw-r--r--sql/sql_select.cc47
-rw-r--r--sql/sql_show.cc8
-rw-r--r--sql/sql_table.cc20
-rw-r--r--sql/sql_update.cc14
-rw-r--r--sql/sql_view.cc2
-rw-r--r--sql/sql_yacc.yy80
-rw-r--r--sql/table.h1
48 files changed, 1600 insertions, 572 deletions
diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed
index 43292906ddd..c79a4cf25cc 100644
--- a/BitKeeper/etc/collapsed
+++ b/BitKeeper/etc/collapsed
@@ -34,3 +34,12 @@
459c2098XoAUsUn8N07IVRDD6CTM-A
459ea845XenN-uWqEM5LFvUT60tW_A
45af88c9RIIJWPfBxs3o7zekI-ELPQ
+45c38d90tNwOTSaYKHXd3ccLtnytlQ
+45c390d6BbWrwyEi5T5VsWKYxl06Rg
+45c39d31g0iik6UE_oTK5N55ry-ycA
+45da6370nnZlAAIieMCrXkxF9toOyQ
+45da6551zUuplwxuqcT2fhRgceC0CQ
+45db0d4bkGtxBk21sZFJgbCV1FcNRg
+45db468b-DKE8kUTV42eYMYmk8_g9g
+45dd21d1rVPnDfvZTNVHLalcjnbsZw
+45ddaf15_Ld7IAEpUUP3FJjJ-oSEFg
diff --git a/configure.in b/configure.in
index b86353d6b79..3e0e6c9762b 100644
--- a/configure.in
+++ b/configure.in
@@ -667,6 +667,20 @@ else
AC_MSG_RESULT([no])
fi
+# Add query profiler
+AC_ARG_ENABLE(profiling,
+ [ --disable-profiling Build a version without query profiling code ],
+ [ ENABLED_PROFILING=$enableval ],
+ [ ENABLED_PROFILING=yes ])
+
+if test "$ENABLED_PROFILING" = "yes"
+then
+ AC_DEFINE([ENABLED_PROFILING], [1],
+ [If SHOW PROFILE should be enabled])
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
# Use this to set the place used for unix socket used to local communication.
AC_ARG_WITH(unix-socket-path,
diff --git a/include/my_dbug.h b/include/my_dbug.h
index a3591f0151a..ba5bddad1bc 100644
--- a/include/my_dbug.h
+++ b/include/my_dbug.h
@@ -50,12 +50,12 @@ extern void _db_unlock_file(void);
&_db_framep_)
#define DBUG_LEAVE \
(_db_return_ (__LINE__, &_db_func_, &_db_file_, &_db_level_))
-#define DBUG_RETURN(a1) {DBUG_LEAVE; return(a1);}
-#define DBUG_VOID_RETURN {DBUG_LEAVE; return;}
+#define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0)
+#define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0)
#define DBUG_EXECUTE(keyword,a1) \
- {if (_db_on_) {if (_db_keyword_ (keyword)) { a1 }}}
+ do {if (_db_on_) {if (_db_keyword_ (keyword)) { a1 }}} while(0)
#define DBUG_PRINT(keyword,arglist) \
- {if (_db_on_) {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;}}
+ do {if (_db_on_) {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;}} while(0)
#define DBUG_PUSH(a1) _db_push_ (a1)
#define DBUG_POP() _db_pop_ ()
#define DBUG_PROCESS(a1) (_db_process_ = a1)
@@ -63,7 +63,7 @@ extern void _db_unlock_file(void);
#define DBUG_SETJMP(a1) (_db_setjmp_ (), setjmp (a1))
#define DBUG_LONGJMP(a1,a2) (_db_longjmp_ (), longjmp (a1, a2))
#define DBUG_DUMP(keyword,a1,a2)\
- {if (_db_on_) {_db_dump_(__LINE__,keyword,a1,a2);}}
+ do {if (_db_on_) {_db_dump_(__LINE__,keyword,a1,a2);}} while(0)
#define DBUG_IN_USE (_db_fp_ && _db_fp_ != stderr)
#define DEBUGGER_OFF _no_db_=1;_db_on_=0;
#define DEBUGGER_ON _no_db_=0
@@ -73,7 +73,7 @@ extern void _db_unlock_file(void);
#define DBUG_OUTPUT(A) { _db_output_(A); }
#define DBUG_ASSERT(A) assert(A)
#define DBUG_EXECUTE_IF(keyword,a1) \
- {if (_db_on_) {if (_db_strict_keyword_ (keyword)) { a1 }}}
+ do {if (_db_on_) {if (_db_strict_keyword_ (keyword)) { a1 }}} while(0)
#else /* No debugger */
#define DBUG_ENTER(a1)
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 20a50fff9d7..b911826a976 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -196,7 +196,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
if (len != MI_BASE_INFO_SIZE)
{
DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d",
- len,MI_BASE_INFO_SIZE))
+ len,MI_BASE_INFO_SIZE));
}
disk_pos= (char*)
my_n_base_info_read((uchar*) disk_cache + base_pos, &share->base);
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index d4fd536003a..742d35d4ce7 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -42,6 +42,7 @@ COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
COLUMN_PRIVILEGES
KEY_COLUMN_USAGE
+PROFILING
ROUTINES
SCHEMATA
SCHEMA_PRIVILEGES
@@ -730,7 +731,7 @@ CREATE TABLE t_crashme ( f1 BIGINT);
CREATE VIEW a1 (t_CRASHME) AS SELECT f1 FROM t_crashme GROUP BY f1;
CREATE VIEW a2 AS SELECT t_CRASHME FROM a1;
count(*)
-101
+102
drop view a2, a1;
drop table t_crashme;
select table_schema,table_name, column_name from
@@ -801,7 +802,7 @@ delete from mysql.db where user='mysqltest_4';
flush privileges;
SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
table_schema count(*)
-information_schema 16
+information_schema 17
mysql 17
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row
@@ -1094,8 +1095,8 @@ table_schema='information_schema' and
(column_type = 'varchar(7)' or column_type = 'varchar(20)')
group by column_type order by num;
column_type group_concat(table_schema, '.', table_name) num
-varchar(20) information_schema.COLUMNS 1
-varchar(7) information_schema.ROUTINES,information_schema.VIEWS 2
+varchar(20) information_schema.COLUMNS,information_schema.PROFILING 2
+varchar(7) information_schema.PROFILING,information_schema.PROFILING,information_schema.PROFILING,information_schema.ROUTINES,information_schema.VIEWS 5
create table t1(f1 char(1) not null, f2 char(9) not null)
default character set utf8;
select CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH from
@@ -1192,6 +1193,7 @@ COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME
COLUMNS TABLE_SCHEMA
COLUMN_PRIVILEGES TABLE_SCHEMA
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
+PROFILING Query_id
ROUTINES ROUTINE_SCHEMA
SCHEMATA SCHEMA_NAME
SCHEMA_PRIVILEGES TABLE_SCHEMA
@@ -1223,6 +1225,7 @@ COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME
COLUMNS TABLE_SCHEMA
COLUMN_PRIVILEGES TABLE_SCHEMA
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
+PROFILING Query_id
ROUTINES ROUTINE_SCHEMA
SCHEMATA SCHEMA_NAME
SCHEMA_PRIVILEGES TABLE_SCHEMA
diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result
index 40773a7afc1..dcd48d3aa46 100644
--- a/mysql-test/r/information_schema_db.result
+++ b/mysql-test/r/information_schema_db.result
@@ -11,6 +11,7 @@ COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
COLUMN_PRIVILEGES
KEY_COLUMN_USAGE
+PROFILING
ROUTINES
SCHEMATA
SCHEMA_PRIVILEGES
diff --git a/mysql-test/r/mysqlshow.result b/mysql-test/r/mysqlshow.result
index 2bf8a58de4e..31b4940ec53 100644
--- a/mysql-test/r/mysqlshow.result
+++ b/mysql-test/r/mysqlshow.result
@@ -85,6 +85,7 @@ Database: information_schema
| COLUMNS |
| COLUMN_PRIVILEGES |
| KEY_COLUMN_USAGE |
+| PROFILING |
| ROUTINES |
| SCHEMATA |
| SCHEMA_PRIVILEGES |
@@ -106,6 +107,7 @@ Database: INFORMATION_SCHEMA
| COLUMNS |
| COLUMN_PRIVILEGES |
| KEY_COLUMN_USAGE |
+| PROFILING |
| ROUTINES |
| SCHEMATA |
| SCHEMA_PRIVILEGES |
diff --git a/mysql-test/r/profile.result b/mysql-test/r/profile.result
deleted file mode 100644
index 8a4db348445..00000000000
--- a/mysql-test/r/profile.result
+++ /dev/null
@@ -1,30 +0,0 @@
-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
diff --git a/mysql-test/r/profiling.result b/mysql-test/r/profiling.result
new file mode 100644
index 00000000000..f8aa060eee4
--- /dev/null
+++ b/mysql-test/r/profiling.result
@@ -0,0 +1,365 @@
+show session variables like 'profil%';
+Variable_name Value
+profiling OFF
+profiling_history_size 15
+select @@profiling;
+@@profiling
+0
+set global profiling = ON;
+ERROR HY000: Variable 'profiling' is a SESSION variable and can't be used with SET GLOBAL
+set global profiling_history_size=100;
+show global variables like 'profil%';
+Variable_name Value
+profiling OFF
+profiling_history_size 100
+set session profiling = ON;
+set session profiling_history_size=30;
+show session variables like 'profil%';
+Variable_name Value
+profiling ON
+profiling_history_size 30
+select @@profiling;
+@@profiling
+1
+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);
+select max(x) from (select sum(a) as x from t1 group by b) as teeone;
+max(x)
+20
+insert into t1 select * from t1;
+select count(*) from t1;
+count(*)
+24
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+select count(*) from t1;
+count(*)
+192
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+select count(*) from t1;
+count(*)
+1536
+select sum(a) from t1;
+sum(a)
+6144
+select sum(a) from t1 group by b;
+sum(a)
+2048
+1536
+2560
+select sum(a) + sum(b) from t1 group by b;
+sum(a) + sum(b)
+NULL
+2048
+4608
+select max(x) from (select sum(a) as x from t1 group by b) as teeone;
+max(x)
+2560
+select '012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890' as big_string;
+big_string
+012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890
+show profiles;
+Query_ID Duration Query
+0 # set session profiling = ON
+1 # set session profiling_history_size=30
+2 # show session variables like 'profil%'
+3 # select @@profiling
+4 # create table t1 (
+a int,
+b int
+)
+5 # insert into t1 values (1,1), (2,null), (3, 4)
+6 # insert into t1 values (5,1), (6,null), (7, 4)
+7 # insert into t1 values (1,1), (2,null), (3, 4)
+8 # insert into t1 values (5,1), (6,null), (7, 4)
+9 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
+10 # insert into t1 select * from t1
+11 # select count(*) from t1
+12 # insert into t1 select * from t1
+13 # insert into t1 select * from t1
+14 # insert into t1 select * from t1
+15 # select count(*) from t1
+16 # insert into t1 select * from t1
+17 # insert into t1 select * from t1
+18 # insert into t1 select * from t1
+19 # select count(*) from t1
+20 # select sum(a) from t1
+21 # select sum(a) from t1 group by b
+22 # select sum(a) + sum(b) from t1 group by b
+23 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
+24 # select '0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345
+show profile for query 15;
+show profile cpu for query 15;
+show profile cpu, block io for query 15;
+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;
+show profile all for query 15;
+select * from information_schema.profiling;
+select query_id, state, duration from information_schema.profiling;
+select query_id, sum(duration) from information_schema.profiling group by query_id;
+select query_id, count(*) from information_schema.profiling group by query_id;
+select sum(duration) from information_schema.profiling;
+select query_id, count(*), sum(duration) from information_schema.profiling group by query_id;
+select 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 from information_schema.profiling;
+drop table if exists t1, t2, t3;
+Warnings:
+Note 1051 Unknown table 't2'
+Note 1051 Unknown table 't3'
+create table t1 (id int );
+create table t2 (id int not null);
+create table t3 (id int not null primary key);
+insert into t1 values (1), (2), (3);
+insert into t2 values (1), (2), (3);
+insert into t3 values (1), (2), (3);
+show profiles;
+Query_ID Duration Query
+10 # insert into t1 select * from t1
+11 # select count(*) from t1
+12 # insert into t1 select * from t1
+13 # insert into t1 select * from t1
+14 # insert into t1 select * from t1
+15 # select count(*) from t1
+16 # insert into t1 select * from t1
+17 # insert into t1 select * from t1
+18 # insert into t1 select * from t1
+19 # select count(*) from t1
+20 # select sum(a) from t1
+21 # select sum(a) from t1 group by b
+22 # select sum(a) + sum(b) from t1 group by b
+23 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
+24 # select '0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345
+25 # select * from information_schema.profiling
+26 # select query_id, state, duration from information_schema.profiling
+27 # select query_id, sum(duration) from information_schema.profiling group by query_id
+28 # select query_id, count(*) from information_schema.profiling group by query_id
+29 # select sum(duration) from information_schema.profiling
+30 # select query_id, count(*), sum(duration) from information_schema.profiling group by query_id
+31 # select 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 from information_schema.profiling
+32 # drop table if exists t1, t2, t3
+33 # SHOW WARNINGS
+34 # create table t1 (id int )
+35 # create table t2 (id int not null)
+36 # create table t3 (id int not null primary key)
+37 # insert into t1 values (1), (2), (3)
+38 # insert into t2 values (1), (2), (3)
+39 # insert into t3 values (1), (2), (3)
+select * from t1;
+id
+1
+2
+3
+show profiles;
+Query_ID Duration Query
+11 # select count(*) from t1
+12 # insert into t1 select * from t1
+13 # insert into t1 select * from t1
+14 # insert into t1 select * from t1
+15 # select count(*) from t1
+16 # insert into t1 select * from t1
+17 # insert into t1 select * from t1
+18 # insert into t1 select * from t1
+19 # select count(*) from t1
+20 # select sum(a) from t1
+21 # select sum(a) from t1 group by b
+22 # select sum(a) + sum(b) from t1 group by b
+23 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
+24 # select '0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345
+25 # select * from information_schema.profiling
+26 # select query_id, state, duration from information_schema.profiling
+27 # select query_id, sum(duration) from information_schema.profiling group by query_id
+28 # select query_id, count(*) from information_schema.profiling group by query_id
+29 # select sum(duration) from information_schema.profiling
+30 # select query_id, count(*), sum(duration) from information_schema.profiling group by query_id
+31 # select 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 from information_schema.profiling
+32 # drop table if exists t1, t2, t3
+33 # SHOW WARNINGS
+34 # create table t1 (id int )
+35 # create table t2 (id int not null)
+36 # create table t3 (id int not null primary key)
+37 # insert into t1 values (1), (2), (3)
+38 # insert into t2 values (1), (2), (3)
+39 # insert into t3 values (1), (2), (3)
+40 # select * from t1
+This ^^ should end in "select * from t1;\"
+delete from t1;
+insert into t1 values (1), (2), (3);
+insert into t1 values (1), (2), (3);
+select * from t1;
+id
+1
+2
+3
+1
+2
+3
+show profiles;
+Query_ID Duration Query
+15 # select count(*) from t1
+16 # insert into t1 select * from t1
+17 # insert into t1 select * from t1
+18 # insert into t1 select * from t1
+19 # select count(*) from t1
+20 # select sum(a) from t1
+21 # select sum(a) from t1 group by b
+22 # select sum(a) + sum(b) from t1 group by b
+23 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
+24 # select '0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345
+25 # select * from information_schema.profiling
+26 # select query_id, state, duration from information_schema.profiling
+27 # select query_id, sum(duration) from information_schema.profiling group by query_id
+28 # select query_id, count(*) from information_schema.profiling group by query_id
+29 # select sum(duration) from information_schema.profiling
+30 # select query_id, count(*), sum(duration) from information_schema.profiling group by query_id
+31 # select 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 from information_schema.profiling
+32 # drop table if exists t1, t2, t3
+33 # SHOW WARNINGS
+34 # create table t1 (id int )
+35 # create table t2 (id int not null)
+36 # create table t3 (id int not null primary key)
+37 # insert into t1 values (1), (2), (3)
+38 # insert into t2 values (1), (2), (3)
+39 # insert into t3 values (1), (2), (3)
+40 # select * from t1
+41 # delete from t1
+42 # insert into t1 values (1), (2), (3)
+43 # insert into t1 values (1), (2), (3)
+44 # select * from t1
+set session profiling = OFF;
+select sum(id) from t1;
+sum(id)
+12
+show profiles;
+Query_ID Duration Query
+16 # insert into t1 select * from t1
+17 # insert into t1 select * from t1
+18 # insert into t1 select * from t1
+19 # select count(*) from t1
+20 # select sum(a) from t1
+21 # select sum(a) from t1 group by b
+22 # select sum(a) + sum(b) from t1 group by b
+23 # select max(x) from (select sum(a) as x from t1 group by b) as teeone
+24 # select '0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345
+25 # select * from information_schema.profiling
+26 # select query_id, state, duration from information_schema.profiling
+27 # select query_id, sum(duration) from information_schema.profiling group by query_id
+28 # select query_id, count(*) from information_schema.profiling group by query_id
+29 # select sum(duration) from information_schema.profiling
+30 # select query_id, count(*), sum(duration) from information_schema.profiling group by query_id
+31 # select 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 from information_schema.profiling
+32 # drop table if exists t1, t2, t3
+33 # SHOW WARNINGS
+34 # create table t1 (id int )
+35 # create table t2 (id int not null)
+36 # create table t3 (id int not null primary key)
+37 # insert into t1 values (1), (2), (3)
+38 # insert into t2 values (1), (2), (3)
+39 # insert into t3 values (1), (2), (3)
+40 # select * from t1
+41 # delete from t1
+42 # insert into t1 values (1), (2), (3)
+43 # insert into t1 values (1), (2), (3)
+44 # select * from t1
+45 # set session profiling = OFF
+set session profiling = ON;
+select @@profiling;
+@@profiling
+1
+create function f1() returns varchar(50) return 'hello';
+select @@profiling;
+@@profiling
+1
+select * from t1 where id <> f1();
+id
+1
+2
+3
+1
+2
+3
+select @@profiling;
+@@profiling
+1
+set session profiling = ON;
+drop table if exists t2;
+create table t2 (id int not null);
+create trigger t2_bi before insert on t2 for each row set @x=0;
+select @@profiling;
+@@profiling
+1
+insert into t2 values (1), (2), (3);
+select @@profiling;
+@@profiling
+1
+set session profiling = ON;
+drop table if exists t1, t2;
+create table t1 (id int not null primary key);
+create table t2 (id int not null primary key, id1 int not null);
+select @@profiling;
+@@profiling
+1
+alter table t2 add foreign key (id1) references t1 (id) on delete cascade;
+select @@profiling;
+@@profiling
+1
+lock table t1 write;
+select @@profiling;
+@@profiling
+1
+unlock table;
+select @@profiling;
+@@profiling
+1
+set autocommit=0;
+select @@profiling, @@autocommit;
+@@profiling @@autocommit
+1 0
+begin;
+select @@profiling;
+@@profiling
+1
+insert into t1 values (1);
+insert into t2 values (1,1);
+testing referential integrity cascade
+delete from t1 where id = 1;
+select @@profiling;
+@@profiling
+1
+testing rollback
+rollback;
+select @@profiling;
+@@profiling
+1
+testing commit
+begin;
+select @@profiling;
+@@profiling
+1
+commit;
+select @@profiling;
+@@profiling
+1
+drop table if exists t1, t2, t3;
+drop view if exists v1;
+Warnings:
+Note 1051 Unknown table 'test.v1'
+drop function if exists f1;
+set session profiling = OFF;
+End of 5.0 tests
diff --git a/mysql-test/t/profile.test b/mysql-test/t/profile.test
deleted file mode 100644
index 4cf2a3aa92f..00000000000
--- a/mysql-test/t/profile.test
+++ /dev/null
@@ -1,39 +0,0 @@
-
-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
diff --git a/mysql-test/t/profiling.test b/mysql-test/t/profiling.test
new file mode 100644
index 00000000000..ebde8eeffd8
--- /dev/null
+++ b/mysql-test/t/profiling.test
@@ -0,0 +1,195 @@
+# default is OFF
+show session variables like 'profil%';
+select @@profiling;
+
+# setting global variable is an error
+--error ER_LOCAL_VARIABLE
+set global profiling = ON;
+
+# But size is okay
+set global profiling_history_size=100;
+show global variables like 'profil%';
+
+# turn on for testing
+set session profiling = ON;
+set session profiling_history_size=30; # small enough to overflow
+
+# verify it is active
+show session variables like 'profil%';
+select @@profiling;
+
+# Profiling is a descriptive look into the way the server operated
+# in retrospect. Chad doesn't think it's wise to include the result
+# log, as this creates a proscriptive specification about how the
+# server should work in the future -- or it forces everyone who
+# changes the server significantly to record the test results again,
+# and that violates the spirit of our tests. Please don't include
+# execution-specific data here, as in all of the "show profile" and
+# information_schema.profiling results.
+
+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);
+select max(x) from (select sum(a) as x from t1 group by b) as teeone;
+insert into t1 select * from t1;
+select count(*) from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+select count(*) from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+select count(*) from t1;
+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;
+select '012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890' as big_string;
+
+--enable_result_log
+--replace_column 2 #
+show profiles;
+
+--disable_result_log
+###--replace_column 2 # 3 # 4 #
+show profile for query 15;
+###--replace_column 2 # 3 # 4 #
+show profile cpu for query 15;
+###--replace_column 2 # 3 # 4 # 5 # 6 #
+show profile cpu, block io for query 15;
+###--replace_column 2 # 3 # 4 #
+show profile cpu for query 9 limit 2 offset 2;
+show profile cpu for query 10 limit 0;
+--error 0,ER_WRONG_ARGUMENTS
+show profile cpu for query 65534;
+###--replace_column 2 #
+show profile memory;
+###--replace_column 2 # 3 # 4 #
+show profile block io;
+###--replace_column 2 # 3 # 4 #
+show profile context switches;
+###--replace_column 2 # 3 # 4 #
+show profile page faults;
+###--replace_column 2 # 3 # 4 #
+show profile ipc;
+###--replace_column 2 #
+show profile swaps limit 1 offset 2;
+###--replace_column 2 # 5 #
+show profile source;
+show profile all for query 0 limit 0;
+###--replace_column 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 10 # 11 # 12 # 13 # 16 #
+show profile all for query 15;
+###--replace_column 2 # 3 # 4 # 5 # 6 # 7 # 8 # 9 # 10 # 11 # 12 # 13 # 16 #
+
+select * from information_schema.profiling;
+select query_id, state, duration from information_schema.profiling;
+select query_id, sum(duration) from information_schema.profiling group by query_id;
+select query_id, count(*) from information_schema.profiling group by query_id;
+select sum(duration) from information_schema.profiling;
+
+# Broken down into number of stages and duration of each query.
+select query_id, count(*), sum(duration) from information_schema.profiling group by query_id;
+select 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 from information_schema.profiling;
+
+
+--enable_result_log
+drop table if exists t1, t2, t3;
+create table t1 (id int );
+create table t2 (id int not null);
+create table t3 (id int not null primary key);
+insert into t1 values (1), (2), (3);
+insert into t2 values (1), (2), (3);
+insert into t3 values (1), (2), (3);
+
+--replace_column 2 #
+show profiles;
+
+select * from t1;
+--replace_column 2 #
+show profiles;
+--echo This ^^ should end in \"select * from t1;\"
+
+delete from t1;
+insert into t1 values (1), (2), (3);
+insert into t1 values (1), (2), (3);
+
+select * from t1;
+--replace_column 2 #
+show profiles;
+
+# Turning profiling off does freeze it
+set session profiling = OFF;
+select sum(id) from t1;
+--replace_column 2 #
+show profiles;
+
+## Verify that the various juggling of THD contexts doesn't affect profiling.
+
+## Functions
+set session profiling = ON;
+select @@profiling;
+create function f1() returns varchar(50) return 'hello';
+select @@profiling;
+select * from t1 where id <> f1();
+select @@profiling;
+
+## Triggers
+set session profiling = ON;
+drop table if exists t2;
+create table t2 (id int not null);
+create trigger t2_bi before insert on t2 for each row set @x=0;
+select @@profiling;
+insert into t2 values (1), (2), (3);
+select @@profiling;
+
+## ALTER TABLE
+set session profiling = ON;
+drop table if exists t1, t2;
+create table t1 (id int not null primary key);
+create table t2 (id int not null primary key, id1 int not null);
+select @@profiling;
+alter table t2 add foreign key (id1) references t1 (id) on delete cascade;
+select @@profiling;
+
+## Table LOCKing
+lock table t1 write;
+select @@profiling;
+unlock table;
+select @@profiling;
+
+## Transactions
+set autocommit=0;
+select @@profiling, @@autocommit;
+begin;
+select @@profiling;
+insert into t1 values (1);
+insert into t2 values (1,1);
+--echo testing referential integrity cascade
+delete from t1 where id = 1;
+select @@profiling;
+--echo testing rollback
+--disable_warnings
+rollback;
+--enable_warnings
+select @@profiling;
+--echo testing commit
+begin;
+select @@profiling;
+commit;
+select @@profiling;
+
+drop table if exists t1, t2, t3;
+drop view if exists v1;
+drop function if exists f1;
+
+## last thing in the file
+set session profiling = OFF;
+
+##
+--echo End of 5.0 tests
diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp
index 82e8d82bc24..226243ba7a0 100644
--- a/ndb/src/ndbapi/DictCache.cpp
+++ b/ndb/src/ndbapi/DictCache.cpp
@@ -284,7 +284,7 @@ GlobalDictCache::drop(NdbTableImpl * tab)
ver.m_refCount--;
ver.m_status = DROPPED;
if(ver.m_refCount == 0){
- DBUG_PRINT("info", ("refCount is zero, deleting m_impl"))
+ DBUG_PRINT("info", ("refCount is zero, deleting m_impl"));
delete ver.m_impl;
vers->erase(i);
}
diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc
index 6a4d372c43a..70d16f65699 100644
--- a/sql/ha_archive.cc
+++ b/sql/ha_archive.cc
@@ -1205,7 +1205,7 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
ha_rows count= share->rows_recorded;
DBUG_ENTER("ha_archive::check");
- THD_PROC_INFO(thd, "Checking table");
+ thd_proc_info(thd, "Checking table");
/* Flush any waiting data */
gzflush(share->archive_write, Z_SYNC_FLUSH);
@@ -1229,7 +1229,7 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
my_free((char*)buf, MYF(0));
- THD_PROC_INFO(thd, old_proc_info);
+ thd_proc_info(thd, old_proc_info);
if ((rc && rc != HA_ERR_END_OF_FILE) || count)
{
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index d63935f1a9c..e8cff05dac9 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -1855,8 +1855,8 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
OPTION_TABLE_LOCK)) && !trx->all)
{
/* We have to start a master transaction */
- DBUG_PRINT("trans",("starting transaction all: options: 0x%lx",
- (ulong) thd->options));
+ DBUG_PRINT("trans",("starting transaction all: options: 0x%llx",
+ thd->options));
if ((error=txn_begin(db_env, 0, &trx->all, 0)))
{
trx->bdb_lock_count--; // We didn't get the lock
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 7bb597ccf4f..4d562f5347c 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -339,7 +339,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
MYISAM_SHARE* share = file->s;
const char *old_proc_info=thd->proc_info;
- THD_PROC_INFO(thd, "Checking table");
+ thd_proc_info(thd, "Checking table");
myisamchk_init(&param);
param.thd = thd;
param.op_name = "check";
@@ -413,7 +413,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
}
- THD_PROC_INFO(thd, old_proc_info);
+ thd_proc_info(thd, old_proc_info);
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
}
@@ -679,22 +679,22 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
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(thd, buf);
+ thd_proc_info(thd, buf);
error = mi_repair_parallel(&param, file, fixed_name,
param.testflag & T_QUICK);
- THD_PROC_INFO(thd, "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(thd, "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(thd, "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);
@@ -708,7 +708,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
(share->state.changed & STATE_NOT_SORTED_PAGES))
{
optimize_done=1;
- THD_PROC_INFO(thd, "Sorting index");
+ thd_proc_info(thd, "Sorting index");
error=mi_sort_index(&param,file,fixed_name);
}
if (!statistics_done && (local_testflag & T_STATISTICS))
@@ -716,14 +716,14 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
if (share->state.changed & STATE_NOT_ANALYZED)
{
optimize_done=1;
- THD_PROC_INFO(thd, "Analyzing");
+ thd_proc_info(thd, "Analyzing");
error = chk_key(&param, file);
}
else
local_testflag&= ~T_STATISTICS; // Don't update statistics
}
}
- THD_PROC_INFO(thd, "Saving state");
+ thd_proc_info(thd, "Saving state");
if (!error)
{
if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
@@ -761,7 +761,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
update_state_info(&param, file, 0);
}
- THD_PROC_INFO(thd, 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 :
@@ -986,7 +986,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(thd, "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 |
@@ -1011,7 +1011,7 @@ int ha_myisam::enable_indexes(uint mode)
thd->clear_error();
}
info(HA_STATUS_CONST);
- THD_PROC_INFO(thd, save_proc_info);
+ thd_proc_info(thd, save_proc_info);
}
else
{
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 09445f775de..c943627a9b5 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -96,7 +96,7 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno));
return (my_errno ? my_errno : -1);
}
- DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc..."))
+ DBUG_PRINT("info", ("ha_myisammrg::open myrg_extrafunc..."));
myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 0f580c833a9..37203076bb6 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -5821,14 +5821,14 @@ ha_ndbcluster::register_query_cache_table(THD *thd,
if (!is_autocommit)
{
- DBUG_PRINT("exit", ("Can't register table during transaction"))
+ DBUG_PRINT("exit", ("Can't register table during transaction"));
DBUG_RETURN(FALSE);
}
if (ndb_get_commitcount(thd, m_dbname, m_tabname, &commit_count))
{
*engine_data= 0;
- DBUG_PRINT("exit", ("Error, could not get commitcount"))
+ DBUG_PRINT("exit", ("Error, could not get commitcount"));
DBUG_RETURN(FALSE);
}
*engine_data= commit_count;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 936ae04e93d..4492d629f8a 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -3006,7 +3006,7 @@ longlong Item_is_not_null_test::val_int()
}
if (args[0]->is_null())
{
- DBUG_PRINT("info", ("null"))
+ DBUG_PRINT("info", ("null"));
owner->was_null|= 1;
DBUG_RETURN(0);
}
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 0b1d959b6a4..fa6f92ef9f6 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3204,7 +3204,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
Structure is now initialized. Try to get the lock.
Set up control struct to allow others to abort locks
*/
- THD_PROC_INFO(thd, "User lock");
+ thd_proc_info(thd, "User lock");
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
@@ -3229,7 +3229,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
}
pthread_mutex_unlock(&LOCK_user_locks);
pthread_mutex_lock(&thd->mysys_var->mutex);
- THD_PROC_INFO(thd, 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);
@@ -3310,7 +3310,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(thd, "User lock");
+ thd_proc_info(thd, "User lock");
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
@@ -3348,7 +3348,7 @@ longlong Item_func_get_lock::val_int()
pthread_mutex_unlock(&LOCK_user_locks);
pthread_mutex_lock(&thd->mysys_var->mutex);
- THD_PROC_INFO(thd, 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);
diff --git a/sql/lock.cc b/sql/lock.cc
index daf07e16dc5..8c9de2cd317 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -150,7 +150,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
}
}
- THD_PROC_INFO(thd, "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. */
@@ -159,7 +159,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
sql_lock=0;
break;
}
- THD_PROC_INFO(thd, "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,
@@ -193,7 +193,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
thd->locked=0;
break;
}
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
/* some table was altered or deleted. reopen tables marked deleted */
mysql_unlock_tables(thd,sql_lock);
@@ -208,7 +208,7 @@ retry:
if (wait_for_tables(thd))
break; // Couldn't open tables
}
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
if (thd->killed)
{
thd->send_kill_message();
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d493cdfbae9..e0711d687e8 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -4265,7 +4265,7 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
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(thd, 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,
@@ -4319,7 +4319,7 @@ err:
end_io_cache(&file);
if (fd >= 0)
my_close(fd, MYF(0));
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
return error ? 1 : Log_event::exec_event(rli);
}
#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
@@ -4439,7 +4439,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
fname= strmov(proc_info, "Making temp file ");
slave_load_file_stem(fname, file_id, server_id, ".data");
- THD_PROC_INFO(thd, proc_info);
+ thd_proc_info(thd, proc_info);
if (get_create_or_append())
{
my_delete(fname, MYF(0)); // old copy may exist already
@@ -4473,7 +4473,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
err:
if (fd >= 0)
my_close(fd, MYF(0));
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
DBUG_RETURN(error ? error : Log_event::exec_event(rli));
}
#endif
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 458d5faa857..bd69a137a2d 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -20,6 +20,9 @@
except the part which must be in the server and in the client.
*/
+#ifndef MYSQL_PRIV_H_INCLUDED
+#define MYSQL_PRIV_H_INCLUDED
+
#ifndef MYSQL_CLIENT
#include <my_global.h>
@@ -298,55 +301,57 @@ MY_LOCALE *my_locale_by_name(const char *name);
TODO: separate three contexts above, move them to separate bitfields.
*/
-#define SELECT_DISTINCT (1L << 0) // SELECT, user
-#define SELECT_STRAIGHT_JOIN (1L << 1) // SELECT, user
-#define SELECT_DESCRIBE (1L << 2) // SELECT, user
-#define SELECT_SMALL_RESULT (1L << 3) // SELECT, user
-#define SELECT_BIG_RESULT (1L << 4) // SELECT, user
-#define OPTION_FOUND_ROWS (1L << 5) // SELECT, user
-#define OPTION_TO_QUERY_CACHE (1L << 6) // SELECT, user
-#define SELECT_NO_JOIN_CACHE (1L << 7) // intern
-#define OPTION_BIG_TABLES (1L << 8) // THD, user
-#define OPTION_BIG_SELECTS (1L << 9) // THD, user
-#define OPTION_LOG_OFF (1L << 10) // THD, user
-#define OPTION_UPDATE_LOG (1L << 11) // THD, user, unused
-#define TMP_TABLE_ALL_COLUMNS (1L << 12) // SELECT, intern
-#define OPTION_WARNINGS (1L << 13) // THD, user
-#define OPTION_AUTO_IS_NULL (1L << 14) // THD, user, binlog
-#define OPTION_FOUND_COMMENT (1L << 15) // SELECT, intern, parser
-#define OPTION_SAFE_UPDATES (1L << 16) // THD, user
-#define OPTION_BUFFER_RESULT (1L << 17) // SELECT, user
-#define OPTION_BIN_LOG (1L << 18) // THD, user
-#define OPTION_NOT_AUTOCOMMIT (1L << 19) // THD, user
-#define OPTION_BEGIN (1L << 20) // THD, intern
-#define OPTION_TABLE_LOCK (1L << 21) // THD, intern
-#define OPTION_QUICK (1L << 22) // SELECT (for DELETE)
-#define OPTION_QUOTE_SHOW_CREATE (1L << 23) // THD, user
+#define SELECT_DISTINCT (ULL(1) << 0) // SELECT, user
+#define SELECT_STRAIGHT_JOIN (ULL(1) << 1) // SELECT, user
+#define SELECT_DESCRIBE (ULL(1) << 2) // SELECT, user
+#define SELECT_SMALL_RESULT (ULL(1) << 3) // SELECT, user
+#define SELECT_BIG_RESULT (ULL(1) << 4) // SELECT, user
+#define OPTION_FOUND_ROWS (ULL(1) << 5) // SELECT, user
+#define OPTION_TO_QUERY_CACHE (ULL(1) << 6) // SELECT, user
+#define SELECT_NO_JOIN_CACHE (ULL(1) << 7) // intern
+#define OPTION_BIG_TABLES (ULL(1) << 8) // THD, user
+#define OPTION_BIG_SELECTS (ULL(1) << 9) // THD, user
+#define OPTION_LOG_OFF (ULL(1) << 10) // THD, user
+#define OPTION_UPDATE_LOG (ULL(1) << 11) // THD, user, unused
+#define TMP_TABLE_ALL_COLUMNS (ULL(1) << 12) // SELECT, intern
+#define OPTION_WARNINGS (ULL(1) << 13) // THD, user
+#define OPTION_AUTO_IS_NULL (ULL(1) << 14) // THD, user, binlog
+#define OPTION_FOUND_COMMENT (ULL(1) << 15) // SELECT, intern, parser
+#define OPTION_SAFE_UPDATES (ULL(1) << 16) // THD, user
+#define OPTION_BUFFER_RESULT (ULL(1) << 17) // SELECT, user
+#define OPTION_BIN_LOG (ULL(1) << 18) // THD, user
+#define OPTION_NOT_AUTOCOMMIT (ULL(1) << 19) // THD, user
+#define OPTION_BEGIN (ULL(1) << 20) // THD, intern
+#define OPTION_TABLE_LOCK (ULL(1) << 21) // THD, intern
+#define OPTION_QUICK (ULL(1) << 22) // SELECT (for DELETE)
+#define OPTION_QUOTE_SHOW_CREATE (ULL(1) << 23) // THD, user
/* Thr following is used to detect a conflict with DISTINCT
in the user query has requested */
-#define SELECT_ALL (1L << 24) // SELECT, user, parser
+#define SELECT_ALL (ULL(1) << 24) // SELECT, user, parser
/* Set if we are updating a non-transaction safe table */
-#define OPTION_STATUS_NO_TRANS_UPDATE (1L << 25) // THD, intern
+#define OPTION_STATUS_NO_TRANS_UPDATE (ULL(1) << 25) // THD, intern
/* The following can be set when importing tables in a 'wrong order'
to suppress foreign key checks */
-#define OPTION_NO_FOREIGN_KEY_CHECKS (1L << 26) // THD, user, binlog
+#define OPTION_NO_FOREIGN_KEY_CHECKS (ULL(1) << 26) // THD, user, binlog
/* The following speeds up inserts to InnoDB tables by suppressing unique
key checks in some cases */
-#define OPTION_RELAXED_UNIQUE_CHECKS (1L << 27) // THD, user, binlog
-#define SELECT_NO_UNLOCK (1L << 28) // SELECT, intern
-#define OPTION_SCHEMA_TABLE (1L << 29) // SELECT, intern
+#define OPTION_RELAXED_UNIQUE_CHECKS (ULL(1) << 27) // THD, user, binlog
+#define SELECT_NO_UNLOCK (ULL(1) << 28) // SELECT, intern
+#define OPTION_SCHEMA_TABLE (ULL(1) << 29) // SELECT, intern
/* Flag set if setup_tables already done */
-#define OPTION_SETUP_TABLES_DONE (1L << 30) // intern
+#define OPTION_SETUP_TABLES_DONE (ULL(1) << 30) // intern
/* If not set then the thread will ignore all warnings with level notes. */
-#define OPTION_SQL_NOTES (1UL << 31) // THD, user
+#define OPTION_SQL_NOTES (ULL(1) << 31) // THD, user
/*
Force the used temporary table to be a MyISAM table (because we will use
fulltext functions when reading from it.
*/
-#define TMP_TABLE_FORCE_MYISAM (LL(1) << 32)
+#define TMP_TABLE_FORCE_MYISAM (ULL(1) << 32)
+#define OPTION_PROFILING (ULL(1) << 33)
+
/*
Maximum length of time zone name that we support
@@ -1686,3 +1691,5 @@ inline void kill_delayed_threads(void) {}
#endif
#endif /* MYSQL_CLIENT */
+
+#endif
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 29590cdd6a0..a2afc3449cd 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1657,7 +1657,7 @@ void end_thread(THD *thd, bool put_in_cache)
! abort_loop && !kill_cached_threads)
{
/* Don't kill the thread, just put it in cache for reuse */
- DBUG_PRINT("info", ("Adding thread to cache"))
+ DBUG_PRINT("info", ("Adding thread to cache"));
cached_thread_count++;
while (!abort_loop && ! wake_thread && ! kill_cached_threads)
(void) pthread_cond_wait(&COND_thread_cache, &LOCK_thread_count);
@@ -4696,6 +4696,7 @@ enum options_mysqld
OPT_TABLE_LOCK_WAIT_TIMEOUT,
OPT_PORT_OPEN_TIMEOUT,
OPT_MERGE,
+ OPT_PROFILING,
OPT_INNODB_ROLLBACK_ON_TIMEOUT
};
@@ -5257,6 +5258,12 @@ Disable with --skip-ndbcluster (will save memory).",
"Maximum time in seconds to wait for the port to become free. "
"(Default: no wait)", (gptr*) &mysqld_port_timeout,
(gptr*) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef ENABLED_PROFILING
+ {"profiling_history_size", OPT_PROFILING, "Limit of query profiling memory",
+ (gptr*) &global_system_variables.profiling_history_size,
+ (gptr*) &max_system_variables.profiling_history_size,
+ 0, GET_UINT, REQUIRED_ARG, 15, 0, 100, 0, 0, 0},
+#endif
{"relay-log", OPT_RELAY_LOG,
"The location and name to use for relay logs.",
(gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0,
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 88b45caf354..3d8a4ebd547 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -91,7 +91,7 @@ static int init_failsafe_rpl_thread(THD* thd)
if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options|= OPTION_BIG_SELECTS;
- THD_PROC_INFO(thd, "Thread initialized");
+ thd_proc_info(thd, "Thread initialized");
thd->version=refresh_version;
thd->set_time();
DBUG_RETURN(0);
@@ -597,7 +597,7 @@ pthread_handler_t handle_failsafe_rpl(void *arg)
{
bool break_req_chain = 0;
pthread_cond_wait(&COND_rpl_status, &LOCK_rpl_status);
- THD_PROC_INFO(thd, "Processing request");
+ thd_proc_info(thd, "Processing request");
while (!break_req_chain)
{
switch (rpl_status) {
@@ -941,7 +941,7 @@ bool load_master_data(THD* thd)
goto err;
}
}
- THD_PROC_INFO(thd, "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))
@@ -968,7 +968,7 @@ bool load_master_data(THD* thd)
flush_relay_log_info(&active_mi->rli);
pthread_cond_broadcast(&active_mi->rli.data_cond);
pthread_mutex_unlock(&active_mi->rli.data_lock);
- thd->proc_info = "starting slave";
+ thd_proc_info(thd, "starting slave");
if (restart_thread_mask)
{
error=start_slave_threads(0 /* mutex not needed */,
@@ -980,7 +980,7 @@ bool load_master_data(THD* thd)
err:
unlock_slave_threads(active_mi);
pthread_mutex_unlock(&LOCK_active_mi);
- thd->proc_info = 0;
+ thd_proc_info(thd, 0);
mysql_close(&mysql); // safe to call since we always do mysql_init()
if (!error)
diff --git a/sql/set_var.cc b/sql/set_var.cc
index b4fd6b90d18..c02561261c0 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -545,6 +545,12 @@ static sys_var_thd_bit sys_unique_checks("unique_checks", 0,
set_option_bit,
OPTION_RELAXED_UNIQUE_CHECKS,
1);
+#ifdef ENABLED_PROFILING
+static sys_var_thd_bit sys_profiling("profiling", NULL, set_option_bit,
+ ulonglong(OPTION_PROFILING));
+sys_var_thd_ulong sys_profiling_history_size("profiling_history_size",
+ &SV::profiling_history_size);
+#endif
/* Local state variables */
@@ -696,6 +702,10 @@ sys_var *sys_variables[]=
&sys_optimizer_prune_level,
&sys_optimizer_search_depth,
&sys_preload_buff_size,
+#ifdef ENABLED_PROFILING
+ &sys_profiling,
+ &sys_profiling_history_size,
+#endif
&sys_pseudo_thread_id,
&sys_query_alloc_block_size,
&sys_query_cache_size,
@@ -1003,6 +1013,10 @@ struct show_var_st init_vars[]= {
{"pid_file", (char*) pidfile_name, SHOW_CHAR},
{"port", (char*) &mysqld_port, SHOW_INT},
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
+#ifdef ENABLED_PROFILING
+ {sys_profiling.name, (char*) &sys_profiling, SHOW_SYS},
+ {sys_profiling_history_size.name, (char*) &sys_profiling_history_size, SHOW_SYS},
+#endif
{"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size,
SHOW_SYS},
@@ -2842,14 +2856,14 @@ static bool set_option_autocommit(THD *thd, set_var *var)
if ((org_options & OPTION_NOT_AUTOCOMMIT))
{
/* We changed to auto_commit mode */
- thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->options&= ~(OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
if (ha_commit(thd))
return 1;
}
else
{
- thd->options&= ~(ulong) (OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->options&= ~(OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
}
}
diff --git a/sql/set_var.h b/sql/set_var.h
index 3304f552a97..d55ca4d289f 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -457,11 +457,11 @@ class sys_var_thd_bit :public sys_var_thd
sys_check_func check_func;
sys_update_func update_func;
public:
- ulong bit_flag;
+ ulonglong bit_flag;
bool reverse;
sys_var_thd_bit(const char *name_arg,
sys_check_func c_func, sys_update_func u_func,
- ulong bit, bool reverse_arg=0)
+ ulonglong bit, bool reverse_arg=0)
:sys_var_thd(name_arg), check_func(c_func), update_func(u_func),
bit_flag(bit), reverse(reverse_arg)
{}
diff --git a/sql/slave.cc b/sql/slave.cc
index 94e4fb7b6bd..83bd6b7bd2d 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1557,8 +1557,8 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
/* Create the table. We do not want to log the "create table" statement */
save_options = thd->options;
- thd->options &= ~(ulong) (OPTION_BIN_LOG);
- thd->proc_info = "Creating table from master dump";
+ thd->options &= ~ (OPTION_BIN_LOG);
+ thd_proc_info(thd, "Creating table from master dump");
// save old db in case we are creating in a different database
save_db = thd->db;
save_db_length= thd->db_length;
@@ -1572,7 +1572,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
if (thd->query_error)
goto err; // mysql_parse took care of the error send
- thd->proc_info = "Opening master dump table";
+ thd_proc_info(thd, "Opening master dump table");
tables.lock_type = TL_WRITE;
if (!open_ltable(thd, &tables, TL_WRITE))
{
@@ -1581,7 +1581,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
}
file = tables.table->file;
- thd->proc_info = "Reading master dump table data";
+ thd_proc_info(thd, "Reading master dump table data");
/* Copy the data file */
if (file->net_read_dump(net))
{
@@ -1593,7 +1593,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
check_opt.init();
check_opt.flags|= T_VERY_SILENT | T_CALC_CHECKSUM | T_QUICK;
- thd->proc_info = "Rebuilding the index on master dump table";
+ thd_proc_info(thd, "Rebuilding the index on master dump table");
/*
We do not want repair() to spam us with messages
just send them to the error log, and report the failure in case of
@@ -2924,9 +2924,9 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
#endif
if (thd_type == SLAVE_THD_SQL)
- THD_PROC_INFO(thd, "Waiting for the next event in relay log");
+ thd_proc_info(thd, "Waiting for the next event in relay log");
else
- THD_PROC_INFO(thd, "Waiting for master update");
+ thd_proc_info(thd, "Waiting for master update");
thd->version=refresh_version;
thd->set_time();
DBUG_RETURN(0);
@@ -3486,7 +3486,7 @@ slave_begin:
goto err;
}
- thd->proc_info = "Connecting to master";
+ thd_proc_info(thd, "Connecting to master");
// we can get killed during safe_connect
if (!safe_connect(thd, mysql, mi))
{
@@ -3513,7 +3513,7 @@ connected:
// TODO: the assignment below should be under mutex (5.0)
mi->slave_running= MYSQL_SLAVE_RUN_CONNECT;
thd->slave_net = &mysql->net;
- thd->proc_info = "Checking master version";
+ thd_proc_info(thd, "Checking master version");
if (get_master_version_and_clock(mysql, mi))
goto err;
@@ -3524,7 +3524,7 @@ connected:
If fails, this is not fatal - we just print the error message and go
on with life.
*/
- thd->proc_info = "Registering slave on master";
+ thd_proc_info(thd, "Registering slave on master");
if (register_slave_on_master(mysql) || update_slave_list(mysql, mi))
goto err;
}
@@ -3533,7 +3533,7 @@ connected:
while (!io_slave_killed(thd,mi))
{
bool suppress_warnings= 0;
- thd->proc_info = "Requesting binlog dump";
+ thd_proc_info(thd, "Requesting binlog dump");
if (request_dump(mysql, mi, &suppress_warnings))
{
sql_print_error("Failed on request_dump()");
@@ -3545,7 +3545,7 @@ dump");
}
mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
- THD_PROC_INFO(thd, "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
@@ -3569,7 +3569,7 @@ dump");
goto err;
}
- thd->proc_info = "Reconnecting after a failed binlog dump request";
+ thd_proc_info(thd, "Reconnecting after a failed binlog dump request");
if (!suppress_warnings)
sql_print_error("Slave I/O thread: failed dump request, \
reconnecting to try again, log '%s' at postion %s", IO_RPL_LOG_NAME,
@@ -3594,7 +3594,7 @@ after reconnect");
important thing is to not confuse users by saying "reading" whereas
we're in fact receiving nothing.
*/
- thd->proc_info = "Waiting for master to send event";
+ thd_proc_info(thd, "Waiting for master to send event");
ulong event_len = read_event(mysql, mi, &suppress_warnings);
if (io_slave_killed(thd,mi))
{
@@ -3622,7 +3622,7 @@ max_allowed_packet",
goto err;
}
mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
- thd->proc_info = "Waiting to reconnect after a failed master event read";
+ thd_proc_info(thd, "Waiting to reconnect after a failed master event read");
#ifdef SIGNAL_WITH_VIO_CLOSE
thd->clear_active_vio();
#endif
@@ -3641,7 +3641,7 @@ max_allowed_packet",
reconnect after a failed read");
goto err;
}
- thd->proc_info = "Reconnecting after a failed master event read";
+ thd_proc_info(thd, "Reconnecting after a failed master event read");
if (!suppress_warnings)
sql_print_information("Slave I/O thread: Failed reading log event, \
reconnecting to retry, log '%s' position %s", IO_RPL_LOG_NAME,
@@ -3658,7 +3658,7 @@ reconnect done to recover from failed read");
} // if (event_len == packet_error)
retry_count=0; // ok event, reset retry counter
- thd->proc_info = "Queueing master event to the relay log";
+ thd_proc_info(thd, "Queueing master event to the relay log");
if (queue_event(mi,(const char*)mysql->net.read_pos + 1,
event_len))
{
@@ -3740,7 +3740,7 @@ err:
mi->mysql=0;
}
write_ignored_events_info_to_relay_log(thd, mi);
- thd->proc_info = "Waiting for slave mutex on exit";
+ thd_proc_info(thd, "Waiting for slave mutex on exit");
pthread_mutex_lock(&mi->run_lock);
/* Forget the relay log's format */
@@ -3912,7 +3912,7 @@ Slave SQL thread aborted. Can't execute init_slave query");
while (!sql_slave_killed(thd,rli))
{
- thd->proc_info = "Reading event from the relay log";
+ thd_proc_info(thd, "Reading event from the relay log");
DBUG_ASSERT(rli->sql_thd == thd);
THD_CHECK_SENTRY(thd);
if (exec_relay_log_event(thd,rli))
@@ -3944,7 +3944,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
thd->query= 0;
thd->query_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
- thd->proc_info = "Waiting for slave mutex on exit";
+ thd_proc_info(thd, "Waiting for slave mutex on exit");
pthread_mutex_lock(&rli->run_lock);
/* We need data_lock, at least to wake up any waiting master_pos_wait() */
pthread_mutex_lock(&rli->data_lock);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index c6e49fae801..c0d24a5afdc 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2387,9 +2387,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
m_lex->unit.cleanup();
- THD_PROC_INFO(thd, "closing tables");
+ thd_proc_info(thd, "closing tables");
close_thread_tables(thd);
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
if (m_lex->query_tables_own_last)
{
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 636006ea7c2..11cc1584780 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -306,7 +306,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
*/
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
- THD_PROC_INFO(thd, "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,
@@ -348,7 +348,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0;
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
pthread_mutex_unlock(&thd->mysys_var->mutex);
}
DBUG_RETURN(result);
@@ -549,7 +549,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
good idea to turn off OPTION_TABLE_LOCK flag.
*/
DBUG_ASSERT(thd->lex->requires_prelocking());
- thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
+ thd->options&= ~(OPTION_TABLE_LOCK);
}
DBUG_VOID_RETURN;
@@ -1070,7 +1070,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(thd, "Waiting for table");
+ thd_proc_info(thd, "Waiting for table");
if (!thd->killed)
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
@@ -1078,7 +1078,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(thd, proc_info);
+ thd_proc_info(thd, proc_info);
pthread_mutex_unlock(&thd->mysys_var->mutex);
DBUG_VOID_RETURN;
}
@@ -1783,7 +1783,7 @@ bool wait_for_tables(THD *thd)
bool result;
DBUG_ENTER("wait_for_tables");
- THD_PROC_INFO(thd, "Waiting for tables");
+ thd_proc_info(thd, "Waiting for tables");
pthread_mutex_lock(&LOCK_open);
while (!thd->killed)
{
@@ -1799,12 +1799,12 @@ bool wait_for_tables(THD *thd)
else
{
/* Now we can open all tables without any interference */
- THD_PROC_INFO(thd, "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(thd, 0);
+ thd_proc_info(thd, 0);
DBUG_RETURN(result);
}
@@ -2103,7 +2103,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
restart:
*counter= 0;
query_tables_last_own= 0;
- THD_PROC_INFO(thd, "Opening tables");
+ thd_proc_info(thd, "Opening tables");
/*
If we are not already executing prelocked statement and don't have
@@ -2283,7 +2283,7 @@ process_view_routines:
}
err:
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block
if (query_tables_last_own)
@@ -2357,7 +2357,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
bool refresh;
DBUG_ENTER("open_ltable");
- THD_PROC_INFO(thd, "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;
@@ -2391,7 +2391,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
table= 0;
}
}
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
DBUG_RETURN(table);
}
@@ -2611,7 +2611,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
{
if (thd->lex->requires_prelocking())
{
- thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
+ thd->options&= ~(OPTION_TABLE_LOCK);
thd->in_lock_tables=0;
}
DBUG_RETURN(-1);
@@ -2644,7 +2644,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
ha_rollback_stmt(thd);
mysql_unlock_tables(thd, thd->locked_tables);
thd->locked_tables= 0;
- thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
+ thd->options&= ~(OPTION_TABLE_LOCK);
DBUG_RETURN(-1);
}
}
@@ -5436,7 +5436,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
List_iterator<Item_func_match> li(*(select_lex->ftfunc_list));
Item_func_match *ifm;
DBUG_PRINT("info",("Performing FULLTEXT search"));
- THD_PROC_INFO(thd, "FULLTEXT initialization");
+ thd_proc_info(thd, "FULLTEXT initialization");
while ((ifm=li++))
ifm->init_search(no_order);
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 7340da5ce93..cb65eb562a2 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -315,13 +315,13 @@ TODO list:
#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
(ulong)(M))); pthread_mutex_unlock(M);}
#define RW_WLOCK(M) {DBUG_PRINT("lock", ("rwlock wlock 0x%lx",(ulong)(M))); \
- if (!rw_wrlock(M)) DBUG_PRINT("lock", ("rwlock wlock ok")) \
+ if (!rw_wrlock(M)) DBUG_PRINT("lock", ("rwlock wlock ok")); \
else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); }
#define RW_RLOCK(M) {DBUG_PRINT("lock", ("rwlock rlock 0x%lx", (ulong)(M))); \
- if (!rw_rdlock(M)) DBUG_PRINT("lock", ("rwlock rlock ok")) \
+ if (!rw_rdlock(M)) DBUG_PRINT("lock", ("rwlock rlock ok")); \
else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); }
#define RW_UNLOCK(M) {DBUG_PRINT("lock", ("rwlock unlock 0x%lx",(ulong)(M))); \
- if (!rw_unlock(M)) DBUG_PRINT("lock", ("rwlock unlock ok")) \
+ if (!rw_unlock(M)) DBUG_PRINT("lock", ("rwlock unlock ok")); \
else DBUG_PRINT("lock", ("rwlock unlock FAILED %d", errno)); }
#define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); \
pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));}
@@ -688,7 +688,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");
+ 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
@@ -726,7 +726,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");
+ thd_proc_info(thd, "storing result in query cache");
DUMP(&query_cache);
BLOCK_LOCK_WR(query_block);
Query_cache_query *header= query_block->query();
@@ -1091,7 +1091,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
DBUG_PRINT("qcache", ("No active database"));
}
- THD_PROC_INFO(thd, "checking query cache for query");
+ 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);
@@ -1167,7 +1167,7 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
}
// Check access;
- THD_PROC_INFO(thd, "checking privileges on cached query");
+ 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++)
@@ -1260,7 +1260,7 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
Send cached result to client
*/
#ifndef EMBEDDED_LIBRARY
- THD_PROC_INFO(thd, "sending cached result to client");
+ thd_proc_info(thd, "sending cached result to client");
do
{
DBUG_PRINT("qcache", ("Results (len: %lu used: %lu headers: %lu)",
@@ -1342,7 +1342,7 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
DBUG_ENTER("Query_cache::invalidate (changed table list)");
if (tables_used)
{
- THD_PROC_INFO(thd, "invalidating query cache entries (table list)");
+ thd_proc_info(thd, "invalidating query cache entries (table list)");
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size > 0 && !flush_in_progress)
{
@@ -1377,7 +1377,7 @@ void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
DBUG_ENTER("Query_cache::invalidate_locked_for_write");
if (tables_used)
{
- THD_PROC_INFO(thd, "invalidating query cache entries (table)");
+ thd_proc_info(thd, "invalidating query cache entries (table)");
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size > 0 && !flush_in_progress)
{
@@ -1427,7 +1427,7 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size > 0 && !flush_in_progress)
{
- THD_PROC_INFO(thd, "invalidating query cache entries (key)");
+ 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
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index fc9ec55f54a..4878acabbb2 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -247,7 +247,9 @@ THD::THD()
init();
/* Initialize sub structures */
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
+#ifdef ENABLED_PROFILING
profiling.set_thd(this);
+#endif
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,7 +332,6 @@ 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;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 582d6afe51c..3795627fd58 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -521,6 +521,7 @@ struct system_variables
ulong optimizer_prune_level;
ulong optimizer_search_depth;
ulong preload_buff_size;
+ ulong profiling_history_size;
ulong query_cache_type;
ulong read_buff_size;
ulong read_rnd_buff_size;
@@ -1154,6 +1155,9 @@ public:
Points to info-string that we show in SHOW PROCESSLIST
You are supposed to update thd->proc_info only if you have coded
a time-consuming piece that MySQL can get stuck in for a long time.
+
+ Set it using the thd_proc_info(THD *thread, const char *message)
+ macro/function.
*/
const char *proc_info;
@@ -1308,8 +1312,9 @@ public:
List <MYSQL_ERROR> warn_list;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count;
-
+#ifdef ENABLED_PROFILING
PROFILING profiling;
+#endif
/*
Id of current query. Statement can be reused to execute several queries
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index d02bc89068e..ac290a50b9b 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -54,7 +54,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
table->file->print_error(error, MYF(0));
DBUG_RETURN(error);
}
- THD_PROC_INFO(thd, "init");
+ thd_proc_info(thd, "init");
table->map=1;
if (mysql_prepare_delete(thd, table_list, &conds))
@@ -205,7 +205,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
deleted=0L;
init_ftfuncs(thd, select_lex, 1);
- THD_PROC_INFO(thd, "updating");
+ thd_proc_info(thd, "updating");
if (table->triggers)
table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
@@ -261,7 +261,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
}
if (thd->killed && !error)
error= 1; // Aborted
- THD_PROC_INFO(thd, "end");
+ thd_proc_info(thd, "end");
end_read_record(&info);
free_io_cache(table); // Will not do any harm
if (options & OPTION_QUICK)
@@ -485,7 +485,7 @@ multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
DBUG_ENTER("multi_delete::prepare");
unit= u;
do_delete= 1;
- THD_PROC_INFO(thd, "deleting from main table");
+ thd_proc_info(thd, "deleting from main table");
DBUG_RETURN(0);
}
@@ -749,7 +749,7 @@ int multi_delete::do_deletes()
bool multi_delete::send_eof()
{
- THD_PROC_INFO(thd, "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
@@ -758,7 +758,7 @@ bool multi_delete::send_eof()
local_error= local_error || error;
/* reset used flags */
- THD_PROC_INFO(thd, "end");
+ thd_proc_info(thd, "end");
/*
We must invalidate the query cache before binlog writing and
@@ -903,7 +903,7 @@ end:
/* Probably InnoDB table */
ulonglong save_options= thd->options;
table_list->lock_type= TL_WRITE;
- thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
+ thd->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
ha_enable_transaction(thd, FALSE);
mysql_init_select(thd->lex);
error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0,
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index c2e30c47cfb..b384098bc00 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -397,7 +397,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (res || thd->is_fatal_error)
DBUG_RETURN(TRUE);
- THD_PROC_INFO(thd, "init");
+ thd_proc_info(thd, "init");
thd->used_tables=0;
values= its++;
@@ -470,7 +470,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
error=0;
id=0;
- THD_PROC_INFO(thd, "update");
+ thd_proc_info(thd, "update");
if (duplic != DUP_ERROR || ignore)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
if (duplic == DUP_REPLACE)
@@ -676,7 +676,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->lock=0;
}
}
- THD_PROC_INFO(thd, "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
@@ -1407,7 +1407,7 @@ I_List<delayed_insert> delayed_threads;
delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list)
{
- THD_PROC_INFO(thd, "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;
@@ -1444,7 +1444,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
*/
if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads)
DBUG_RETURN(0);
- THD_PROC_INFO(thd, "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.
@@ -1486,13 +1486,13 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
}
/* Wait until table is open */
- THD_PROC_INFO(thd, "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(thd, "got old table");
+ thd_proc_info(thd, "got old table");
if (tmp->thd.killed)
{
if (tmp->thd.is_fatal_error)
@@ -1552,13 +1552,13 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
tables_in_use++;
if (!thd.lock) // Table is not locked
{
- THD_PROC_INFO(client_thd, "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);
}
- THD_PROC_INFO(client_thd, "got handler lock");
+ thd_proc_info(client_thd, "got handler lock");
if (client_thd->killed)
goto error;
if (dead)
@@ -1576,7 +1576,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
bytes. Since the table copy is used for creating one record only,
the other record buffers and alignment are unnecessary.
*/
- THD_PROC_INFO(client_thd, "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);
@@ -1656,11 +1656,11 @@ static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, bool igno
delayed_insert *di=thd->di;
DBUG_ENTER("write_delayed");
- THD_PROC_INFO(thd, "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(thd, "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;
@@ -1869,7 +1869,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
/* Information for pthread_kill */
di->thd.mysys_var->current_mutex= &di->mutex;
di->thd.mysys_var->current_cond= &di->cond;
- THD_PROC_INFO(&(di->thd), "Waiting for INSERT");
+ thd_proc_info(&(di->thd), "Waiting for INSERT");
DBUG_PRINT("info",("Waiting for someone to insert rows"));
while (!thd->killed)
@@ -1904,7 +1904,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
pthread_mutex_unlock(&di->thd.mysys_var->mutex);
pthread_mutex_lock(&di->mutex);
}
- THD_PROC_INFO(&(di->thd), 0);
+ thd_proc_info(&(di->thd), 0);
if (di->tables_in_use && ! thd->lock)
{
@@ -2023,7 +2023,7 @@ bool delayed_insert::handle_inserts(void)
table->next_number_field=table->found_next_number_field;
- THD_PROC_INFO(&thd, "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 */
@@ -2031,7 +2031,7 @@ bool delayed_insert::handle_inserts(void)
goto err;
}
- THD_PROC_INFO(&thd, "insert");
+ thd_proc_info(&thd, "insert");
max_rows= delayed_insert_limit;
if (thd.killed || table->s->version != refresh_version)
{
@@ -2149,7 +2149,7 @@ bool delayed_insert::handle_inserts(void)
{
if (tables_in_use)
pthread_cond_broadcast(&cond_client); // If waiting clients
- THD_PROC_INFO(&thd, "reschedule");
+ thd_proc_info(&thd, "reschedule");
pthread_mutex_unlock(&mutex);
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
{
@@ -2168,14 +2168,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(&thd, "insert");
+ thd_proc_info(&thd, "insert");
}
if (tables_in_use)
pthread_cond_broadcast(&cond_client); // If waiting clients
}
}
- THD_PROC_INFO(&thd, 0);
+ thd_proc_info(&thd, 0);
table->next_number_field=0;
pthread_mutex_unlock(&mutex);
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index da562babea1..47fe2e8ac0e 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -173,8 +173,9 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->proc_list.first= 0;
lex->escape_used= FALSE;
lex->reset_query_tables_list(FALSE);
+#ifdef ENABLED_PROFILING
lex->profile_options= PROFILE_NONE;
-
+#endif
lex->nest_level=0 ;
lex->allow_sum_func= 0;
lex->in_sum_func= NULL;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 96ce02f7409..22f9d6026f9 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -95,8 +95,12 @@ enum enum_sql_command {
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 !!! */
+ /*
+ When a command is added here, be sure it's also added in mysqld.cc
+ in "struct show_var_st status_vars[]= {" ...
+ */
+ /* This should be the last !!! */
SQLCOM_END
};
@@ -939,8 +943,9 @@ typedef struct st_lex : public Query_tables_list
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 profile_options;
uint uint_geom_type;
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 779db99a4ff..449d57c2b2d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -140,14 +140,14 @@ static bool end_active_trans(THD *thd)
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
OPTION_TABLE_LOCK))
{
- DBUG_PRINT("info",("options: 0x%lx", (ulong) thd->options));
+ DBUG_PRINT("info",("options: 0x%llx", thd->options));
/* Safety if one did "drop table" on locked tables */
if (!thd->locked_tables)
thd->options&= ~OPTION_TABLE_LOCK;
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (ha_commit(thd))
error=1;
- thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->options&= ~(OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
}
DBUG_RETURN(error);
}
@@ -171,7 +171,7 @@ static bool begin_trans(THD *thd)
else
{
LEX *lex= thd->lex;
- thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
+ thd->options= ((thd->options & ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
@@ -1058,7 +1058,7 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var,
Vio* save_vio;
ulong save_client_capabilities;
- THD_PROC_INFO(thd, "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
@@ -1158,7 +1158,7 @@ pthread_handler_t handle_one_connection(void *arg)
net->compress=1; // Use compression
thd->version= refresh_version;
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
thd->command= COM_SLEEP;
thd->set_time();
thd->init_for_queries();
@@ -1175,7 +1175,7 @@ pthread_handler_t handle_one_connection(void *arg)
sctx->host_or_ip, "init_connect command failed");
sql_print_warning("%s", net->last_error);
}
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
thd->set_time();
thd->init_for_queries();
}
@@ -1258,7 +1258,7 @@ pthread_handler_t handle_bootstrap(void *arg)
if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
- THD_PROC_INFO(thd, 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));
@@ -1447,7 +1447,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion)
*/
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
res= ha_commit(thd);
- thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->options&= ~(OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
break;
case COMMIT_RELEASE:
do_release= 1; /* fall through */
@@ -1464,7 +1464,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion)
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (ha_rollback(thd))
res= -1;
- thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->options&= ~(OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
if (!res && (completion == ROLLBACK_AND_CHAIN))
res= begin_trans(thd);
break;
@@ -2105,7 +2105,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (thd->lock || thd->open_tables || thd->derived_tables ||
thd->prelocked_mode)
{
- THD_PROC_INFO(thd, "closing tables");
+ thd_proc_info(thd, "closing tables");
close_thread_tables(thd); /* Free tables */
}
/*
@@ -2128,9 +2128,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
log_slow_statement(thd);
- THD_PROC_INFO(thd, "cleaning up");
+ thd_proc_info(thd, "cleaning up");
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list
- THD_PROC_INFO(thd, 0);
+ thd_proc_info(thd, 0);
thd->command=COM_SLEEP;
thd->query=0;
thd->query_length=0;
@@ -2163,6 +2163,8 @@ void log_slow_statement(THD *thd)
*/
if (thd->enable_slow_log && !thd->user_time)
{
+ thd_proc_info(thd, "logging slow query");
+
if ((ulong) (thd->start_time - thd->time_after_lock) >
thd->variables.long_query_time ||
(thd->server_status &
@@ -2171,7 +2173,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_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);
}
@@ -2698,16 +2700,33 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHOW_PROFILES:
{
+#ifdef ENABLED_PROFILING
thd->profiling.store();
thd->profiling.discard();
res= thd->profiling.show_profiles();
+ if (res)
+ goto error;
+#else
+ my_error(ER_FEATURE_DISABLED, MYF(0), "query profiling", "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()
- res= thd->profiling.show_last(lex->profile_options);
+ 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), "query profiling", "enable-profiling");
+ goto error;
+#endif
break;
}
case SQLCOM_SHOW_NEW_MASTER:
@@ -3557,7 +3576,7 @@ end_with_restore_list:
if (add_item_to_list(thd, new Item_null()))
goto error;
- THD_PROC_INFO(thd, "init");
+ thd_proc_info(thd, "init");
if ((res= open_and_lock_tables(thd, all_tables)))
break;
@@ -3721,7 +3740,7 @@ end_with_restore_list:
if (thd->options & OPTION_TABLE_LOCK)
{
end_active_trans(thd);
- thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
+ thd->options&= ~(OPTION_TABLE_LOCK);
}
if (thd->global_read_lock)
unlock_global_read_lock(thd);
@@ -3747,7 +3766,7 @@ end_with_restore_list:
send_ok(thd);
}
else
- thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
+ thd->options&= ~(OPTION_TABLE_LOCK);
thd->in_lock_tables=0;
break;
case SQLCOM_CREATE_DB:
@@ -4847,7 +4866,7 @@ create_sp_error:
thd->transaction.xid_state.xa_state=XA_ACTIVE;
thd->transaction.xid_state.xid.set(thd->lex->xid);
xid_cache_insert(&thd->transaction.xid_state);
- thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
+ thd->options= ((thd->options & ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
send_ok(thd);
@@ -4941,7 +4960,7 @@ create_sp_error:
xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
- thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->options&= ~(OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state=XA_NOTR;
@@ -4971,7 +4990,7 @@ create_sp_error:
my_error(ER_XAER_RMERR, MYF(0));
else
send_ok(thd);
- thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->options&= ~(OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
xid_cache_delete(&thd->transaction.xid_state);
thd->transaction.xid_state.xa_state=XA_NOTR;
@@ -4986,7 +5005,7 @@ create_sp_error:
send_ok(thd);
break;
}
- THD_PROC_INFO(thd, "query end");
+ thd_proc_info(thd, "query end");
/* Two binlog-related cleanups: */
/*
@@ -5157,8 +5176,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
else
save_priv= &dummy;
- THD_PROC_INFO(thd, "checking permissions");
-
+ thd_proc_info(thd, "checking permissions");
if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
{
DBUG_PRINT("error",("No database"));
@@ -5605,6 +5623,9 @@ mysql_init_query(THD *thd, uchar *buf, uint length)
DBUG_ENTER("mysql_init_query");
lex_start(thd, buf, length);
mysql_reset_thd_for_next_command(thd);
+#ifdef ENABLED_PROFILING
+ thd->profiling.reset();
+#endif
DBUG_VOID_RETURN;
}
@@ -5646,7 +5667,9 @@ void mysql_reset_thd_for_next_command(THD *thd)
thd->total_warn_count=0; // Warnings for this query
thd->rand_used= 0;
thd->sent_row_count= thd->examined_row_count= 0;
+#ifdef ENABLED_PROFILING
thd->profiling.reset();
+#endif
}
DBUG_VOID_RETURN;
}
@@ -5870,7 +5893,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
query_cache_abort(&thd->net);
lex->unit.cleanup();
}
- THD_PROC_INFO(thd, "freeing items");
+ thd_proc_info(thd, "freeing items");
thd->end_statement();
thd->cleanup_after_query();
DBUG_ASSERT(thd->change_list.is_empty());
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 152cc3aa385..83ddb9c9212 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2222,6 +2222,7 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute")))
DBUG_VOID_RETURN;
+ thd->profiling.set_query_source(stmt->query, stmt->query_length);
DBUG_PRINT("exec_query", ("%s", stmt->query));
DBUG_PRINT("info",("stmt: %p", stmt));
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index 98a5f8d7576..e9b6ef0b522 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -14,149 +14,282 @@
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"
+#include "my_sys.h"
+
+#define TIME_FLOAT_DIGITS 7
+#define MAX_QUERY_LENGTH 300
+
+bool schema_table_store_record(THD *thd, TABLE *table);
+
+/* Reserved for systems that can't record the function name in source. */
+const char *_db_func_= "<unknown>";
+
+/**
+ Connects Information_Schema and Profiling.
+*/
+int fill_query_profile_statistics_info(THD *thd, struct st_table_list *tables,
+ Item *cond)
+{
+#ifdef ENABLED_PROFILING
+ return(thd->profiling.fill_statistics_info(thd, tables, cond));
+#else
+ return(1);
+#endif
+}
-#define RUSAGE_USEC(tv) ((tv).tv_sec*1000000 + (tv).tv_usec)
+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},
+ {NULL, 0, MYSQL_TYPE_STRING, 0, true, NULL}
+};
+
+#ifdef ENABLED_PROFILING
+
+#define RUSAGE_USEC(tv) ((tv).tv_sec*1000*1000 + (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)
+ :profile(NULL), status(NULL), function(NULL), file(NULL), line(0),
+ time_usecs(0.0), allocated_status_memory(NULL)
{
collect();
}
-PROFILE_ENTRY::PROFILE_ENTRY(PROFILE *profile_arg, const char *status_arg)
- :profile(profile_arg), function(NULL), file(NULL), line(0)
+PROFILE_ENTRY::PROFILE_ENTRY(QUERY_PROFILE *profile_arg, const char *status_arg)
+ :profile(profile_arg)
{
collect();
- if (status_arg)
- set_status(status_arg);
+ set_status(status_arg, NULL, NULL, 0);
}
-PROFILE_ENTRY::PROFILE_ENTRY(PROFILE *profile_arg, const char *status_arg,
+PROFILE_ENTRY::PROFILE_ENTRY(QUERY_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;
+ set_status(status_arg, function_arg, file_arg, line_arg);
}
PROFILE_ENTRY::~PROFILE_ENTRY()
{
- if (status)
- free(status);
- if (function)
- free(function);
- if (file)
- free(file);
+ if (allocated_status_memory != NULL)
+ my_free(allocated_status_memory, MYF(0));
+ status= function= file= NULL;
}
-void PROFILE_ENTRY::set_status(const char *status_arg)
+void PROFILE_ENTRY::set_status(const char *status_arg, const char *function_arg, const char *file_arg, unsigned int line_arg)
{
- status= strdup_root(&profile->profiling->root, status_arg);
+ size_t sizes[3]; /* 3 == status+function+file */
+ char *cursor;
+
+ /*
+ Compute all the space we'll need to allocate one block for everything
+ we'll need, instead of N mallocs.
+ */
+ if (status_arg != NULL)
+ sizes[0]= strlen(status_arg) + 1;
+ else
+ sizes[0]= 0;
+
+ if (function_arg != NULL)
+ sizes[1]= strlen(function_arg) + 1;
+ else
+ sizes[1]= 0;
+
+ if (file_arg != NULL)
+ sizes[2]= strlen(file_arg) + 1;
+ else
+ sizes[2]= 0;
+
+ allocated_status_memory= (char *) my_malloc(sizes[0] + sizes[1] + sizes[2], MYF(0));
+ DBUG_ASSERT(allocated_status_memory != NULL);
+
+ cursor= allocated_status_memory;
+
+ if (status_arg != NULL)
+ {
+ strcpy(cursor, status_arg);
+ status= cursor;
+ cursor+= sizes[0];
+ }
+ else
+ status= NULL;
+
+ if (function_arg != NULL)
+ {
+ strcpy(cursor, function_arg);
+ function= cursor;
+ cursor+= sizes[1];
+ }
+ else
+ function= NULL;
+
+ if (file_arg != NULL)
+ {
+ strcpy(cursor, file_arg);
+ file= cursor;
+ cursor+= sizes[2];
+ }
+ else
+ file= NULL;
+
+ line= line_arg;
}
void PROFILE_ENTRY::collect()
{
- time= my_getsystime();
+ time_usecs= (double) my_getsystime() / 10.0; /* 1 sec was 1e7, now is 1e6 */
+#ifdef HAVE_GETRUSAGE
getrusage(RUSAGE_SELF, &rusage);
+#endif
}
-PROFILE::PROFILE(PROFILING *profiling_arg)
- :profiling(profiling_arg)
+QUERY_PROFILE::QUERY_PROFILE(PROFILING *profiling_arg, char *query_source_arg,
+ uint query_length_arg)
+ :profiling(profiling_arg), server_query_id(-1), profiling_query_id(-1),
+ query_source(NULL)
{
profile_end= &profile_start;
+ set_query_source(query_source_arg, query_length_arg);
}
-PROFILE::~PROFILE()
+void QUERY_PROFILE::set_query_source(char *query_source_arg,
+ uint query_length_arg)
{
+ /* Truncate to avoid DoS attacks. */
+ uint length= min(MAX_QUERY_LENGTH, query_length_arg);
+ /* TODO?: Provide a way to include the full text, as in SHOW PROCESSLIST. */
+
+ if (query_source_arg != NULL)
+ query_source= my_strdup_with_length(query_source_arg, length, MYF(0));
+}
+
+QUERY_PROFILE::~QUERY_PROFILE()
+{
+ PROFILE_ENTRY *entry;
+ List_iterator<PROFILE_ENTRY> it(entries);
+ while ((entry= it++) != NULL)
+ delete entry;
entries.empty();
+
+ if (query_source != NULL)
+ my_free(query_source, MYF(0));
}
-void PROFILE::status(const char *status_arg,
- const char *function_arg=NULL,
- const char *file_arg=NULL, unsigned int line_arg=0)
+void QUERY_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");
+ PROFILE_ENTRY *prof;
+ MEM_ROOT *saved_mem_root;
+ DBUG_ENTER("QUERY_PROFILE::status");
/* Blank status. Just return, and thd->proc_info will be set blank later. */
- if (unlikely(!status_arg))
+ if (unlikely(status_arg == NULL))
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))))
+ if (likely((thd->proc_info != NULL) &&
+ ((thd->proc_info == status_arg) ||
+ (strcmp(thd->proc_info, status_arg) == 0))))
+ {
DBUG_VOID_RETURN;
+ }
/* Is this the same query as our profile currently contains? */
- if (unlikely(thd->query_id != query_id && !thd->spcont))
+ if (unlikely((thd->query_id != server_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.
+ mysqld cleans up after the query.
+
+ The "entries" list allocates is memory from the current thd's mem_root.
+ We substitute our mem_root temporarily so that we intercept those
+ allocations into our own mem_root.
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)))
+ saved_mem_root= thd->mem_root;
+ thd->mem_root= &profiling->mem_root;
+ //thd->mem_root= NULL;
+
+ 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 {
+ }
+ else
+ {
if ((profile_end= prof= new PROFILE_ENTRY(this, status_arg)))
entries.push_back(prof);
}
- thd->mem_root= old_root;
+
+ /* Restore mem_root */
+ thd->mem_root= saved_mem_root;
DBUG_VOID_RETURN;
}
-void PROFILE::reset()
+void QUERY_PROFILE::reset()
{
- DBUG_ENTER("PROFILE::reset");
- if (profiling->thd->query_id != query_id)
+ DBUG_ENTER("QUERY_PROFILE::reset");
+ if (likely(profiling->thd->query_id != server_query_id))
{
- query_id= profiling->thd->query_id;
+ server_query_id= profiling->thd->query_id; /* despite name, is global */
profile_start.collect();
+
+ PROFILE_ENTRY *entry;
+ List_iterator<PROFILE_ENTRY> it(entries);
+ while ((entry= it++) != NULL)
+ delete entry;
entries.empty();
}
DBUG_VOID_RETURN;
}
-bool PROFILE::show(uint options)
+bool QUERY_PROFILE::show(uint options)
{
- PROFILE_ENTRY *prof;
THD *thd= profiling->thd;
- PROFILE_ENTRY *ps= &profile_start;
List<Item> field_list;
- DBUG_ENTER("PROFILE::show");
+ 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("Time_elapsed", 20,
- MYSQL_TYPE_LONGLONG));
+ 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", 20,
- MYSQL_TYPE_LONGLONG));
- field_list.push_back(new Item_return_int("CPU_system", 20,
- MYSQL_TYPE_LONGLONG));
+ 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)
@@ -200,7 +333,7 @@ bool PROFILE::show(uint options)
field_list.push_back(new Item_return_int("Swaps", 10, MYSQL_TYPE_LONG));
}
- if(options & PROFILE_SOURCE)
+ if (options & PROFILE_SOURCE)
{
field_list.push_back(new Item_empty_string("Source_function",
MYSQL_ERRMSG_SIZE));
@@ -214,146 +347,231 @@ bool PROFILE::show(uint options)
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;
- Protocol *protocol=thd->protocol;
-
unit->set_limit(sel);
+ double last_time= profile_start.time_usecs;
+#ifdef HAVE_GETRUSAGE
+ struct rusage *last_rusage= &(profile_start.rusage);
+#endif
List_iterator<PROFILE_ENTRY> it(entries);
- ulonglong last_time= ps->time;
- while ((prof= it++))
+ PROFILE_ENTRY *entry;
+ while ((entry= it++) != NULL)
{
+#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();
- protocol->store(prof->status, strlen(prof->status), system_charset_info);
- protocol->store((ulonglong)(prof->time - ps->time)/10);
+ protocol->store(entry->status, strlen(entry->status), system_charset_info);
+ protocol->store((double)(entry->time_usecs - last_time)/(1000.0*1000),
+ (uint32) TIME_FLOAT_DIGITS-1, &elapsed);
+ //protocol->store((double)(entry->time - last_time)/(1000*1000*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));
+#ifdef HAVE_GETRUSAGE
+ String cpu_utime, cpu_stime;
+ protocol->store((double)(RUSAGE_DIFF_USEC(rusage->ru_utime,
+ last_rusage->ru_utime))/(1000.0*1000),
+ (uint32) TIME_FLOAT_DIGITS-1, &cpu_utime);
+ protocol->store((double)(RUSAGE_DIFF_USEC(rusage->ru_stime,
+ last_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)
{
- protocol->store((uint32)(prof->rusage.ru_nvcsw - ps->rusage.ru_nvcsw));
- protocol->store((uint32)(prof->rusage.ru_nivcsw - ps->rusage.ru_nivcsw));
+#ifdef HAVE_GETRUSAGE
+ protocol->store((uint32)(rusage->ru_nvcsw - last_rusage->ru_nvcsw));
+ protocol->store((uint32)(rusage->ru_nivcsw - last_rusage->ru_nivcsw));
+#else
+ protocol->store_null();
+ protocol->store_null();
+#endif
}
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));
+#ifdef HAVE_GETRUSAGE
+ protocol->store((uint32)(rusage->ru_inblock - last_rusage->ru_inblock));
+ protocol->store((uint32)(rusage->ru_oublock - last_rusage->ru_oublock));
+#else
+ protocol->store_null();
+ protocol->store_null();
+#endif
}
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));
+#ifdef HAVE_GETRUSAGE
+ protocol->store((uint32)(rusage->ru_msgsnd - last_rusage->ru_msgsnd));
+ protocol->store((uint32)(rusage->ru_msgrcv - last_rusage->ru_msgrcv));
+#else
+ protocol->store_null();
+ protocol->store_null();
+#endif
}
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));
+#ifdef HAVE_GETRUSAGE
+ protocol->store((uint32)(rusage->ru_majflt - last_rusage->ru_majflt));
+ protocol->store((uint32)(rusage->ru_minflt - last_rusage->ru_minflt));
+#else
+ protocol->store_null();
+ protocol->store_null();
+#endif
}
if (options & PROFILE_SWAPS)
{
- protocol->store((uint32)(prof->rusage.ru_nswap - ps->rusage.ru_nswap));
+#ifdef HAVE_GETRUSAGE
+ protocol->store((uint32)(rusage->ru_nswap - last_rusage->ru_nswap));
+#else
+ protocol->store_null();
+#endif
}
if (options & PROFILE_SOURCE)
{
- if(prof->function && prof->file)
+ if ((entry->function != NULL) && (entry->file != NULL))
{
- protocol->store(prof->function, strlen(prof->function), system_charset_info);
- protocol->store(prof->file, strlen(prof->file), system_charset_info);
- protocol->store(prof->line);
+ protocol->store(entry->function, strlen(entry->function),
+ system_charset_info);
+ protocol->store(entry->file, strlen(entry->file), system_charset_info);
+ protocol->store(entry->line);
} else {
- protocol->store("(unknown)", 10, system_charset_info);
- protocol->store("(unknown)", 10, system_charset_info);
- protocol->store((uint32) 0);
+ protocol->store_null();
+ protocol->store_null();
+ protocol->store_null();
}
}
if (protocol->write())
DBUG_RETURN(TRUE);
- last_time= prof->time;
+
+ last_time= entry->time_usecs;
+#ifdef HAVE_GETRUSAGE
+ last_rusage= &(entry->rusage);
+#endif
+
}
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)
+ :profile_id_counter(0), keeping(1), current(NULL), last(NULL)
{
- init_sql_alloc(&root,
+ init_sql_alloc(&mem_root,
PROFILE_ALLOC_BLOCK_SIZE,
PROFILE_ALLOC_PREALLOC_SIZE);
}
PROFILING::~PROFILING()
{
- free_root(&root, MYF(0));
+ QUERY_PROFILE *prof;
+
+ List_iterator<QUERY_PROFILE> it(history);
+ while ((prof= it++) != NULL)
+ delete prof;
+ history.empty();
+
+ if (current != NULL)
+ delete current;
+
+ free_root(&mem_root, MYF(0));
}
-void PROFILING::status(const char *status_arg,
- const char *function_arg,
- const char *file_arg, unsigned int line_arg)
+void PROFILING::status_change(const char *status_arg,
+ const char *function_arg,
+ const char *file_arg, unsigned int line_arg)
{
- DBUG_ENTER("PROFILING::status");
+ DBUG_ENTER("PROFILING::status_change");
- if(!current)
- reset();
+ if (unlikely((thd->options & OPTION_PROFILING) != 0))
+ {
+ if (unlikely(current == NULL))
+ reset();
+
+ DBUG_ASSERT(current != NULL);
- 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;
+ MEM_ROOT *saved_mem_root;
DBUG_ENTER("PROFILING::store");
- if (last && current && (last->query_id == current->query_id))
+ /* Already stored */
+ if (unlikely((last != NULL) &&
+ (current != NULL) &&
+ (last->server_query_id == current->server_query_id)))
+ {
DBUG_VOID_RETURN;
+ }
- if (history.elements > 10) /* XXX: global/session var */
+ while (history.elements > thd->variables.profiling_history_size)
{
- PROFILE *tmp= history.pop();
+ QUERY_PROFILE *tmp= history.pop();
delete tmp;
}
- old_root= thd->mem_root;
- thd->mem_root= &root;
+ /*
+ Switch out memory roots so that we're sure that we keep what we need
+
+ The "history" list implementation allocates its memory in the current
+ thd's mem_root. We substitute our mem_root temporarily so that we
+ intercept those allocations into our own mem_root.
+ */
+
+ saved_mem_root= thd->mem_root;
+ thd->mem_root= &mem_root;
- if (current)
+ if (current != NULL)
{
- if (keeping && (!current->entries.is_empty())) {
- last= current;
+ if (keeping &&
+ (current->query_source != NULL) &&
+ (current->query_source[0] != '\0') &&
+ (!current->entries.is_empty()))
+ {
+ current->profiling_query_id= next_profile_id(); /* assign an id */
+
+ last= current; /* never contains something that is not in the history. */
history.push_back(current);
current= NULL;
- } else {
+ }
+ else
+ {
delete current;
+ current= NULL;
}
}
- current= new PROFILE(this);
- thd->mem_root= old_root;
+ DBUG_ASSERT(current == NULL);
+ current= new QUERY_PROFILE(this, thd->query, thd->query_length);
+
+ /* Restore memory root */
+ thd->mem_root= saved_mem_root;
DBUG_VOID_RETURN;
}
@@ -364,8 +582,8 @@ void PROFILING::reset()
store();
- current->reset();
- /*free_root(&root, MYF(0));*/
+ if (current != NULL)
+ current->reset();
keep();
DBUG_VOID_RETURN;
@@ -373,15 +591,15 @@ void PROFILING::reset()
bool PROFILING::show_profiles()
{
- PROFILE *prof;
+ DBUG_ENTER("PROFILING::show_profiles");
+ QUERY_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. */
+ field_list.push_back(new Item_return_int("Duration", TIME_FLOAT_DIGITS-1,
+ MYSQL_TYPE_DOUBLE));
+ field_list.push_back(new Item_empty_string("Query", 40));
if (thd->protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
@@ -390,13 +608,15 @@ bool PROFILING::show_profiles()
SELECT_LEX *sel= &thd->lex->select_lex;
SELECT_LEX_UNIT *unit= &thd->lex->unit;
ha_rows idx= 0;
- Protocol *protocol=thd->protocol;
+ Protocol *protocol= thd->protocol;
unit->set_limit(sel);
- List_iterator<PROFILE> it(history);
- while ((prof= it++))
+ List_iterator<QUERY_PROFILE> it(history);
+ while ((prof= it++) != NULL)
{
+ String elapsed;
+
PROFILE_ENTRY *ps= &prof->profile_start;
PROFILE_ENTRY *pe= prof->profile_end;
@@ -406,8 +626,14 @@ bool PROFILING::show_profiles()
break;
protocol->prepare_for_resend();
- protocol->store((uint32)(prof->query_id));
- protocol->store((ulonglong)((pe->time - ps->time)/10));
+ protocol->store((uint32)(prof->profiling_query_id));
+ protocol->store((double)(pe->time_usecs - ps->time_usecs)/(1000.0*1000),
+ (uint32) TIME_FLOAT_DIGITS-1, &elapsed);
+ if (prof->query_source != NULL)
+ protocol->store(prof->query_source, strlen(prof->query_source),
+ system_charset_info);
+ else
+ protocol->store_null();
if (protocol->write())
DBUG_RETURN(TRUE);
@@ -416,18 +642,37 @@ bool PROFILING::show_profiles()
DBUG_RETURN(FALSE);
}
-bool PROFILING::show(uint options, uint query_id)
+/*
+ This is an awful hack to let prepared statements tell us the query
+ that they're executing.
+*/
+void PROFILING::set_query_source(char *query_source_arg, uint query_length_arg)
+{
+ DBUG_ENTER("PROFILING::set_query_source");
+
+ /* We can't get this query source through normal means. */
+ DBUG_ASSERT((thd->query == NULL) || (thd->query_length == 0));
+
+ if (current != NULL)
+ current->set_query_source(query_source_arg, query_length_arg);
+ else
+ DBUG_PRINT("info", ("no current profile to send query source to"));
+ DBUG_VOID_RETURN;
+}
+
+bool PROFILING::show(uint options, uint profiling_query_id)
{
DBUG_ENTER("PROFILING::show");
- PROFILE *prof;
+ QUERY_PROFILE *prof;
- List_iterator<PROFILE> it(history);
- while ((prof= it++))
+ List_iterator<QUERY_PROFILE> it(history);
+ while ((prof= it++) != NULL)
{
- if(prof->query_id == query_id)
- prof->show(options);
+ 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);
}
@@ -439,3 +684,130 @@ bool PROFILING::show_last(uint options)
}
DBUG_RETURN(TRUE);
}
+
+
+/**
+ Fill the information schema table, "query_profile", as defined in show.cc .
+*/
+int PROFILING::fill_statistics_info(THD *thd, struct st_table_list *tables, Item *cond)
+{
+ DBUG_ENTER("PROFILING::fill_statistics_info");
+ TABLE *table= tables->table;
+ ulonglong row_number= 0;
+
+ List_iterator<QUERY_PROFILE> query_it(history);
+ QUERY_PROFILE *query;
+ /* Go through each query in this thread's stored history... */
+ while ((query= query_it++) != NULL)
+ {
+ PROFILE_ENTRY *ps= &(query->profile_start);
+ double last_time= ps->time_usecs;
+#ifdef HAVE_GETRUSAGE
+ struct rusage *last_rusage= &(ps->rusage);
+#endif
+
+ /*
+ Because we put all profiling info into a table that may be reordered, let
+ us also include a numbering of each state per query. The query_id and
+ the "seq" together are unique.
+ */
+ ulonglong seq;
+
+ List_iterator<PROFILE_ENTRY> step_it(query->entries);
+ PROFILE_ENTRY *entry;
+ /* ...and for each query, go through all its state-change steps. */
+ for (seq= 0, entry= step_it++;
+ entry != NULL;
+#ifdef HAVE_GETRUSAGE
+ last_rusage= &(entry->rusage),
+#endif
+ seq++, last_time= entry->time_usecs, entry= step_it++, row_number++)
+ {
+ /* Set default values for this row. */
+ restore_record(table, s->default_values);
+
+ /*
+ The order of these fields is set by the query_profile_statistics_info
+ array.
+ */
+ table->field[0]->store((ulonglong) query->profiling_query_id);
+ table->field[1]->store((ulonglong) seq); /* the step in the sequence */
+ table->field[2]->store(entry->status, strlen(entry->status),
+ system_charset_info);
+ table->field[3]->store((double)(entry->time_usecs - last_time)/(1000*1000));
+
+#ifdef HAVE_GETRUSAGE
+ table->field[4]->store((double)RUSAGE_DIFF_USEC(entry->rusage.ru_utime,
+ last_rusage->ru_utime)/(1000.0*1000));
+ table->field[4]->null_ptr= NULL;
+ table->field[5]->store((double)RUSAGE_DIFF_USEC(entry->rusage.ru_stime,
+ last_rusage->ru_stime)/(1000.0*1000));
+
+ table->field[5]->null_ptr= NULL;
+#else
+ /* TODO: Add CPU-usage info for non-BSD systems */
+#endif
+
+#ifdef HAVE_GETRUSAGE
+ table->field[6]->store((uint32)(entry->rusage.ru_nvcsw - last_rusage->ru_nvcsw));
+ table->field[6]->null_ptr= NULL;
+ table->field[7]->store((uint32)(entry->rusage.ru_nivcsw - last_rusage->ru_nivcsw));
+ table->field[7]->null_ptr= NULL;
+#else
+ /* TODO: Add context switch info for non-BSD systems */
+#endif
+
+#ifdef HAVE_GETRUSAGE
+ table->field[8]->store((uint32)(entry->rusage.ru_inblock - last_rusage->ru_inblock));
+ table->field[8]->null_ptr= NULL;
+ table->field[9]->store((uint32)(entry->rusage.ru_oublock - last_rusage->ru_oublock));
+ table->field[9]->null_ptr= NULL;
+#else
+ /* TODO: Add block IO info for non-BSD systems */
+#endif
+
+#ifdef HAVE_GETRUSAGE
+ table->field[10]->store((uint32)(entry->rusage.ru_msgsnd - last_rusage->ru_msgsnd), true);
+ table->field[10]->null_ptr= NULL;
+ table->field[11]->store((uint32)(entry->rusage.ru_msgrcv - last_rusage->ru_msgrcv), true);
+ table->field[11]->null_ptr= NULL;
+#else
+ /* TODO: Add message info for non-BSD systems */
+#endif
+
+#ifdef HAVE_GETRUSAGE
+ table->field[12]->store((uint32)(entry->rusage.ru_majflt - last_rusage->ru_majflt), true);
+ table->field[12]->null_ptr= NULL;
+ table->field[13]->store((uint32)(entry->rusage.ru_minflt - last_rusage->ru_minflt), true);
+ table->field[13]->null_ptr= NULL;
+#else
+ /* TODO: Add page fault info for non-BSD systems */
+#endif
+
+#ifdef HAVE_GETRUSAGE
+ table->field[14]->store((uint32)(entry->rusage.ru_nswap - last_rusage->ru_nswap), true);
+ table->field[14]->null_ptr= NULL;
+#else
+ /* TODO: Add swap info for non-BSD systems */
+#endif
+
+ if ((entry->function != NULL) && (entry->file != NULL))
+ {
+ table->field[15]->store(entry->function, strlen(entry->function),
+ system_charset_info);
+ table->field[15]->null_ptr= NULL;
+ table->field[16]->store(entry->file, strlen(entry->file), system_charset_info);
+ table->field[16]->null_ptr= NULL;
+ table->field[17]->store(entry->line, true);
+ table->field[17]->null_ptr= NULL;
+ }
+
+ if (schema_table_store_record(thd, table))
+ DBUG_RETURN(1);
+
+ }
+ }
+
+ DBUG_RETURN(0);
+}
+#endif /* ENABLED_PROFILING */
diff --git a/sql/sql_profile.h b/sql/sql_profile.h
index 698a80f07e4..006760cab79 100644
--- a/sql/sql_profile.h
+++ b/sql/sql_profile.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 MySQL AB
+/* Copyright (C) 2007 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
@@ -14,99 +14,135 @@
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)
+#ifndef _SQL_PROFILE_H
+#define _SQL_PROFILE_H
+
+#if __STDC_VERSION__ < 199901L
+# if __GNUC__ >= 2
+# define __func__ __FUNCTION__
+# else
+# define __func__ _db_func_
+extern const char *_db_func_;
+# endif
+#elif defined(_MSC_VER)
+# if _MSC_VER < 1300
+# define __func__ _db_func_
+extern const char *_db_func_;
+# else
+# define __func__ __FUNCTION__
+# endif
+#elif defined(__BORLANDC__)
+# define __func__ __FUNC__
#else
-#define THD_PROC_INFO(thd, msg) do { (thd)->proc_info= (msg); } while (0)
+# define __func__ _db_func_
+extern const char *_db_func_;
#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 */
- };
+extern ST_FIELD_INFO query_profile_statistics_info[];
+int fill_query_profile_statistics_info(THD *thd, struct st_table_list *tables, Item *cond);
-#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
+#define PROFILE_CPU (1<<0)
+#define PROFILE_MEMORY (1<<1)
+#define PROFILE_BLOCK_IO (1<<2)
+#define PROFILE_CONTEXT (1<<3)
+#define PROFILE_PAGE_FAULTS (1<<4)
+#define PROFILE_IPC (1<<5)
+#define PROFILE_SWAPS (1<<6)
+#define PROFILE_SOURCE (1<<16)
+#define PROFILE_ALL (~0)
+
+
+#ifndef ENABLED_PROFILING
+
+# define thd_proc_info(thd, msg) do { (thd)->proc_info= (msg); } while (0)
+
+#else
+
+# define thd_proc_info(thd, msg) \
+ do { \
+ if (unlikely(((thd)->options & OPTION_PROFILING) != 0)) \
+ { \
+ (thd)->profiling.status_change((msg), __func__, __FILE__, __LINE__); \
+ } \
+ else \
+ { \
+ (thd)->proc_info= (msg); \
+ } \
+ } while (0)
+
+#include "mysql_priv.h"
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
class PROFILE_ENTRY;
-class PROFILE;
+class QUERY_PROFILE;
class PROFILING;
-/*
+
+/**
A single entry in a single profile.
*/
-
-class PROFILE_ENTRY: public Sql_alloc
+class PROFILE_ENTRY
{
-public:
- PROFILE *profile;
- char *status;
- ulonglong time;
+private:
+ friend class QUERY_PROFILE;
+ friend class PROFILING;
+
+ QUERY_PROFILE *profile;
+ char *status;
+#ifdef HAVE_GETRUSAGE
struct rusage rusage;
+#endif
char *function;
char *file;
unsigned int line;
+
+ double time_usecs;
+ char *allocated_status_memory;
+
+ void set_status(const char *status_arg, const char *function_arg,
+ const char *file_arg, unsigned int line_arg);
+ void clean_up();
PROFILE_ENTRY();
- PROFILE_ENTRY(PROFILE *profile_arg, const char *status_arg);
- PROFILE_ENTRY(PROFILE *profile_arg, const char *status_arg,
+ PROFILE_ENTRY(QUERY_PROFILE *profile_arg, const char *status_arg);
+ PROFILE_ENTRY(QUERY_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
+
+/**
+ The full profile for a single query, and includes multiple PROFILE_ENTRY
objects.
*/
-
-class PROFILE: public Sql_alloc
+class QUERY_PROFILE
{
-public:
+private:
+ friend class PROFILING;
+
PROFILING *profiling;
- query_id_t query_id;
+
+ query_id_t server_query_id; /* Global id. */
+ query_id_t profiling_query_id; /* Session-specific id. */
+ char *query_source;
PROFILE_ENTRY profile_start;
PROFILE_ENTRY *profile_end;
List<PROFILE_ENTRY> entries;
- PROFILE(PROFILING *profiling_arg);
- ~PROFILE();
+
+ QUERY_PROFILE(PROFILING *profiling_arg, char *query_source_arg, uint query_length_arg);
+ ~QUERY_PROFILE();
+
+ void set_query_source(char *query_source_arg, uint query_length_arg);
/* Add a profile status change to the current profile. */
void status(const char *status_arg,
@@ -120,68 +156,86 @@ public:
bool show(uint options);
};
-/*
- Profiling state for a single THD. Contains multiple PROFILE objects.
-*/
-class PROFILING: public Sql_alloc
+/**
+ Profiling state for a single THD; contains multiple QUERY_PROFILE objects.
+*/
+class PROFILING
{
-public:
- MEM_ROOT root;
+private:
+ friend class PROFILE_ENTRY;
+ friend class QUERY_PROFILE;
+
+ /*
+ Not the system query_id, but a counter unique to profiling.
+ */
+ query_id_t profile_id_counter;
+ MEM_ROOT mem_root;
THD *thd;
- bool enabled;
bool keeping;
- PROFILE *current;
- PROFILE *last;
- List<PROFILE> history;
+ QUERY_PROFILE *current;
+ QUERY_PROFILE *last;
+ List<QUERY_PROFILE> history;
+
+ query_id_t next_profile_id() { return(profile_id_counter++); }
+public:
PROFILING();
~PROFILING();
+ void set_query_source(char *query_source_arg, uint query_length_arg);
- 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; };
+ /** Reset the current profile and state of profiling for the next query. */
+ void reset();
- /*
+ /**
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.
+ 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; };
+ inline void keep() { keeping= true; };
- void status(const char *status_arg,
- const char *function_arg,
- const char *file_arg, unsigned int line_arg);
+ /**
+ Do we intend to keep the currently collected profile?
+ @see keep()
+ */
+ inline void discard() { keeping= false; };
- /* Stash this profile in the profile history. */
+ /**
+ Stash this profile in the profile history and remove the oldest
+ profile if the history queue is full, as defined by the
+ profiling_history_size system variable.
+ */
void store();
-
- /* Reset the current profile and state of profiling for the next query. */
- void reset();
+
+ /**
+ Called with every update of the status via thd_proc_info() , and is
+ therefore the main hook into the profiling code.
+ */
+ void status_change(const char *status_arg,
+ const char *function_arg,
+ const char *file_arg, unsigned int line_arg);
+
+ inline void set_thd(THD *thd_arg) { thd= thd_arg; };
/* SHOW PROFILES */
bool show_profiles();
/* SHOW PROFILE FOR QUERY query_id */
- bool show(uint options, uint 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);
};
-#endif /* SQL_PROFILE_H */
+# endif /* HAVE_PROFILING */
+#endif /* _SQL_PROFILE_H */
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 07ae439cfb9..11c4d4464d8 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -645,7 +645,7 @@ impossible position";
if (read_packet)
{
- thd->proc_info = "Sending binlog event to slave";
+ thd_proc_info(thd, "Sending binlog event to slave");
if (my_net_write(net, (char*)packet->ptr(), packet->length()) )
{
errmsg = "Failed on my_net_write()";
@@ -683,7 +683,7 @@ impossible position";
bool loop_breaker = 0;
/* need this to break out of the for loop from switch */
- thd->proc_info = "Finished reading one binlog; switching to next binlog";
+ thd_proc_info(thd, "Finished reading one binlog; switching to next binlog");
switch (mysql_bin_log.find_next_log(&linfo, 1)) {
case LOG_INFO_EOF:
loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK);
@@ -729,14 +729,14 @@ end:
(void)my_close(file, MYF(MY_WME));
send_eof(thd);
- thd->proc_info = "Waiting to finalize termination";
+ thd_proc_info(thd, "Waiting to finalize termination");
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN;
err:
- thd->proc_info = "Waiting to finalize termination";
+ thd_proc_info(thd, "Waiting to finalize termination");
end_io_cache(&log);
/*
Exclude iteration through thread list
@@ -888,7 +888,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
if (check_access(thd, SUPER_ACL, any_db,0,0,0,0))
return 1;
- thd->proc_info = "Killing slave";
+ thd_proc_info(thd, "Killing slave");
int thread_mask;
lock_slave_threads(mi);
// Get a mask of _running_ threads
@@ -915,7 +915,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
ER(ER_SLAVE_WAS_NOT_RUNNING));
}
unlock_slave_threads(mi);
- thd->proc_info = 0;
+ thd_proc_info(thd, 0);
if (slave_errno)
{
@@ -1071,7 +1071,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
DBUG_RETURN(TRUE);
}
- thd->proc_info = "Changing master";
+ thd_proc_info(thd, "Changing master");
LEX_MASTER_INFO* lex_mi= &thd->lex->mi;
// TODO: see if needs re-write
if (init_master_info(mi, master_info_file, relay_log_info_file, 0,
@@ -1196,7 +1196,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
if (need_relay_log_purge)
{
relay_log_purge= 1;
- THD_PROC_INFO(thd, "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))
@@ -1259,7 +1259,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
pthread_mutex_unlock(&mi->rli.data_lock);
unlock_slave_threads(mi);
- thd->proc_info = 0;
+ thd_proc_info(thd, 0);
send_ok(thd);
DBUG_RETURN(FALSE);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ada440fbc2d..c9e334b7784 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -598,7 +598,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");
+ 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 +745,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(thd, "statistics");
+ thd_proc_info(thd, "statistics");
if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) ||
thd->is_fatal_error)
{
@@ -755,7 +755,7 @@ JOIN::optimize()
/* Remove distinct if only const tables */
select_distinct= select_distinct && (const_tables != tables);
- THD_PROC_INFO(thd, "preparing");
+ thd_proc_info(thd, "preparing");
if (result->initialize_tables(this))
{
DBUG_PRINT("error",("Error: initialize_tables() failed"));
@@ -1162,7 +1162,7 @@ JOIN::optimize()
if (need_tmp)
{
DBUG_PRINT("info",("Creating tmp table"));
- THD_PROC_INFO(thd, "creating temporary table");
+ thd_proc_info(thd, "Creating tmp table");
init_items_ref_array();
@@ -1213,7 +1213,7 @@ JOIN::optimize()
if (group_list && simple_group)
{
DBUG_PRINT("info",("Sorting for group"));
- THD_PROC_INFO(thd, "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) ||
@@ -1234,9 +1234,8 @@ JOIN::optimize()
if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
{
- DBUG_PRINT("info",("Sorting for order"));
- THD_PROC_INFO(thd, "Sorting for order");
- if (create_sort_index(thd, this, order,
+ thd_proc_info(thd, "Sorting for order");
+ if (create_sort_index(thd, this, order,
HA_POS_ERROR, HA_POS_ERROR))
{
DBUG_RETURN(1);
@@ -1364,7 +1363,7 @@ JOIN::exec()
int tmp_error;
DBUG_ENTER("JOIN::exec");
- THD_PROC_INFO(thd, "executing");
+ thd_proc_info(thd, "executing");
error= 0;
if (procedure)
{
@@ -1504,7 +1503,7 @@ JOIN::exec()
curr_tmp_table= exec_tmp_table1;
/* Copy data to the temporary table */
- THD_PROC_INFO(thd, "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)))
{
@@ -1627,7 +1626,7 @@ JOIN::exec()
}
if (curr_join->group_list)
{
- THD_PROC_INFO(thd, "Creating sort index");
+ thd_proc_info(thd, "Creating sort index");
if (curr_join->join_tab == join_tab && save_join_tab())
{
DBUG_VOID_RETURN;
@@ -1641,7 +1640,7 @@ JOIN::exec()
sortorder= curr_join->sortorder;
}
- THD_PROC_INFO(thd, "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)
@@ -1697,7 +1696,7 @@ JOIN::exec()
curr_join->join_free(); /* Free quick selects */
if (curr_join->select_distinct && ! curr_join->group_list)
{
- THD_PROC_INFO(thd, "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,
@@ -1758,7 +1757,7 @@ JOIN::exec()
if (curr_join->group_list || curr_join->order)
{
DBUG_PRINT("info",("Sorting for send_fields"));
- THD_PROC_INFO(thd, "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)
@@ -1882,7 +1881,7 @@ JOIN::exec()
}
else
{
- THD_PROC_INFO(thd, "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),
@@ -2030,7 +2029,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
{
if (!(join= new JOIN(thd, fields, select_options, result)))
DBUG_RETURN(TRUE);
- THD_PROC_INFO(thd, "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,
@@ -2075,9 +2074,9 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
err:
if (free_join)
{
- THD_PROC_INFO(thd, "cleaning up");
+ thd_proc_info(thd, "end");
err|= select_lex->cleanup();
- THD_PROC_INFO(thd, "end");
+ thd_proc_info(thd, "end");
DBUG_RETURN(err || thd->net.report_error);
}
DBUG_RETURN(join->error);
@@ -9807,7 +9806,7 @@ free_tmp_table(THD *thd, TABLE *entry)
DBUG_PRINT("enter",("table: %s",entry->alias));
save_proc_info=thd->proc_info;
- THD_PROC_INFO(thd, "removing tmp table");
+ thd_proc_info(thd, "removing tmp table");
if (entry->file)
{
@@ -9835,7 +9834,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(thd, save_proc_info);
+ thd_proc_info(thd, save_proc_info);
DBUG_VOID_RETURN;
}
@@ -9865,7 +9864,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
DBUG_RETURN(1); // End of memory
save_proc_info=thd->proc_info;
- THD_PROC_INFO(thd, "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))
@@ -9918,8 +9917,8 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
table->s= &table->share_not_to_be_used;
table->file->change_table_ptr(table);
if (save_proc_info)
- THD_PROC_INFO(thd, (!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:
@@ -9931,7 +9930,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
new_table.file->delete_table(new_table.s->table_name);
delete new_table.file;
err2:
- THD_PROC_INFO(thd, save_proc_info);
+ thd_proc_info(thd, save_proc_info);
DBUG_RETURN(1);
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 0a39640aa4f..133bee1c481 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -44,7 +44,7 @@ static void
append_algorithm(TABLE_LIST *table, String *buff);
static int
view_store_create_info(THD *thd, TABLE_LIST *table, String *buff);
-static bool schema_table_store_record(THD *thd, TABLE *table);
+bool schema_table_store_record(THD *thd, TABLE *table);
/***************************************************************************
@@ -1349,7 +1349,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
if (pthread_kill(tmp->real_id,0))
- THD_PROC_INFO(tmp, "*** 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;
@@ -1847,7 +1847,7 @@ typedef struct st_index_field_values
1 error
*/
-static bool schema_table_store_record(THD *thd, TABLE *table)
+bool schema_table_store_record(THD *thd, TABLE *table)
{
int error;
if ((error= table->file->write_row(table->record[0])))
@@ -4305,6 +4305,8 @@ ST_SCHEMA_TABLE schema_tables[]=
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0},
{"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},
{"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,
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 43fdd693a4b..dc474c080b4 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1729,7 +1729,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
}
}
- THD_PROC_INFO(thd, "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)
@@ -1760,7 +1760,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
end:
VOID(pthread_mutex_unlock(&LOCK_open));
- THD_PROC_INFO(thd, "After create");
+ thd_proc_info(thd, "After create");
DBUG_RETURN(error);
warn:
@@ -2879,7 +2879,7 @@ mysql_discard_or_import_tablespace(THD *thd,
ALTER TABLE
*/
- THD_PROC_INFO(thd, "discard_or_import_tablespace");
+ thd_proc_info(thd, "discard_or_import_tablespace");
discard= test(tablespace_op == DISCARD_TABLESPACE);
@@ -2896,7 +2896,7 @@ mysql_discard_or_import_tablespace(THD *thd,
error=table->file->discard_or_import_tablespace(discard);
- THD_PROC_INFO(thd, "end");
+ thd_proc_info(thd, "end");
if (error)
goto err;
@@ -3007,7 +3007,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
frm_type_enum frm_type;
DBUG_ENTER("mysql_alter_table");
- THD_PROC_INFO(thd, "init");
+ thd_proc_info(thd, "init");
table_name=table_list->table_name;
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
@@ -3142,7 +3142,7 @@ view_err:
DBUG_RETURN(TRUE);
}
- THD_PROC_INFO(thd, "setup");
+ thd_proc_info(thd, "setup");
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
!table->s->tmp_table) // no need to touch frm
{
@@ -3173,7 +3173,7 @@ view_err:
if (!error && (new_name != table_name || new_db != db))
{
- THD_PROC_INFO(thd, "rename");
+ thd_proc_info(thd, "rename");
/* Then do a 'simple' rename of the table */
if (!access(new_name_buff,F_OK))
{
@@ -3627,7 +3627,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(thd, "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)
@@ -3711,7 +3711,7 @@ view_err:
from the cache, free all locks, close the old table and remove it.
*/
- THD_PROC_INFO(thd, "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)
@@ -3822,7 +3822,7 @@ view_err:
broadcast_refresh();
goto err;
}
- THD_PROC_INFO(thd, "end");
+ thd_proc_info(thd, "end");
if (mysql_bin_log.is_open())
{
thd->clear_error();
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 0fdadd9e0db..62be615d3f6 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -166,7 +166,7 @@ int mysql_update(THD *thd,
mysql_handle_derived(thd->lex, &mysql_derived_filling)))
DBUG_RETURN(1);
- THD_PROC_INFO(thd, "init");
+ thd_proc_info(thd, "init");
table= table_list->table;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@@ -358,7 +358,7 @@ int mysql_update(THD *thd,
else
init_read_record_idx(&info, thd, table, 1, used_index);
- THD_PROC_INFO(thd, "Searching rows for update");
+ thd_proc_info(thd, "Searching rows for update");
uint tmp_limit= limit;
while (!(error=info.read_record(&info)) && !thd->killed)
@@ -423,7 +423,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(thd, "Updating");
+ thd_proc_info(thd, "Updating");
query_id=thd->query_id;
transactional_table= table->file->has_transactions();
@@ -511,7 +511,7 @@ int mysql_update(THD *thd,
end_read_record(&info);
free_io_cache(table); // If ORDER BY
delete select;
- THD_PROC_INFO(thd, "end");
+ thd_proc_info(thd, "end");
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
/*
@@ -959,7 +959,7 @@ int multi_update::prepare(List<Item> &not_used_values,
thd->count_cuted_fields= CHECK_FIELD_WARN;
thd->cuted_fields=0L;
- THD_PROC_INFO(thd, "updating main table");
+ thd_proc_info(thd, "updating main table");
tables_to_update= get_table_map(fields);
@@ -1511,11 +1511,11 @@ err2:
bool multi_update::send_eof()
{
char buff[STRING_BUFFER_USUAL_SIZE];
- THD_PROC_INFO(thd, "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(thd, "end");
+ thd_proc_info(thd, "end");
/* We must invalidate the query cache before binlog writing and
ha_autocommit_... */
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index c03dd1f782e..c570c0e6570 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -588,7 +588,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
DBUG_RETURN(0);
err:
- THD_PROC_INFO(thd, "end");
+ thd_proc_info(thd, "end");
lex->link_first_table_back(view, link_to_local);
unit->cleanup();
DBUG_RETURN(res || thd->net.report_error);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 3372cfb3341..20c51360d51 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -928,7 +928,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
union_opt select_derived_init option_type2
%type <ulong_num>
- ulong_num raid_types merge_insert_types opt_profile_query_arg
+ ulong_num raid_types merge_insert_types
%type <ulonglong_number>
ulonglong_num
@@ -6678,36 +6678,52 @@ profile_defs:
profile_def:
CPU_SYM
- { Lex->profile_options|= PROFILE_CPU; }
+ {
+ Lex->profile_options|= PROFILE_CPU;
+ }
| MEMORY_SYM
- { Lex->profile_options|= PROFILE_MEMORY; }
+ {
+ Lex->profile_options|= PROFILE_MEMORY;
+ }
| BLOCK_SYM IO_SYM
- { Lex->profile_options|= PROFILE_BLOCK_IO; }
+ {
+ Lex->profile_options|= PROFILE_BLOCK_IO;
+ }
| CONTEXT_SYM SWITCHES_SYM
- { Lex->profile_options|= PROFILE_CONTEXT; }
+ {
+ Lex->profile_options|= PROFILE_CONTEXT;
+ }
| PAGE_SYM FAULTS_SYM
- { Lex->profile_options|= PROFILE_PAGE_FAULTS; }
+ {
+ Lex->profile_options|= PROFILE_PAGE_FAULTS;
+ }
| IPC_SYM
- { Lex->profile_options|= PROFILE_IPC; }
+ {
+ Lex->profile_options|= PROFILE_IPC;
+ }
| SWAPS_SYM
- { Lex->profile_options|= PROFILE_SWAPS; }
+ {
+ Lex->profile_options|= PROFILE_SWAPS;
+ }
| SOURCE_SYM
- { Lex->profile_options|= PROFILE_SOURCE; }
+ {
+ Lex->profile_options|= PROFILE_SOURCE;
+ }
| ALL
- { Lex->profile_options|= PROFILE_ALL; }
- ;
-
-opt_profile_query_arg:
- /* empty */
- { $$= 0; }
- | QUERY_SYM NUM
- { $$= atoi($2.str); }
+ {
+ Lex->profile_options|= PROFILE_ALL;
+ }
;
opt_profile_args:
/* empty */
- | FOR_SYM opt_profile_query_arg
- { Lex->profile_query_id = $2; }
+ {
+ Lex->profile_query_id= 0;
+ }
+ | FOR_SYM QUERY_SYM NUM
+ {
+ Lex->profile_query_id= atoi($3.str);
+ }
;
/* Show things */
@@ -7940,7 +7956,7 @@ keyword_sp:
| BERKELEY_DB_SYM {}
| BINLOG_SYM {}
| BIT_SYM {}
- | BLOCK_SYM {}
+ | BLOCK_SYM {}
| BOOL_SYM {}
| BOOLEAN_SYM {}
| BTREE_SYM {}
@@ -7957,8 +7973,8 @@ keyword_sp:
| COMPRESSED_SYM {}
| CONCURRENT {}
| CONSISTENT_SYM {}
- | CONTEXT_SYM {}
- | CPU_SYM {}
+ | CONTEXT_SYM {}
+ | CPU_SYM {}
| CUBE_SYM {}
| DATA_SYM {}
| DATETIME {}
@@ -7981,7 +7997,7 @@ keyword_sp:
| EXPANSION_SYM {}
| EXTENDED_SYM {}
| FAST_SYM {}
- | FAULTS_SYM {}
+ | FAULTS_SYM {}
| FOUND_SYM {}
| DISABLE_SYM {}
| ENABLE_SYM {}
@@ -8006,8 +8022,8 @@ keyword_sp:
| ISSUER_SYM {}
| INNOBASE_SYM {}
| INSERT_METHOD {}
- | IO_SYM {}
- | IPC_SYM {}
+ | IO_SYM {}
+ | IPC_SYM {}
| RELAY_THREAD {}
| LAST_SYM {}
| LEAVES {}
@@ -8037,7 +8053,7 @@ keyword_sp:
| MAX_UPDATES_PER_HOUR {}
| MAX_USER_CONNECTIONS_SYM {}
| MEDIUM_SYM {}
- | MEMORY_SYM {}
+ | MEMORY_SYM {}
| MERGE_SYM {}
| MICROSECOND_SYM {}
| MIGRATE_SYM {}
@@ -8064,7 +8080,7 @@ keyword_sp:
| ONE_SHOT_SYM {}
| ONE_SYM {}
| PACK_KEYS_SYM {}
- | PAGE_SYM {}
+ | PAGE_SYM {}
| PARTIAL {}
| PASSWORD {}
| PHASE_SYM {}
@@ -8074,8 +8090,8 @@ keyword_sp:
| PRIVILEGES {}
| PROCESS {}
| PROCESSLIST_SYM {}
- | PROFILE_SYM {}
- | PROFILES_SYM {}
+ | PROFILE_SYM {}
+ | PROFILES_SYM {}
| QUARTER_SYM {}
| QUERY_SYM {}
| QUICK {}
@@ -8109,7 +8125,7 @@ keyword_sp:
| SHUTDOWN {}
| SNAPSHOT_SYM {}
| SOUNDS_SYM {}
- | SOURCE_SYM {}
+ | SOURCE_SYM {}
| SQL_CACHE_SYM {}
| SQL_BUFFER_RESULT {}
| SQL_NO_CACHE_SYM {}
@@ -8121,8 +8137,8 @@ keyword_sp:
| SUBJECT_SYM {}
| SUPER_SYM {}
| SUSPEND_SYM {}
- | SWAPS_SYM {}
- | SWITCHES_SYM {}
+ | SWAPS_SYM {}
+ | SWITCHES_SYM {}
| TABLES {}
| TABLESPACE {}
| TEMPORARY {}
diff --git a/sql/table.h b/sql/table.h
index 70e64439af5..da0f2a48b10 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -308,6 +308,7 @@ enum enum_schema_tables
SCH_COLUMN_PRIVILEGES,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
+ SCH_PROFILING,
SCH_PROCEDURES,
SCH_SCHEMATA,
SCH_SCHEMA_PRIVILEGES,